summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Březina <pbrezina@redhat.com>2015-05-20 14:14:53 +0200
committerJakub Hrozek <jhrozek@redhat.com>2015-06-18 16:44:07 +0200
commitf7adbb15dbdcb79e291f7cf361a400ce25f7b382 (patch)
tree44581d061f7c2ee1a1e00e24820c1be88654b990
parentc5184e9eeb0fd0bc4749677d2f74256515199b46 (diff)
downloadsssd-f7adbb15dbdcb79e291f7cf361a400ce25f7b382.tar.gz
sssd-f7adbb15dbdcb79e291f7cf361a400ce25f7b382.tar.xz
sssd-f7adbb15dbdcb79e291f7cf361a400ce25f7b382.zip
SBUS: Add support for <node /> in introspection
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-rw-r--r--src/sbus/sssd_dbus.h10
-rw-r--r--src/sbus/sssd_dbus_connection.c7
-rw-r--r--src/sbus/sssd_dbus_interface.c115
-rw-r--r--src/sbus/sssd_dbus_introspect.c41
-rw-r--r--src/sbus/sssd_dbus_private.h11
-rw-r--r--src/tests/sbus_tests.c2
6 files changed, 181 insertions, 5 deletions
diff --git a/src/sbus/sssd_dbus.h b/src/sbus/sssd_dbus.h
index 61c18ae28..818070fa5 100644
--- a/src/sbus/sssd_dbus.h
+++ b/src/sbus/sssd_dbus.h
@@ -80,6 +80,10 @@ typedef void (*sbus_conn_reconn_callback_fn)(struct sbus_connection *, int, void
*/
typedef int (*sbus_server_conn_init_fn)(struct sbus_connection *, void *);
+typedef const char ** (* sbus_nodes_fn)(TALLOC_CTX *mem_ctx,
+ const char *path,
+ void *data);
+
enum {
SBUS_CONN_TYPE_PRIVATE = 1,
SBUS_CONN_TYPE_SHARED,
@@ -177,6 +181,12 @@ int sbus_conn_register_iface(struct sbus_connection *conn,
const char *object_path,
void *handler_data);
+void
+sbus_conn_register_nodes(struct sbus_connection *conn,
+ const char *path,
+ sbus_nodes_fn nodes_fn,
+ void *data);
+
errno_t
sbus_conn_reregister_paths(struct sbus_connection *conn);
diff --git a/src/sbus/sssd_dbus_connection.c b/src/sbus/sssd_dbus_connection.c
index 8ff279c1b..d0df95bb2 100644
--- a/src/sbus/sssd_dbus_connection.c
+++ b/src/sbus/sssd_dbus_connection.c
@@ -168,6 +168,13 @@ int sbus_init_connection(TALLOC_CTX *ctx,
return EIO;
}
+ ret = sbus_nodes_hash_init(conn, conn, &conn->nodes_fns);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create node functions hash table\n");
+ talloc_free(conn);
+ return EIO;
+ }
+
ret = sss_hash_create(conn, 32, &conn->clients);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create clients hash table\n");
diff --git a/src/sbus/sssd_dbus_interface.c b/src/sbus/sssd_dbus_interface.c
index 1651478a8..f8046c7c1 100644
--- a/src/sbus/sssd_dbus_interface.c
+++ b/src/sbus/sssd_dbus_interface.c
@@ -732,6 +732,106 @@ done:
return ret;
}
+errno_t
+sbus_nodes_hash_init(TALLOC_CTX *mem_ctx,
+ struct sbus_connection *conn,
+ hash_table_t **_table)
+{
+ return sss_hash_create_ex(mem_ctx, 10, _table, 0, 0, 0, 0,
+ NULL, conn);
+}
+
+struct sbus_nodes_data {
+ sbus_nodes_fn nodes_fn;
+ void *handler_data;
+};
+
+static errno_t
+sbus_nodes_hash_add(hash_table_t *table,
+ const char *object_path,
+ sbus_nodes_fn nodes_fn,
+ void *handler_data)
+{
+ TALLOC_CTX *tmp_ctx;
+ struct sbus_nodes_data *data;
+ hash_key_t key;
+ hash_value_t value;
+ errno_t ret;
+ bool has_key;
+ int hret;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ return ENOMEM;
+ }
+
+ key.type = HASH_KEY_STRING;
+ key.str = talloc_strdup(tmp_ctx, object_path);
+ if (key.str == NULL) {
+ return ENOMEM;
+ }
+
+ has_key = hash_has_key(table, &key);
+ if (has_key) {
+ ret = EEXIST;
+ goto done;
+ }
+
+ data = talloc_zero(tmp_ctx, struct sbus_nodes_data);
+ if (data == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ data->handler_data = handler_data;
+ data->nodes_fn = nodes_fn;
+
+ value.type = HASH_VALUE_PTR;
+ value.ptr = data;
+
+ hret = hash_enter(table, &key, &value);
+ if (hret != HASH_SUCCESS) {
+ ret = EIO;
+ goto done;
+ }
+
+ talloc_steal(table, key.str);
+ talloc_steal(table, data);
+
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+const char **
+sbus_nodes_hash_lookup(TALLOC_CTX *mem_ctx,
+ hash_table_t *table,
+ const char *object_path)
+{
+ struct sbus_nodes_data *data;
+ hash_key_t key;
+ hash_value_t value;
+ int hret;
+
+ key.type = HASH_KEY_STRING;
+ key.str = discard_const(object_path);
+
+ hret = hash_lookup(table, &key, &value);
+ if (hret == HASH_ERROR_KEY_NOT_FOUND) {
+ return NULL;
+ } else if (hret != HASH_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Unable to search hash table: hret=%d\n", hret);
+ return NULL;
+ }
+
+ data = talloc_get_type(value.ptr, struct sbus_nodes_data);
+
+ return data->nodes_fn(mem_ctx, object_path, data->handler_data);
+}
+
static struct sbus_interface *
sbus_new_interface(TALLOC_CTX *mem_ctx,
const char *object_path,
@@ -870,6 +970,21 @@ sbus_conn_register_iface(struct sbus_connection *conn,
return ret;
}
+void
+sbus_conn_register_nodes(struct sbus_connection *conn,
+ const char *path,
+ sbus_nodes_fn nodes_fn,
+ void *data)
+{
+ errno_t ret;
+
+ ret = sbus_nodes_hash_add(conn->nodes_fns, path, nodes_fn, data);
+ if (ret != EOK && ret != EEXIST) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Unable to register node function with "
+ "%s. Introspection may not work correctly.\n", path);
+ }
+}
+
errno_t
sbus_conn_reregister_paths(struct sbus_connection *conn)
{
diff --git a/src/sbus/sssd_dbus_introspect.c b/src/sbus/sssd_dbus_introspect.c
index 34279c8d4..a66432dd9 100644
--- a/src/sbus/sssd_dbus_introspect.c
+++ b/src/sbus/sssd_dbus_introspect.c
@@ -34,7 +34,7 @@
"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n" \
" \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
-#define FMT_NODE "<node>\n"
+#define FMT_NODE "<node name=\"%s\">\n"
#define FMT_IFACE " <interface name=\"%s\">\n"
#define FMT_METHOD " <method name=\"%s\">\n"
#define FMT_METHOD_NOARG " <method name=\"%s\" />\n"
@@ -46,6 +46,7 @@
#define FMT_SIGNAL_CLOSE " </signal>\n"
#define FMT_PROPERTY " <property name=\"%s\" type=\"%s\" access=\"%s\" />\n"
#define FMT_IFACE_CLOSE " </interface>\n"
+#define FMT_CHILD_NODE " <node name=\"%s\" />\n"
#define FMT_NODE_CLOSE "</node>\n"
#define WRITE_OR_FAIL(file, ret, label, fmt, ...) do { \
@@ -294,8 +295,31 @@ done:
return ret;
}
+static int
+sbus_introspect_generate_nodes(FILE *file, const char **nodes)
+{
+ int ret;
+ int i;
+
+ if (nodes == NULL) {
+ return EOK;
+ }
+
+ for (i = 0; nodes[i] != NULL; i++) {
+ WRITE_OR_FAIL(file, ret, done, FMT_CHILD_NODE, nodes[i]);
+ }
+
+ ret = EOK;
+
+done:
+ return ret;
+}
+
static char *
-sbus_introspect_generate(TALLOC_CTX *mem_ctx, struct sbus_interface_list *list)
+sbus_introspect_generate(TALLOC_CTX *mem_ctx,
+ const char *node,
+ const char **nodes,
+ struct sbus_interface_list *list)
{
struct sbus_interface_list *item;
char *introspect = NULL;
@@ -310,7 +334,7 @@ sbus_introspect_generate(TALLOC_CTX *mem_ctx, struct sbus_interface_list *list)
}
WRITE_OR_FAIL(memstream, ret, done, FMT_DOCTYPE);
- WRITE_OR_FAIL(memstream, ret, done, FMT_NODE);
+ WRITE_OR_FAIL(memstream, ret, done, FMT_NODE, node);
DLIST_FOR_EACH(item, list) {
ret = sbus_introspect_generate_iface(memstream, item->interface);
@@ -319,6 +343,11 @@ sbus_introspect_generate(TALLOC_CTX *mem_ctx, struct sbus_interface_list *list)
}
}
+ ret = sbus_introspect_generate_nodes(memstream, nodes);
+ if (ret != EOK) {
+ goto done;
+ }
+
WRITE_OR_FAIL(memstream, ret, done, FMT_NODE_CLOSE);
fflush(memstream);
@@ -341,6 +370,7 @@ sbus_introspect(struct sbus_request *sbus_req, void *pvt)
DBusError *error;
struct sbus_interface_list *list;
struct sbus_connection *conn;
+ const char **nodes;
char *introspect;
errno_t ret;
@@ -354,7 +384,10 @@ sbus_introspect(struct sbus_request *sbus_req, void *pvt)
return sbus_request_fail_and_finish(sbus_req, error);
}
- introspect = sbus_introspect_generate(sbus_req, list);
+ nodes = sbus_nodes_hash_lookup(sbus_req, conn->nodes_fns, sbus_req->path);
+
+ introspect = sbus_introspect_generate(sbus_req, sbus_req->path,
+ nodes, list);
if (introspect == NULL) {
ret = ENOMEM;
goto done;
diff --git a/src/sbus/sssd_dbus_private.h b/src/sbus/sssd_dbus_private.h
index 24b6bec18..0493e1536 100644
--- a/src/sbus/sssd_dbus_private.h
+++ b/src/sbus/sssd_dbus_private.h
@@ -48,6 +48,7 @@ struct sbus_connection {
int disconnect;
hash_table_t *managed_paths;
+ hash_table_t *nodes_fns;
/* reconnect settings */
int retries;
@@ -129,6 +130,16 @@ sbus_opath_hash_lookup_supported(TALLOC_CTX *mem_ctx,
const char *object_path,
struct sbus_interface_list **_list);
+errno_t
+sbus_nodes_hash_init(TALLOC_CTX *mem_ctx,
+ struct sbus_connection *conn,
+ hash_table_t **_table);
+
+const char **
+sbus_nodes_hash_lookup(TALLOC_CTX *mem_ctx,
+ hash_table_t *table,
+ const char *object_path);
+
void
sbus_request_invoke_or_finish(struct sbus_request *dbus_req,
sbus_msg_handler_fn handler_fn,
diff --git a/src/tests/sbus_tests.c b/src/tests/sbus_tests.c
index 47d0556cf..598cc536d 100644
--- a/src/tests/sbus_tests.c
+++ b/src/tests/sbus_tests.c
@@ -47,7 +47,7 @@
#define PILOT_IFACE_INTROSPECT \
"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n" \
" \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n" \
- "<node>\n" \
+ "<node name=\"/test/leela\">\n" \
" <interface name=\"org.freedesktop.DBus.Introspectable\">\n" \
" <method name=\"Introspect\">\n" \
" <arg type=\"s\" name=\"data\" direction=\"out\" />\n" \