summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/lib/sifp/sss_sifp.c437
-rw-r--r--src/lib/sifp/sss_sifp_attrs.c259
-rw-r--r--src/lib/sifp/sss_sifp_dbus.c192
-rw-r--r--src/lib/sifp/sss_sifp_parser.c536
-rw-r--r--src/lib/sifp/sss_sifp_private.h115
-rw-r--r--src/lib/sifp/sss_sifp_utils.c117
6 files changed, 1656 insertions, 0 deletions
diff --git a/src/lib/sifp/sss_sifp.c b/src/lib/sifp/sss_sifp.c
new file mode 100644
index 000000000..0bf29075e
--- /dev/null
+++ b/src/lib/sifp/sss_sifp.c
@@ -0,0 +1,437 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@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 <dbus/dbus.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lib/sifp/sss_sifp.h"
+#include "lib/sifp/sss_sifp_dbus.h"
+#include "lib/sifp/sss_sifp_private.h"
+
+#define DBUS_IFACE_PROP "org.freedesktop.DBus.Properties"
+
+static void * default_alloc(size_t size, void *pvt)
+{
+ return malloc(size);
+}
+
+static void default_free(void *ptr, void *pvt)
+{
+ free(ptr);
+}
+
+static DBusMessage * sss_sifp_create_prop_msg(const char *object_path,
+ const char *method)
+{
+ return sss_sifp_create_message(object_path, DBUS_IFACE_PROP, method);
+}
+
+sss_sifp_error
+sss_sifp_init(sss_sifp_ctx **_ctx)
+{
+ return sss_sifp_init_ex(NULL, default_alloc, default_free, _ctx);
+}
+
+sss_sifp_error
+sss_sifp_init_ex(void *alloc_pvt,
+ sss_sifp_alloc_func *alloc_func,
+ sss_sifp_free_func *free_func,
+ sss_sifp_ctx **_ctx)
+{
+ sss_sifp_ctx *ctx = NULL;
+ DBusConnection *conn = NULL;
+ DBusError dbus_error;
+ sss_sifp_error ret;
+
+ if (_ctx == NULL || alloc_func == NULL || free_func == NULL) {
+ return SSS_SIFP_INVALID_ARGUMENT;
+ }
+
+ dbus_error_init(&dbus_error);
+
+ ctx = alloc_func(sizeof(sss_sifp_ctx), alloc_pvt);
+ if (ctx == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ ctx->conn = NULL;
+ ctx->alloc_fn = alloc_func;
+ ctx->free_fn = free_func;
+ ctx->alloc_pvt = alloc_pvt;
+ ctx->io_error = alloc_func(sizeof(DBusError), alloc_pvt);
+ if (ctx->io_error == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ dbus_error_init(ctx->io_error);
+
+ conn = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error);
+ if (dbus_error_is_set(&dbus_error)) {
+ sss_sifp_set_io_error(ctx, &dbus_error);
+ ret = SSS_SIFP_IO_ERROR;
+ goto done;
+ }
+
+ ctx->conn = conn;
+ *_ctx = ctx;
+
+ ret = SSS_SIFP_OK;
+
+done:
+ if (ret != SSS_SIFP_OK) {
+ sss_sifp_free(&ctx);
+ }
+
+ dbus_error_free(&dbus_error);
+ return ret;
+}
+
+const char *
+sss_sifp_get_last_io_error_name(sss_sifp_ctx *ctx)
+{
+ if (ctx == NULL) {
+ return "Invalid sss_sifp context";
+ }
+
+ if (!dbus_error_is_set(ctx->io_error)) {
+ return NULL;
+ }
+
+ return ctx->io_error->name;
+}
+
+const char *
+sss_sifp_get_last_io_error_message(sss_sifp_ctx *ctx)
+{
+ if (ctx == NULL) {
+ return "Invalid sss_sifp context";
+ }
+
+ if (!dbus_error_is_set(ctx->io_error)) {
+ return NULL;
+ }
+
+ return ctx->io_error->message;
+}
+
+sss_sifp_error
+sss_sifp_fetch_attr(sss_sifp_ctx *ctx,
+ const char *object_path,
+ const char *interface,
+ const char *name,
+ sss_sifp_attr ***_attrs)
+{
+ DBusMessage *msg = NULL;
+ DBusMessage *reply = NULL;
+ dbus_bool_t bret;
+ sss_sifp_error ret;
+
+ if (ctx == NULL || object_path == NULL || interface == NULL
+ || name == NULL || _attrs == NULL) {
+ return SSS_SIFP_INVALID_ARGUMENT;
+ }
+
+ /* Message format:
+ * In: string:interface
+ * In: string:attribute
+ * Out: variant(misc:value)
+ */
+
+ msg = sss_sifp_create_prop_msg(object_path, "Get");
+ if (msg == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ bret = dbus_message_append_args(msg, DBUS_TYPE_STRING, &interface,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_INVALID);
+ if (!bret) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ ret = sss_sifp_send_message(ctx, msg, &reply);
+ if (ret != SSS_SIFP_OK) {
+ goto done;
+ }
+
+ ret = sss_sifp_parse_attr(ctx, name, reply, _attrs);
+
+done:
+ if (msg != NULL) {
+ dbus_message_unref(msg);
+ }
+
+ if (reply != NULL) {
+ dbus_message_unref(reply);
+ }
+
+ return ret;
+}
+
+sss_sifp_error
+sss_sifp_fetch_all_attrs(sss_sifp_ctx *ctx,
+ const char *object_path,
+ const char *interface,
+ sss_sifp_attr ***_attrs)
+{
+ DBusMessage *msg = NULL;
+ DBusMessage *reply = NULL;
+ dbus_bool_t bret;
+ sss_sifp_error ret;
+
+ if (ctx == NULL || object_path == NULL || interface == NULL
+ || _attrs == NULL) {
+ return SSS_SIFP_INVALID_ARGUMENT;
+ }
+
+ msg = sss_sifp_create_prop_msg(object_path, "GetAll");
+ if (msg == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ bret = dbus_message_append_args(msg, DBUS_TYPE_STRING, &interface,
+ DBUS_TYPE_INVALID);
+ if (!bret) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ ret = sss_sifp_send_message(ctx, msg, &reply);
+ if (ret != SSS_SIFP_OK) {
+ goto done;
+ }
+
+ ret = sss_sifp_parse_attr_list(ctx, reply, _attrs);
+
+done:
+ if (msg != NULL) {
+ dbus_message_unref(msg);
+ }
+
+ if (reply != NULL) {
+ dbus_message_unref(reply);
+ }
+
+ return ret;
+}
+
+sss_sifp_error
+sss_sifp_fetch_object(sss_sifp_ctx *ctx,
+ const char *object_path,
+ const char *interface,
+ sss_sifp_object **_object)
+{
+ sss_sifp_object *object = NULL;
+ sss_sifp_attr **attrs = NULL;
+ const char *name = NULL;
+ sss_sifp_error ret;
+
+ if (ctx == NULL || object_path == NULL || interface == NULL
+ || _object == NULL) {
+ return SSS_SIFP_INVALID_ARGUMENT;
+ }
+
+ ret = sss_sifp_fetch_all_attrs(ctx, object_path, interface, &attrs);
+ if (ret != SSS_SIFP_OK) {
+ goto done;
+ }
+
+ ret = sss_sifp_find_attr_as_string(attrs, "name", &name);
+ if (ret != SSS_SIFP_OK) {
+ goto done;
+ }
+
+ object = _alloc_zero(ctx, sss_sifp_object, 1);
+ if (object == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ object->attrs = attrs;
+
+ object->name = sss_sifp_strdup(ctx, name);
+ if (object->name == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ object->object_path = sss_sifp_strdup(ctx, object_path);
+ if (object->object_path == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ object->interface = sss_sifp_strdup(ctx, interface);
+ if (object->interface == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ *_object = object;
+
+ ret = SSS_SIFP_OK;
+
+done:
+ if (ret != SSS_SIFP_OK) {
+ sss_sifp_free_object(ctx, &object);
+ }
+
+ return ret;
+}
+
+void
+sss_sifp_free(sss_sifp_ctx **_ctx)
+{
+ sss_sifp_ctx *ctx = NULL;
+
+ if (_ctx == NULL || *_ctx == NULL) {
+ return;
+ }
+
+ ctx = *_ctx;
+
+ if (ctx->conn != NULL) {
+ dbus_connection_unref(ctx->conn);
+ }
+
+ if (ctx->io_error != NULL) {
+ dbus_error_free(ctx->io_error);
+ _free(ctx, ctx->io_error);
+ }
+
+ _free(ctx, ctx);
+ *_ctx = NULL;
+
+ return;
+}
+
+void
+sss_sifp_free_attrs(sss_sifp_ctx *ctx,
+ sss_sifp_attr ***_attrs)
+{
+ sss_sifp_attr **attrs = NULL;
+ unsigned int i, j;
+
+ if (_attrs == NULL || *_attrs == NULL) {
+ return;
+ }
+
+ attrs = *_attrs;
+
+ for (i = 0; attrs[i] != NULL; i++) {
+ switch (attrs[i]->type) {
+ case SSS_SIFP_ATTR_TYPE_BOOL:
+ _free(ctx, attrs[i]->data.boolean);
+ break;
+ case SSS_SIFP_ATTR_TYPE_INT16:
+ _free(ctx, attrs[i]->data.int16);
+ break;
+ case SSS_SIFP_ATTR_TYPE_UINT16:
+ _free(ctx, attrs[i]->data.uint16);
+ break;
+ case SSS_SIFP_ATTR_TYPE_INT32:
+ _free(ctx, attrs[i]->data.int32);
+ break;
+ case SSS_SIFP_ATTR_TYPE_UINT32:
+ _free(ctx, attrs[i]->data.uint32);
+ break;
+ case SSS_SIFP_ATTR_TYPE_INT64:
+ _free(ctx, attrs[i]->data.int64);
+ break;
+ case SSS_SIFP_ATTR_TYPE_UINT64:
+ _free(ctx, attrs[i]->data.uint64);
+ break;
+ case SSS_SIFP_ATTR_TYPE_STRING:
+ for (j = 0; j < attrs[i]->num_values; j++) {
+ _free(ctx, attrs[i]->data.str[j]);
+ }
+ _free(ctx, attrs[i]->data.str);
+ break;
+ }
+ _free(ctx, attrs[i]->name);
+ _free(ctx, attrs[i]);
+ }
+
+ _free(ctx, attrs);
+
+ *_attrs = NULL;
+}
+
+void
+sss_sifp_free_object(sss_sifp_ctx *ctx,
+ sss_sifp_object **_object)
+{
+ sss_sifp_object *object = NULL;
+
+ if (_object == NULL || *_object == NULL) {
+ return;
+ }
+
+ object = *_object;
+
+ sss_sifp_free_attrs(ctx, &object->attrs);
+ _free(ctx, object->object_path);
+ _free(ctx, object->interface);
+ _free(ctx, object->name);
+ _free(ctx, object);
+
+ *_object = NULL;
+}
+
+void
+sss_sifp_free_string(sss_sifp_ctx *ctx,
+ char **_str)
+{
+ if (_str == NULL || *_str == NULL) {
+ return;
+ }
+
+ _free(ctx, *_str);
+
+ *_str = NULL;
+}
+
+void
+sss_sifp_free_string_array(sss_sifp_ctx *ctx,
+ char ***_str_array)
+{
+ char **str_array = NULL;
+ int i;
+
+ if (_str_array == NULL || *_str_array == NULL) {
+ return;
+ }
+
+ str_array = *_str_array;
+
+ for (i = 0; str_array[i] != NULL; i++) {
+ _free(ctx, str_array[i]);
+ }
+
+ _free(ctx, str_array);
+
+ *_str_array = NULL;
+}
diff --git a/src/lib/sifp/sss_sifp_attrs.c b/src/lib/sifp/sss_sifp_attrs.c
new file mode 100644
index 000000000..8e871b2e6
--- /dev/null
+++ b/src/lib/sifp/sss_sifp_attrs.c
@@ -0,0 +1,259 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@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 <string.h>
+
+#include "lib/sifp/sss_sifp.h"
+#include "lib/sifp/sss_sifp_private.h"
+
+#define GET_ATTR(attrs, name, rtype, field, out) do { \
+ sss_sifp_attr *attr = sss_sifp_find_attr(attrs, name); \
+ \
+ if (attr == NULL) { \
+ return SSS_SIFP_ATTR_MISSING; \
+ } \
+ \
+ if (attr->type != rtype) { \
+ return SSS_SIFP_INCORRECT_TYPE; \
+ } \
+ \
+ if (attr->data.field == NULL) { \
+ return SSS_SIFP_ATTR_NULL; \
+ } \
+ \
+ out = attr->data.field[0]; \
+} while (0)
+
+#define GET_ATTR_ARRAY(attrs, name, rtype, field, out_num, out_val) do { \
+ sss_sifp_attr *attr = sss_sifp_find_attr(attrs, name); \
+ \
+ if (attr == NULL) { \
+ return SSS_SIFP_ATTR_MISSING; \
+ } \
+ \
+ if (attr->type != rtype) { \
+ return SSS_SIFP_INCORRECT_TYPE; \
+ } \
+ \
+ if (attr->data.field == NULL) { \
+ return SSS_SIFP_ATTR_NULL; \
+ } \
+ \
+ out_num = attr->num_values; \
+ out_val = attr->data.field; \
+} while (0)
+
+static sss_sifp_attr *sss_sifp_find_attr(sss_sifp_attr **attrs,
+ const char *name)
+{
+ int i;
+
+ if (attrs == NULL || name == NULL) {
+ return NULL;
+ }
+
+ for (i = 0; attrs[i] != NULL; i++) {
+ if (strcmp(attrs[i]->name, name) == 0) {
+ return attrs[i];
+ }
+ }
+
+ return NULL;
+}
+
+sss_sifp_error
+sss_sifp_find_attr_as_bool(sss_sifp_attr **attrs,
+ const char *name,
+ bool *_value)
+{
+ GET_ATTR(attrs, name, SSS_SIFP_ATTR_TYPE_BOOL, boolean, *_value);
+ return SSS_SIFP_OK;
+}
+
+sss_sifp_error
+sss_sifp_find_attr_as_int16(sss_sifp_attr **attrs,
+ const char *name,
+ int16_t *_value)
+{
+ GET_ATTR(attrs, name, SSS_SIFP_ATTR_TYPE_INT16, int16, *_value);
+ return SSS_SIFP_OK;
+}
+
+sss_sifp_error
+sss_sifp_find_attr_as_uint16(sss_sifp_attr **attrs,
+ const char *name,
+ uint16_t *_value)
+{
+ GET_ATTR(attrs, name, SSS_SIFP_ATTR_TYPE_UINT16, uint16, *_value);
+ return SSS_SIFP_OK;
+}
+
+sss_sifp_error
+sss_sifp_find_attr_as_int32(sss_sifp_attr **attrs,
+ const char *name,
+ int32_t *_value)
+{
+ GET_ATTR(attrs, name, SSS_SIFP_ATTR_TYPE_INT32, int32, *_value);
+ return SSS_SIFP_OK;
+}
+
+sss_sifp_error
+sss_sifp_find_attr_as_uint32(sss_sifp_attr **attrs,
+ const char *name,
+ uint32_t *_value)
+{
+ GET_ATTR(attrs, name, SSS_SIFP_ATTR_TYPE_UINT32, uint32, *_value);
+ return SSS_SIFP_OK;
+}
+
+sss_sifp_error
+sss_sifp_find_attr_as_int64(sss_sifp_attr **attrs,
+ const char *name,
+ int64_t *_value)
+{
+ GET_ATTR(attrs, name, SSS_SIFP_ATTR_TYPE_INT64, int64, *_value);
+ return SSS_SIFP_OK;
+}
+
+sss_sifp_error
+sss_sifp_find_attr_as_uint64(sss_sifp_attr **attrs,
+ const char *name,
+ uint64_t *_value)
+{
+ GET_ATTR(attrs, name, SSS_SIFP_ATTR_TYPE_UINT64, uint64, *_value);
+ return SSS_SIFP_OK;
+}
+
+sss_sifp_error
+sss_sifp_find_attr_as_string(sss_sifp_attr **attrs,
+ const char *name,
+ const char **_value)
+{
+ const char *value = NULL;
+
+ GET_ATTR(attrs, name, SSS_SIFP_ATTR_TYPE_STRING, str, value);
+
+ if (value == NULL) {
+ return SSS_SIFP_ATTR_NULL;
+ }
+
+ *_value = value;
+ return SSS_SIFP_OK;
+}
+
+/**
+ * @brief Find attribute in list and return its values.
+ *
+ * @param[in] attrs Attributes
+ * @param[in] name Name of the attribute to find
+ *
+ * @return Attribute values or NULL if it is not found.
+ */
+sss_sifp_error
+sss_sifp_find_attr_as_bool_array(sss_sifp_attr **attrs,
+ const char *name,
+ unsigned int *_num_values,
+ bool **_value)
+{
+ GET_ATTR_ARRAY(attrs, name, SSS_SIFP_ATTR_TYPE_BOOL, boolean,
+ *_num_values, *_value);
+ return SSS_SIFP_OK;
+}
+
+sss_sifp_error
+sss_sifp_find_attr_as_int16_array(sss_sifp_attr **attrs,
+ const char *name,
+ unsigned int *_num_values,
+ int16_t **_value)
+{
+ GET_ATTR_ARRAY(attrs, name, SSS_SIFP_ATTR_TYPE_INT16, int16,
+ *_num_values, *_value);
+ return SSS_SIFP_OK;
+}
+
+sss_sifp_error
+sss_sifp_find_attr_as_uint16_array(sss_sifp_attr **attrs,
+ const char *name,
+ unsigned int *_num_values,
+ uint16_t **_value)
+{
+ GET_ATTR_ARRAY(attrs, name, SSS_SIFP_ATTR_TYPE_UINT16, uint16,
+ *_num_values, *_value);
+ return SSS_SIFP_OK;
+}
+
+sss_sifp_error
+sss_sifp_find_attr_as_int32_array(sss_sifp_attr **attrs,
+ const char *name,
+ unsigned int *_num_values,
+ int32_t **_value)
+{
+ GET_ATTR_ARRAY(attrs, name, SSS_SIFP_ATTR_TYPE_INT32, int32,
+ *_num_values, *_value);
+ return SSS_SIFP_OK;
+}
+
+sss_sifp_error
+sss_sifp_find_attr_as_uint32_array(sss_sifp_attr **attrs,
+ const char *name,
+ unsigned int *_num_values,
+ uint32_t **_value)
+{
+ GET_ATTR_ARRAY(attrs, name, SSS_SIFP_ATTR_TYPE_UINT32, uint32,
+ *_num_values, *_value);
+ return SSS_SIFP_OK;
+}
+
+sss_sifp_error
+sss_sifp_find_attr_as_int64_array(sss_sifp_attr **attrs,
+ const char *name,
+ unsigned int *_num_values,
+ int64_t **_value)
+{
+ GET_ATTR_ARRAY(attrs, name, SSS_SIFP_ATTR_TYPE_INT64, int64,
+ *_num_values, *_value);
+ return SSS_SIFP_OK;
+}
+
+sss_sifp_error
+sss_sifp_find_attr_as_uint64_array(sss_sifp_attr **attrs,
+ const char *name,
+ unsigned int *_num_values,
+ uint64_t **_value)
+{
+ GET_ATTR_ARRAY(attrs, name, SSS_SIFP_ATTR_TYPE_UINT64, uint64,
+ *_num_values, *_value);
+ return SSS_SIFP_OK;
+}
+
+sss_sifp_error
+sss_sifp_find_attr_as_string_array(sss_sifp_attr **attrs,
+ const char *name,
+ unsigned int *_num_values,
+ const char * const **_value)
+{
+ char **value;
+
+ GET_ATTR_ARRAY(attrs, name, SSS_SIFP_ATTR_TYPE_STRING, str,
+ *_num_values, value);
+ *_value = (const char * const *)value;
+
+ return SSS_SIFP_OK;
+}
diff --git a/src/lib/sifp/sss_sifp_dbus.c b/src/lib/sifp/sss_sifp_dbus.c
new file mode 100644
index 000000000..d9813718b
--- /dev/null
+++ b/src/lib/sifp/sss_sifp_dbus.c
@@ -0,0 +1,192 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@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 <dbus/dbus.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lib/sifp/sss_sifp.h"
+#include "lib/sifp/sss_sifp_dbus.h"
+#include "lib/sifp/sss_sifp_private.h"
+
+static sss_sifp_error sss_sifp_ifp_call(sss_sifp_ctx *ctx,
+ const char *method,
+ int first_arg_type,
+ va_list ap,
+ DBusMessage **_reply)
+{
+ DBusMessage *msg = NULL;
+ sss_sifp_error ret;
+
+ msg = sss_sifp_create_message(SSS_SIFP_PATH_IFP, SSS_SIFP_IFACE_IFP, method);
+ if (msg == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ if (first_arg_type != DBUS_TYPE_INVALID) {
+ dbus_message_append_args_valist(msg, first_arg_type, ap);
+ }
+
+ ret = sss_sifp_send_message(ctx, msg, _reply);
+
+done:
+ if (msg != NULL) {
+ dbus_message_unref(msg);
+ }
+
+ return ret;
+}
+
+DBusMessage *
+sss_sifp_create_message(const char *object_path,
+ const char *interface,
+ const char *method)
+{
+ return dbus_message_new_method_call(SSS_SIFP_IFP, object_path,
+ interface, method);
+}
+
+sss_sifp_error
+sss_sifp_send_message(sss_sifp_ctx *ctx,
+ DBusMessage *msg,
+ DBusMessage **_reply)
+{
+ return sss_sifp_send_message_ex(ctx, msg, 5000, _reply);
+}
+
+sss_sifp_error
+sss_sifp_send_message_ex(sss_sifp_ctx *ctx,
+ DBusMessage *msg,
+ int timeout,
+ DBusMessage **_reply)
+{
+ DBusMessage *reply = NULL;
+ DBusError dbus_error;
+ sss_sifp_error ret;
+
+ if (ctx == NULL || msg == NULL) {
+ return SSS_SIFP_INVALID_ARGUMENT;
+ }
+
+ dbus_error_init(&dbus_error);
+
+ reply = dbus_connection_send_with_reply_and_block(ctx->conn, msg,
+ timeout, &dbus_error);
+ if (dbus_error_is_set(&dbus_error)) {
+ sss_sifp_set_io_error(ctx, &dbus_error);
+ ret = SSS_SIFP_IO_ERROR;
+ goto done;
+ }
+
+ if (_reply == NULL) {
+ dbus_message_unref(reply);
+ } else {
+ *_reply = reply;
+ }
+
+ ret = SSS_SIFP_OK;
+
+done:
+ dbus_error_free(&dbus_error);
+ return ret;
+}
+
+sss_sifp_error
+sss_sifp_invoke_list(sss_sifp_ctx *ctx,
+ const char *method,
+ char ***_object_paths,
+ int first_arg_type,
+ ...)
+{
+ DBusMessage *reply = NULL;
+ char *dbus_method = NULL;
+ sss_sifp_error ret;
+ va_list ap;
+
+ if (ctx == NULL || method == NULL || _object_paths == NULL) {
+ return SSS_SIFP_INVALID_ARGUMENT;
+ }
+
+ dbus_method = sss_sifp_strcat(ctx, "List", method);
+ if (dbus_method == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ va_start(ap, first_arg_type);
+ ret = sss_sifp_ifp_call(ctx, dbus_method, first_arg_type, ap, &reply);
+ va_end(ap);
+ if (ret != SSS_SIFP_OK) {
+ goto done;
+ }
+
+ ret = sss_sifp_parse_object_path_list(ctx, reply, _object_paths);
+
+done:
+ sss_sifp_free_string(ctx, &dbus_method);
+
+ if (reply != NULL) {
+ dbus_message_unref(reply);
+ }
+
+ return ret;
+}
+
+sss_sifp_error
+sss_sifp_invoke_find(sss_sifp_ctx *ctx,
+ const char *method,
+ char **_object_path,
+ int first_arg_type,
+ ...)
+{
+ DBusMessage *reply = NULL;
+ char *dbus_method = NULL;
+ sss_sifp_error ret;
+ va_list ap;
+
+ if (ctx == NULL || method == NULL || _object_path == NULL) {
+ return SSS_SIFP_INVALID_ARGUMENT;
+ }
+
+ dbus_method = sss_sifp_strcat(ctx, "Find", method);
+ if (dbus_method == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ va_start(ap, first_arg_type);
+ ret = sss_sifp_ifp_call(ctx, dbus_method, first_arg_type, ap, &reply);
+ va_end(ap);
+ if (ret != SSS_SIFP_OK) {
+ goto done;
+ }
+
+ ret = sss_sifp_parse_object_path(ctx, reply, _object_path);
+
+done:
+ sss_sifp_free_string(ctx, &dbus_method);
+
+ if (reply != NULL) {
+ dbus_message_unref(reply);
+ }
+
+ return ret;
+}
diff --git a/src/lib/sifp/sss_sifp_parser.c b/src/lib/sifp/sss_sifp_parser.c
new file mode 100644
index 000000000..1c1ff80c8
--- /dev/null
+++ b/src/lib/sifp/sss_sifp_parser.c
@@ -0,0 +1,536 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@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 <dbus/dbus.h>
+#include <string.h>
+
+#include "lib/sifp/sss_sifp.h"
+#include "lib/sifp/sss_sifp_private.h"
+
+#define check_dbus_arg(iter, type, ret, done) do { \
+ if (dbus_message_iter_get_arg_type((iter)) != (type)) { \
+ ret = SSS_SIFP_INTERNAL_ERROR; \
+ goto done; \
+ } \
+} while (0)
+
+#define parse_basic(ctx, iter, ret, attr_type, dbus_type, \
+ data_type, field, done) \
+do { \
+ dbus_type val; \
+ dbus_message_iter_get_basic(iter, &val); \
+ attr->type = attr_type; \
+ attr->data.field = _alloc_zero(ctx, data_type, 1); \
+ \
+ if (attr->data.field == NULL) { \
+ ret = SSS_SIFP_OUT_OF_MEMORY; \
+ goto done; \
+ } \
+ \
+ attr->data.field[0] = val; \
+ attr->num_values = 1; \
+ \
+ ret = SSS_SIFP_OK; \
+} while (0)
+
+#define parse_array(ctx, iter, ret, attr_type, dbus_type, \
+ data_type, field, done) \
+do { \
+ dbus_type val; \
+ unsigned int i; \
+ \
+ attr->type = attr_type; \
+ if (attr->num_values == 0) { \
+ attr->data.field = NULL; \
+ ret = SSS_SIFP_OK; \
+ goto done; \
+ } \
+ \
+ attr->data.field = _alloc_zero(ctx, data_type, attr->num_values); \
+ if (attr->data.field == NULL) { \
+ ret = SSS_SIFP_OUT_OF_MEMORY; \
+ goto done; \
+ } \
+ \
+ for (i = 0; i < attr->num_values; i++) { \
+ dbus_message_iter_get_basic(iter, &val); \
+ attr->data.field[i] = val; \
+ \
+ if (!dbus_message_iter_next(iter) && i + 1 < attr->num_values) { \
+ ret = SSS_SIFP_INTERNAL_ERROR; \
+ goto done; \
+ } \
+ } \
+ \
+ ret = SSS_SIFP_OK; \
+} while (0)
+
+static unsigned int
+sss_sifp_get_array_length(DBusMessageIter *iter)
+{
+ DBusMessageIter array_iter;
+ unsigned int size;
+
+ dbus_message_iter_recurse(iter, &array_iter);
+
+ if (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_INVALID) {
+ return 0;
+ }
+
+ size = 0;
+ do {
+ size++;
+ } while (dbus_message_iter_next(&array_iter));
+
+ return size;
+}
+
+static sss_sifp_error
+sss_sifp_parse_basic(sss_sifp_ctx *ctx,
+ DBusMessageIter *iter,
+ sss_sifp_attr *attr)
+{
+ sss_sifp_error ret;
+
+ switch (dbus_message_iter_get_arg_type(iter)) {
+ case DBUS_TYPE_BOOLEAN:
+ parse_basic(ctx, iter, ret, SSS_SIFP_ATTR_TYPE_BOOL,
+ dbus_bool_t, bool, boolean, done);
+ break;
+ case DBUS_TYPE_INT16:
+ parse_basic(ctx, iter, ret, SSS_SIFP_ATTR_TYPE_INT16,
+ int16_t, int16_t, int16, done);
+ break;
+ case DBUS_TYPE_UINT16:
+ parse_basic(ctx, iter, ret, SSS_SIFP_ATTR_TYPE_UINT16,
+ uint16_t, uint16_t, uint16, done);
+ break;
+ case DBUS_TYPE_INT32:
+ parse_basic(ctx, iter, ret, SSS_SIFP_ATTR_TYPE_INT32,
+ int32_t, int32_t, int32, done);
+ break;
+ case DBUS_TYPE_UINT32:
+ parse_basic(ctx, iter, ret, SSS_SIFP_ATTR_TYPE_UINT32,
+ uint32_t, uint32_t, uint32, done);
+ break;
+ case DBUS_TYPE_INT64:
+ parse_basic(ctx, iter, ret, SSS_SIFP_ATTR_TYPE_INT64,
+ int64_t, int64_t, int64, done);
+ break;
+ case DBUS_TYPE_UINT64:
+ parse_basic(ctx, iter, ret, SSS_SIFP_ATTR_TYPE_UINT64,
+ uint64_t, uint64_t, uint64, done);
+ break;
+ case DBUS_TYPE_STRING:
+ case DBUS_TYPE_OBJECT_PATH: ;
+ const char *val = NULL;
+
+ dbus_message_iter_get_basic(iter, &val);
+
+ attr->type = SSS_SIFP_ATTR_TYPE_STRING;
+ attr->data.str = _alloc_zero(ctx, char*, 1);
+ if (attr->data.str == NULL) { \
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ attr->data.str[0] = sss_sifp_strdup(ctx, val);
+ if (attr->data.str[0] == NULL) {
+ _free(ctx, attr->data.str);
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ attr->num_values = 1;
+
+ ret = SSS_SIFP_OK;
+ break;
+ default:
+ ret = SSS_SIFP_INVALID_ARGUMENT;
+ break;
+ }
+
+done:
+ return ret;
+}
+
+static sss_sifp_error
+sss_sifp_parse_array(sss_sifp_ctx *ctx,
+ DBusMessageIter *iter,
+ sss_sifp_attr *attr)
+{
+ DBusMessageIter array_iter;
+ sss_sifp_error ret;
+
+ attr->num_values = sss_sifp_get_array_length(iter);
+ dbus_message_iter_recurse(iter, &array_iter);
+
+ switch (dbus_message_iter_get_element_type(iter)) {
+ case DBUS_TYPE_BOOLEAN:
+ parse_array(ctx, &array_iter, ret, SSS_SIFP_ATTR_TYPE_BOOL,
+ dbus_bool_t, bool, boolean, done);
+ break;
+ case DBUS_TYPE_INT16:
+ parse_array(ctx, &array_iter, ret, SSS_SIFP_ATTR_TYPE_INT16,
+ int16_t, int16_t, int16, done);
+ break;
+ case DBUS_TYPE_UINT16:
+ parse_array(ctx, &array_iter, ret, SSS_SIFP_ATTR_TYPE_UINT16,
+ uint16_t, uint16_t, uint16, done);
+ break;
+ case DBUS_TYPE_INT32:
+ parse_array(ctx, &array_iter, ret, SSS_SIFP_ATTR_TYPE_INT32,
+ int32_t, int32_t, int32, done);
+ break;
+ case DBUS_TYPE_UINT32:
+ parse_array(ctx, &array_iter, ret, SSS_SIFP_ATTR_TYPE_UINT32,
+ uint32_t, uint32_t, uint32, done);
+ break;
+ case DBUS_TYPE_INT64:
+ parse_array(ctx, &array_iter, ret, SSS_SIFP_ATTR_TYPE_INT64,
+ int64_t, int64_t, int64, done);
+ break;
+ case DBUS_TYPE_UINT64:
+ parse_array(ctx, &array_iter, ret, SSS_SIFP_ATTR_TYPE_UINT64,
+ uint64_t, uint64_t, uint64, done);
+ break;
+ case DBUS_TYPE_STRING:
+ case DBUS_TYPE_OBJECT_PATH: ;
+ const char *val;
+ unsigned int i;
+
+ attr->type = SSS_SIFP_ATTR_TYPE_STRING;
+ if (attr->num_values == 0) {
+ attr->data.str = NULL;
+ ret = SSS_SIFP_OK;
+ goto done;
+ }
+
+ attr->data.str = _alloc_zero(ctx, char *, attr->num_values);
+ if (attr->data.str == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ for (i = 0; i < attr->num_values; i++) {
+ dbus_message_iter_get_basic(&array_iter, &val);
+ attr->data.str[i] = sss_sifp_strdup(ctx, val);
+ if (attr->data.str[i] == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ if (!dbus_message_iter_next(&array_iter)
+ && i + 1 < attr->num_values) {
+ ret = SSS_SIFP_INTERNAL_ERROR;
+ goto done;
+ }
+ }
+
+ ret = SSS_SIFP_OK;
+ break;
+ default:
+ ret = SSS_SIFP_INVALID_ARGUMENT;
+ break;
+ }
+
+done:
+ if (ret != SSS_SIFP_OK && attr->type == SSS_SIFP_ATTR_TYPE_STRING
+ && attr->data.str != NULL) {
+ unsigned int i;
+ for (i = 0; attr->data.str[i] != NULL && i < attr->num_values; i++) {
+ _free(ctx, attr->data.str[i]);
+ }
+ _free(ctx, attr->data.str);
+ }
+
+ return ret;
+}
+
+static sss_sifp_error
+sss_sifp_parse_variant(sss_sifp_ctx *ctx,
+ DBusMessageIter *iter,
+ sss_sifp_attr *attr)
+{
+ DBusMessageIter variant_iter;
+ sss_sifp_error ret;
+ int type;
+
+ check_dbus_arg(iter, DBUS_TYPE_VARIANT, ret, done);
+
+ dbus_message_iter_recurse(iter, &variant_iter);
+
+ type = dbus_message_iter_get_arg_type(&variant_iter);
+ if (dbus_type_is_basic(type)) {
+ ret = sss_sifp_parse_basic(ctx, &variant_iter, attr);
+ } else {
+ /* container types */
+ switch (type) {
+ case DBUS_TYPE_ARRAY:
+ ret = sss_sifp_parse_array(ctx, &variant_iter, attr);;
+ break;
+ default:
+ ret = SSS_SIFP_NOT_SUPPORTED;
+ break;
+ }
+ }
+
+done:
+ return ret;
+}
+
+/**
+ * DBusMessage format:
+ * variant:value
+ *
+ * Iterator has to point to the variant but not inside the variant.
+ */
+static sss_sifp_error
+sss_sifp_parse_single_attr(sss_sifp_ctx *ctx,
+ const char *name,
+ DBusMessageIter *iter,
+ sss_sifp_attr **_attr)
+{
+ sss_sifp_attr *attr = NULL;
+ sss_sifp_error ret;
+
+ attr = _alloc_zero(ctx, sss_sifp_attr, 1);
+ if (attr == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ attr->name = sss_sifp_strdup(ctx, name);
+ if (attr->name == NULL) {
+ _free(ctx, attr);
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ ret = sss_sifp_parse_variant(ctx, iter, attr);
+ if (ret != SSS_SIFP_OK) {
+ _free(ctx, attr->name);
+ _free(ctx, attr);
+ }
+
+ *_attr = attr;
+
+done:
+ return ret;
+}
+
+/**
+ * DBusMessage format:
+ * variant:value
+ */
+sss_sifp_error
+sss_sifp_parse_attr(sss_sifp_ctx *ctx,
+ const char *name,
+ DBusMessage *msg,
+ sss_sifp_attr ***_attrs)
+{
+ sss_sifp_attr **attrs = NULL;
+ DBusMessageIter iter;
+ sss_sifp_error ret;
+
+ dbus_message_iter_init(msg, &iter);
+
+ attrs = _alloc_zero(ctx, sss_sifp_attr *, 2);
+ if (attrs == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ ret = sss_sifp_parse_single_attr(ctx, name, &iter, &attrs[0]);
+ if (ret != SSS_SIFP_OK) {
+ goto done;
+ }
+
+ *_attrs = attrs;
+
+ ret = SSS_SIFP_OK;
+
+done:
+ if (ret != SSS_SIFP_OK) {
+ sss_sifp_free_attrs(ctx, &attrs);
+ }
+
+ return ret;
+}
+
+/**
+ * DBusMessage format:
+ * array of dict_entry(string:attr_name, variant:value)
+ */
+sss_sifp_error
+sss_sifp_parse_attr_list(sss_sifp_ctx *ctx,
+ DBusMessage *msg,
+ sss_sifp_attr ***_attrs)
+{
+ DBusMessageIter iter;
+ DBusMessageIter array_iter;
+ DBusMessageIter dict_iter;
+ sss_sifp_attr **attrs = NULL;
+ const char *name = NULL;
+ unsigned int num_values;
+ sss_sifp_error ret;
+ unsigned int i;
+
+ dbus_message_iter_init(msg, &iter);
+
+ check_dbus_arg(&iter, DBUS_TYPE_ARRAY, ret, done);
+
+ if (dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
+ ret = SSS_SIFP_INTERNAL_ERROR;
+ goto done;
+ }
+
+ num_values = sss_sifp_get_array_length(&iter);
+ attrs = _alloc_zero(ctx, sss_sifp_attr *, num_values + 1);
+ if (attrs == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ dbus_message_iter_recurse(&iter, &array_iter);
+
+ for (i = 0; i < num_values; i++) {
+ dbus_message_iter_recurse(&array_iter, &dict_iter);
+
+ /* get the key */
+ check_dbus_arg(&dict_iter, DBUS_TYPE_STRING, ret, done);
+ dbus_message_iter_get_basic(&dict_iter, &name);
+
+ if (!dbus_message_iter_next(&dict_iter)) {
+ ret = SSS_SIFP_INTERNAL_ERROR;
+ goto done;
+ }
+
+ /* now read the value */
+ check_dbus_arg(&dict_iter, DBUS_TYPE_VARIANT, ret, done);
+
+ ret = sss_sifp_parse_single_attr(ctx, name, &dict_iter, &attrs[i]);
+ if (ret != SSS_SIFP_OK) {
+ goto done;
+ }
+
+ dbus_message_iter_next(&array_iter);
+ }
+
+ *_attrs = attrs;
+ ret = SSS_SIFP_OK;
+
+done:
+ if (ret != SSS_SIFP_OK) {
+ sss_sifp_free_attrs(ctx, &attrs);
+ }
+
+ return ret;
+}
+
+sss_sifp_error
+sss_sifp_parse_object_path(sss_sifp_ctx *ctx,
+ DBusMessage *msg,
+ char **_object_path)
+{
+ char *object_path = NULL;
+ const char *dbus_path = NULL;
+ DBusError dbus_error;
+ dbus_bool_t bret;
+ sss_sifp_error ret;
+
+ dbus_error_init(&dbus_error);
+
+ bret = dbus_message_get_args(msg, &dbus_error,
+ DBUS_TYPE_OBJECT_PATH, &dbus_path,
+ DBUS_TYPE_INVALID);
+ if (!bret) {
+ sss_sifp_set_io_error(ctx, &dbus_error);
+ ret = SSS_SIFP_IO_ERROR;
+ goto done;
+ }
+
+ object_path = sss_sifp_strdup(ctx, dbus_path);
+ if (object_path == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ *_object_path = object_path;
+ ret = SSS_SIFP_OK;
+
+done:
+ dbus_error_free(&dbus_error);
+
+ return ret;
+}
+
+sss_sifp_error
+sss_sifp_parse_object_path_list(sss_sifp_ctx *ctx,
+ DBusMessage *msg,
+ char ***_object_paths)
+{
+ char **object_paths = NULL;
+ char **dbus_paths = NULL;
+ int num_paths;
+ DBusError dbus_error;
+ dbus_bool_t bret;
+ sss_sifp_error ret;
+ int i;
+
+ dbus_error_init(&dbus_error);
+
+ bret = dbus_message_get_args(msg, &dbus_error,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH,
+ &dbus_paths, &num_paths,
+ DBUS_TYPE_INVALID);
+ if (!bret) {
+ sss_sifp_set_io_error(ctx, &dbus_error);
+ ret = SSS_SIFP_IO_ERROR;
+ goto done;
+ }
+
+ object_paths = _alloc_zero(ctx, char *, num_paths + 1);
+ if (object_paths == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ for (i = 0; i < num_paths; i++) {
+ object_paths[i] = sss_sifp_strdup(ctx, dbus_paths[i]);
+ if (object_paths[i] == NULL) {
+ ret = SSS_SIFP_OUT_OF_MEMORY;
+ goto done;
+ }
+ }
+
+ *_object_paths = object_paths;
+ ret = SSS_SIFP_OK;
+
+done:
+ dbus_error_free(&dbus_error);
+ dbus_free_string_array(dbus_paths);
+
+ if (ret != SSS_SIFP_OK && object_paths != NULL) {
+ sss_sifp_free_string_array(ctx, &object_paths);
+ }
+
+ return ret;
+}
diff --git a/src/lib/sifp/sss_sifp_private.h b/src/lib/sifp/sss_sifp_private.h
new file mode 100644
index 000000000..0f21e4a97
--- /dev/null
+++ b/src/lib/sifp/sss_sifp_private.h
@@ -0,0 +1,115 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@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/>.
+*/
+
+#ifndef SSS_SIFP_PRIVATE_H_
+#define SSS_SIFP_PRIVATE_H_
+
+#define SSS_SIFP_PATH_IFP "/org/freedesktop/sssd/infopipe"
+
+#include <dbus/dbus.h>
+#include "lib/sifp/sss_sifp.h"
+
+void *sss_sifp_alloc_zero(sss_sifp_ctx *ctx, size_t size, size_t num);
+
+#define _alloc_zero(ctx, type, num) sss_sifp_alloc_zero(ctx, sizeof(type), num)
+
+#define _free(ctx, var) \
+ do { \
+ ctx->free_fn((var), ctx->alloc_pvt); \
+ (var) = NULL; \
+ } while (0)
+
+struct sss_sifp_ctx {
+ DBusConnection *conn;
+ sss_sifp_alloc_func *alloc_fn;
+ sss_sifp_free_func *free_fn;
+ void *alloc_pvt;
+
+ DBusError *io_error;
+};
+
+enum sss_sifp_attr_type {
+ SSS_SIFP_ATTR_TYPE_BOOL,
+ SSS_SIFP_ATTR_TYPE_INT16,
+ SSS_SIFP_ATTR_TYPE_UINT16,
+ SSS_SIFP_ATTR_TYPE_INT32,
+ SSS_SIFP_ATTR_TYPE_UINT32,
+ SSS_SIFP_ATTR_TYPE_INT64,
+ SSS_SIFP_ATTR_TYPE_UINT64,
+ SSS_SIFP_ATTR_TYPE_STRING
+};
+
+/**
+ * D-Bus object attribute
+ */
+struct sss_sifp_attr {
+ char *name;
+ enum sss_sifp_attr_type type;
+ unsigned int num_values;
+ union {
+ bool *boolean;
+ int16_t *int16;
+ uint16_t *uint16;
+ int32_t *int32;
+ uint32_t *uint32;
+ int64_t *int64;
+ uint64_t *uint64;
+ char **str;
+ } data;
+};
+
+void
+sss_sifp_set_io_error(sss_sifp_ctx *ctx,
+ DBusError *error);
+
+const char *
+sss_sifp_get_iface_for_object(const char *object_path);
+
+char *
+sss_sifp_strdup(sss_sifp_ctx *ctx,
+ const char *str);
+
+char *
+sss_sifp_strcat(sss_sifp_ctx *ctx,
+ const char *str1,
+ const char *str2);
+
+sss_sifp_error
+sss_sifp_parse_attr(sss_sifp_ctx *ctx,
+ const char *name,
+ DBusMessage *msg,
+ sss_sifp_attr ***_attrs);
+
+sss_sifp_error
+sss_sifp_parse_attr_list(sss_sifp_ctx *ctx,
+ DBusMessage *msg,
+ sss_sifp_attr ***_attrs);
+
+sss_sifp_error
+sss_sifp_parse_object_path(sss_sifp_ctx *ctx,
+ DBusMessage *msg,
+ char **_object_path);
+
+sss_sifp_error
+sss_sifp_parse_object_path_list(sss_sifp_ctx *ctx,
+ DBusMessage *msg,
+ char ***_object_paths);
+
+#endif /* SSS_SIFP_PRIVATE_H_ */
diff --git a/src/lib/sifp/sss_sifp_utils.c b/src/lib/sifp/sss_sifp_utils.c
new file mode 100644
index 000000000..29cde7ef5
--- /dev/null
+++ b/src/lib/sifp/sss_sifp_utils.c
@@ -0,0 +1,117 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@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 <dbus/dbus.h>
+#include <string.h>
+
+#include "lib/sifp/sss_sifp.h"
+#include "lib/sifp/sss_sifp_private.h"
+
+void *sss_sifp_alloc_zero(sss_sifp_ctx *ctx, size_t size, size_t num)
+{
+ void *addr = ctx->alloc_fn(size * num, ctx->alloc_pvt);
+
+ if (addr == NULL) {
+ return NULL;
+ }
+
+ memset(addr, '\0', size * num);
+
+ return addr;
+}
+
+void sss_sifp_set_io_error(sss_sifp_ctx *ctx, DBusError *error)
+{
+ dbus_error_free(ctx->io_error);
+ dbus_error_init(ctx->io_error);
+ dbus_set_error(ctx->io_error, error->name, error->message);
+}
+
+const char *
+sss_sifp_get_iface_for_object(const char *object_path)
+{
+ int i;
+ const char *path;
+ static struct {
+ const char *path;
+ const char *iface;
+ } known_types[] = {
+ {SSS_SIFP_PATH_IFP "/Components/", SSS_SIFP_IFACE_COMPONENTS},
+ {SSS_SIFP_PATH_IFP "/Domains/", SSS_SIFP_IFACE_DOMAINS},
+ {SSS_SIFP_PATH_IFP "/Services/", SSS_SIFP_IFACE_SERVICES},
+ {SSS_SIFP_PATH_IFP "/Users/", SSS_SIFP_IFACE_USERS},
+ {SSS_SIFP_PATH_IFP "/Groups/", SSS_SIFP_IFACE_GROUPS},
+ {NULL, NULL}
+ };
+
+ for (i = 0; known_types[i].path != NULL; i++) {
+ path = known_types[i].path;
+ if (strncmp(path, object_path, strlen(path)) == 0) {
+ return known_types[i].iface;
+ }
+ }
+
+ return NULL;
+}
+
+char * sss_sifp_strdup(sss_sifp_ctx *ctx, const char *str)
+{
+ char *result = NULL;
+ size_t str_len;
+
+ if (str == NULL) {
+ return NULL;
+ }
+
+ str_len = strlen(str);
+ result = _alloc_zero(ctx, char, str_len + 1);
+ if (result == NULL) {
+ return NULL;
+ }
+
+ strncpy(result, str, str_len);
+
+ return result;
+}
+
+char * sss_sifp_strcat(sss_sifp_ctx *ctx, const char *str1, const char *str2)
+{
+ char *result = NULL;
+
+ if (str1 == NULL) {
+ return sss_sifp_strdup(ctx, str2);
+ }
+
+ if (str2 == NULL) {
+ return sss_sifp_strdup(ctx, str1);
+ }
+
+ size_t len = strlen(str1) + strlen(str2) + 1;
+
+ result = _alloc_zero(ctx, char, len);
+ if (result == NULL) {
+ return NULL;
+ }
+
+ strcat(result, str1);
+ strcat(result, str2);
+
+ return result;
+}