diff options
-rw-r--r-- | server/monitor.c | 500 | ||||
-rw-r--r-- | server/nss/nsssrv.c | 17 | ||||
-rw-r--r-- | server/nss/nsssrv.h | 2 | ||||
-rw-r--r-- | server/sbus/sssd_dbus.h | 38 | ||||
-rw-r--r-- | server/sbus/sssd_dbus_connection.c | 7 | ||||
-rw-r--r-- | server/sbus/sssd_dbus_server.c | 91 | ||||
-rw-r--r-- | server/sbus_interfaces.h | 1 |
7 files changed, 506 insertions, 150 deletions
diff --git a/server/monitor.c b/server/monitor.c index 5574d70c..1afebd51 100644 --- a/server/monitor.c +++ b/server/monitor.c @@ -32,23 +32,46 @@ #include "sbus/sssd_dbus.h" #include "sbus_interfaces.h" -struct mt_ctx { - struct event_context *ev; - struct confdb_ctx *cdb; - char **services; +struct mt_conn { + struct sbus_conn_ctx *conn_ctx; + struct mt_svc *svc_ptr; }; -struct mt_srv { - const char *name; +struct mt_svc { + struct mt_svc *prev; + struct mt_svc *next; + + struct mt_conn *mt_conn; struct mt_ctx *mt_ctx; + + const char *name; pid_t pid; - time_t last_restart; + int restarts; + time_t last_restart; + time_t last_pong; +}; + +struct mt_ctx { + struct event_context *ev; + struct confdb_ctx *cdb; + char **services; + struct mt_svc *svc_list; + + int service_id_timeout; + int service_ping_time; }; -static int dbus_service_init(struct sbus_conn_ctx *dct_ctx); +static int dbus_service_init(struct sbus_conn_ctx *conn_ctx, void *data); static void identity_check(DBusPendingCall *pending, void *data); +static int service_send_ping(struct mt_svc *svc); +static void ping_check(DBusPendingCall *pending, void *data); + +static int service_check_alive(struct mt_svc *svc); + +static void set_tasks_checker(struct mt_svc *srv); + /* dbus_get_monitor_version * Return the monitor version over D-BUS */ static int dbus_get_monitor_version(DBusMessage *message, @@ -93,109 +116,170 @@ static int monitor_dbus_init(struct mt_ctx *ctx) sd_ctx = talloc_zero(ctx, struct sbus_method_ctx); if (!sd_ctx) { + talloc_free(sbus_address); return ENOMEM; } /* Set up globally-available D-BUS methods */ sd_ctx->interface = talloc_strdup(sd_ctx, MONITOR_DBUS_INTERFACE); if (!sd_ctx->interface) { + talloc_free(sbus_address); talloc_free(sd_ctx); return ENOMEM; } sd_ctx->path = talloc_strdup(sd_ctx, MONITOR_DBUS_PATH); if (!sd_ctx->path) { + talloc_free(sbus_address); talloc_free(sd_ctx); return ENOMEM; } sd_ctx->methods = monitor_methods; sd_ctx->message_handler = NULL; /* Use the default message_handler */ - ret = sbus_new_server(ctx->ev, sd_ctx, sbus_address, dbus_service_init); + ret = sbus_new_server(ctx->ev, sd_ctx, sbus_address, dbus_service_init, ctx); return ret; } - -static void set_tasks_checker(struct mt_srv *srv); - static void tasks_check_handler(struct event_context *ev, struct timed_event *te, struct timeval t, void *ptr) { - struct mt_srv *srv = talloc_get_type(ptr, struct mt_srv); + struct mt_svc *svc = talloc_get_type(ptr, struct mt_svc); time_t now = time(NULL); - int status; - pid_t pid; + bool process_alive = true; int ret; - pid = waitpid(srv->pid, &status, WNOHANG); - if (pid == 0) { - set_tasks_checker(srv); - return; - } + ret = service_check_alive(svc); + switch (ret) { + case EOK: + /* all fine */ + break; - if (pid != srv->pid) { - DEBUG(1, ("bad return (%d) from waitpid() waiting for %d\n", - pid, srv->pid)); - /* TODO: what do we do now ? */ - } + case ECHILD: + DEBUG(1,("Process is stopped!\n")); + process_alive = false; + break; - if (WIFEXITED(status)) { /* children exited on it's own ?? */ - /* TODO: check configuration to see if it was removed - * from the list of process to run */ - DEBUG(0,("Process [%s] exited on it's own ?!\n", srv->name)); + default: + /* TODO: should we tear down it ? */ + DEBUG(1,("Checking for service process failed!!\n")); + break; } - if (srv->last_restart != 0) { - if ((now - srv->last_restart) > 30) { /* TODO: get val from config */ - /* it was long ago reset restart threshold */ - srv->restarts = 0; + if (process_alive) { + ret = service_send_ping(svc); + switch (ret) { + case EOK: + /* all fine */ + break; + + case ENXIO: + DEBUG(1,("Connection with child not available! (yet)\n")); + break; + + default: + /* TODO: should we tear it down ? */ + DEBUG(1,("Sending a message to the service failed!!\n")); + break; + } + + if (svc->last_pong != 0) { + if ((now - svc->last_pong) > 30) { /* TODO: get val from config */ + /* too long since we last heard of this process */ + ret = kill(svc->pid, SIGUSR1); + if (ret != EOK) { + DEBUG(0,("Sending signal to child failed! Ignore and pretend child is dead.\n")); + } + process_alive = false; + } } + } - /* restart the process */ - if (srv->restarts < 3) { /* TODO: get val from config */ + if (!process_alive) { + if (svc->last_restart != 0) { + if ((now - svc->last_restart) > 30) { /* TODO: get val from config */ + /* it was long ago reset restart threshold */ + svc->restarts = 0; + } + } - ret = server_service_init(srv->name, srv->mt_ctx->ev, &srv->pid); - if (ret != EOK) { - DEBUG(0,("Failed to restart service '%s'\n", srv->name)); - talloc_free(srv); + /* restart the process */ + if (svc->restarts > 3) { /* TODO: get val from config */ + DEBUG(0, ("Process [%s], definitely stopped!\n", svc->name)); + talloc_free(svc); return; } - srv->restarts++; - srv->last_restart = now; + ret = server_service_init(svc->name, svc->mt_ctx->ev, &svc->pid); + if (ret != EOK) { + DEBUG(0,("Failed to restart service '%s'\n", svc->name)); + talloc_free(svc); + return; + } - set_tasks_checker(srv); - return; + svc->restarts++; + svc->last_restart = now; + svc->last_pong = 0; } - DEBUG(0, ("Process [%s], definitely stopped!\n", srv->name)); - talloc_free(srv); + /* all fine, set up the task checker again */ + set_tasks_checker(svc); } -static void set_tasks_checker(struct mt_srv *srv) +static void set_tasks_checker(struct mt_svc *svc) { struct timed_event *te = NULL; struct timeval tv; gettimeofday(&tv, NULL); - tv.tv_sec += 2; + tv.tv_sec += svc->mt_ctx->service_ping_time; tv.tv_usec = 0; - te = event_add_timed(srv->mt_ctx->ev, srv, tv, tasks_check_handler, srv); + te = event_add_timed(svc->mt_ctx->ev, svc, tv, tasks_check_handler, svc); if (te == NULL) { DEBUG(0, ("failed to add event, monitor offline for [%s]!\n", - srv->name)); + svc->name)); /* FIXME: shutdown ? */ } } +int get_monitor_config(struct mt_ctx *ctx) +{ + int ret; + + ret = confdb_get_int(ctx->cdb, ctx, + "config.services.monitor", "sbusTimeout", + -1, &ctx->service_id_timeout); + if (ret != EOK) { + return ret; + } + + ret = confdb_get_int(ctx->cdb, ctx, + "config.services.monitor", "servicePingTime", + -1, &ctx->service_ping_time); + if (ret != EOK) { + return ret; + } + + ret = confdb_get_param(ctx->cdb, ctx, + "config.services", "activeServices", + &ctx->services); + + if (ctx->services[0] == NULL) { + DEBUG(0, ("No services configured!\n")); + return EINVAL; + } + + return EOK; +} + int start_monitor(TALLOC_CTX *mem_ctx, struct event_context *event_ctx, struct confdb_ctx *cdb) { struct mt_ctx *ctx; - struct mt_srv *srv; + struct mt_svc *svc; int ret, i; ctx = talloc_zero(mem_ctx, struct mt_ctx); @@ -204,32 +288,32 @@ int start_monitor(TALLOC_CTX *mem_ctx, return ENOMEM; } ctx->ev = event_ctx; + ctx->cdb = cdb; - ret = confdb_get_param(cdb, mem_ctx, "config.services", - "activeServices", &ctx->services); - - if (ctx->services[0] == NULL) { - DEBUG(0, ("No services configured!\n")); - return EINVAL; - } + ret = get_monitor_config(ctx); + if (ret != EOK) + return ret; for (i = 0; ctx->services[i]; i++) { - srv = talloc_zero(ctx, struct mt_srv); - if (!srv) { + svc = talloc_zero(ctx, struct mt_svc); + if (!svc) { talloc_free(ctx); return ENOMEM; } - srv->name = ctx->services[i]; - srv->mt_ctx = ctx; + svc->name = ctx->services[i]; + svc->mt_ctx = ctx; - ret = server_service_init(srv->name, event_ctx, &srv->pid); + ret = server_service_init(svc->name, event_ctx, &svc->pid); if (ret != EOK) { - DEBUG(0,("Failed to restart service '%s'\n", srv->name)); - talloc_free(srv); + DEBUG(0,("Failed to start service '%s'\n", svc->name)); + talloc_free(svc); + continue; } - set_tasks_checker(srv); + DLIST_ADD(ctx->svc_list, svc); + + set_tasks_checker(svc); } /* Initialize D-BUS Server @@ -243,6 +327,21 @@ int start_monitor(TALLOC_CTX *mem_ctx, return EOK; } +static int mt_conn_destructor(void *ptr) +{ + struct mt_conn *mt_conn; + struct mt_svc *svc; + + mt_conn = talloc_get_type(ptr, struct mt_conn); + svc = mt_conn->svc_ptr; + + /* now clear up so that the rest of the code will know there + * is no connection attached to the service anymore */ + svc->mt_conn = NULL; + + return 0; +} + /* * dbus_service_init * This function should initiate a query to the newly connected @@ -250,27 +349,64 @@ int start_monitor(TALLOC_CTX *mem_ctx, * method on the new client). The reply callback for this request * should set the connection destructor appropriately. */ -static int dbus_service_init(struct sbus_conn_ctx *dct_ctx) { +static int dbus_service_init(struct sbus_conn_ctx *conn_ctx, void *data) { + struct mt_ctx *ctx; + struct mt_svc *svc; + struct mt_conn *mt_conn; DBusMessage *msg; DBusPendingCall *pending_reply; DBusConnection *conn; DBusError dbus_error; dbus_bool_t dbret; - - DEBUG(0,("Initializing D-BUS Service")); - conn = sbus_get_connection(dct_ctx); + + DEBUG(3, ("Initializing D-BUS Service\n")); + + ctx = talloc_get_type(data, struct mt_ctx); + conn = sbus_get_connection(conn_ctx); dbus_error_init(&dbus_error); - /* - * Set up identity request + /* hang off this memory to the connection so that when the connection + * is freed we can call a destructor to clear up the structure and + * have a way to know we need to restart the service */ + mt_conn = talloc(conn_ctx, struct mt_conn); + if (!mt_conn) { + DEBUG(0,("Out of memory?!\n")); + talloc_free(conn_ctx); + return ENOMEM; + } + mt_conn->conn_ctx = conn_ctx; + + /* at this stage we still do not know what service is this + * we will know only after we get its identity, so we make + * up a temporary fake service and complete the operation + * when we receive the reply */ + svc = talloc_zero(mt_conn, struct mt_svc); + if (!svc) { + talloc_free(conn_ctx); + return ENOMEM; + } + svc->mt_ctx = ctx; + svc->mt_conn = mt_conn; + + mt_conn->svc_ptr = svc; + talloc_set_destructor((TALLOC_CTX *)mt_conn, mt_conn_destructor); + + /* + * Set up identity request * This should be a well-known path and method * for all services */ msg = dbus_message_new_method_call(NULL, - SERVICE_PATH, - SERVICE_INTERFACE, - SERVICE_METHOD_IDENTITY); - dbret = dbus_connection_send_with_reply(conn, msg, &pending_reply, -1); + SERVICE_PATH, + SERVICE_INTERFACE, + SERVICE_METHOD_IDENTITY); + if (msg == NULL) { + DEBUG(0,("Out of memory?!\n")); + talloc_free(conn_ctx); + return ENOMEM; + } + dbret = dbus_connection_send_with_reply(conn, msg, &pending_reply, + ctx->service_id_timeout); if (!dbret) { /* * Critical Failure @@ -278,25 +414,33 @@ static int dbus_service_init(struct sbus_conn_ctx *dct_ctx) { * We'll drop it using the default destructor. */ DEBUG(0, ("D-BUS send failed.\n")); - talloc_free(dct_ctx); + talloc_free(conn_ctx); + return EIO; } - + /* Set up the reply handler */ - dbus_pending_call_set_notify(pending_reply, identity_check, dct_ctx, NULL); + dbus_pending_call_set_notify(pending_reply, identity_check, svc, NULL); dbus_message_unref(msg); return EOK; } -static void identity_check(DBusPendingCall *pending, void *data) { - struct sbus_conn_ctx *dct_ctx; +static void identity_check(DBusPendingCall *pending, void *data) +{ + struct mt_svc *fake_svc; + struct mt_svc *svc; + struct sbus_conn_ctx *conn_ctx; DBusMessage *reply; DBusError dbus_error; + dbus_uint16_t svc_ver; + char *svc_name; + dbus_bool_t ret; int type; - dct_ctx = talloc_get_type(data, struct sbus_conn_ctx); + fake_svc = talloc_get_type(data, struct mt_svc); + conn_ctx = fake_svc->mt_conn->conn_ctx; dbus_error_init(&dbus_error); - + reply = dbus_pending_call_steal_reply(pending); if (!reply) { /* reply should never be null. This function shouldn't be called @@ -304,31 +448,207 @@ static void identity_check(DBusPendingCall *pending, void *data) { * here, something is seriously wrong and we should bail out. */ DEBUG(0, ("Serious error. A reply callback was called but no reply was received and no timeout occurred\n")); - + /* Destroy this connection */ - sbus_disconnect(dct_ctx); + sbus_disconnect(conn_ctx); return; } - + type = dbus_message_get_type(reply); switch (type) { case DBUS_MESSAGE_TYPE_METHOD_RETURN: - /* Got the service name and version */ - /* Extract the name and version from the message */ + ret = dbus_message_get_args(reply, &dbus_error, + DBUS_TYPE_STRING, &svc_name, + DBUS_TYPE_UINT16, &svc_ver, + DBUS_TYPE_INVALID); + if (!ret) { + DEBUG(1,("Failed, to parse message, killing connection\n")); + sbus_disconnect(conn_ctx); + return; + } + + /* search this service in the list */ + svc = fake_svc->mt_ctx->svc_list; + while (svc) { + ret = strcasecmp(svc->name, svc_name); + if (ret == 0) { + break; + } + svc = svc->next; + } + if (!svc) { + DEBUG(0,("Unable to find peer in list of services, killing connection!\n")); + sbus_disconnect(conn_ctx); + return; + } + + /* transfer all from the fake service and get rid of it */ + fake_svc->mt_conn->svc_ptr = svc; + svc->mt_conn = fake_svc->mt_conn; + talloc_free(fake_svc); + /* Set up the destructor for this service */ break; + case DBUS_MESSAGE_TYPE_ERROR: - DEBUG(0,("getIdentity returned an error %s, closing connection.\n", dbus_message_get_error_name(reply))); + DEBUG(0,("getIdentity returned an error [%s], closing connection.\n", + dbus_message_get_error_name(reply))); /* Falling through to default intentionally*/ default: /* * Timeout or other error occurred or something * unexpected happened. - * It doesn't matter which, because either way we + * It doesn't matter which, because either way we * know that this connection isn't trustworthy. * We'll destroy it now. */ - sbus_disconnect(dct_ctx); + sbus_disconnect(conn_ctx); + return; + } +} + +/* service_send_ping + * this function send a dbus ping to a service. + * It returns EOK if all is fine or ENXIO if the connection is + * not available (either not yet set up or teared down). + * Returns e generic error in other cases. + */ +static int service_send_ping(struct mt_svc *svc) +{ + DBusMessage *msg; + DBusPendingCall *pending_reply; + DBusConnection *conn; + DBusError dbus_error; + dbus_bool_t dbret; + + if (!svc->mt_conn) { + return ENXIO; + } + + conn = sbus_get_connection(svc->mt_conn->conn_ctx); + dbus_error_init(&dbus_error); + + /* + * Set up identity request + * This should be a well-known path and method + * for all services + */ + msg = dbus_message_new_method_call(NULL, + SERVICE_PATH, + SERVICE_INTERFACE, + SERVICE_METHOD_PING); + if (!msg) { + DEBUG(0,("Out of memory?!\n")); + talloc_free(svc->mt_conn->conn_ctx); + return ENOMEM; + } + + dbret = dbus_connection_send_with_reply(conn, msg, &pending_reply, + svc->mt_ctx->service_id_timeout); + if (!dbret) { + /* + * Critical Failure + * We can't communicate on this connection + * We'll drop it using the default destructor. + */ + DEBUG(0, ("D-BUS send failed.\n")); + talloc_free(svc->mt_conn->conn_ctx); + return EIO; + } + + /* Set up the reply handler */ + dbus_pending_call_set_notify(pending_reply, ping_check, svc, NULL); + dbus_message_unref(msg); + + return EOK; +} + +static void ping_check(DBusPendingCall *pending, void *data) +{ + struct mt_svc *svc; + struct sbus_conn_ctx *conn_ctx; + DBusMessage *reply; + DBusError dbus_error; + const char *dbus_error_name; + int type; + + svc = talloc_get_type(data, struct mt_svc); + conn_ctx = svc->mt_conn->conn_ctx; + dbus_error_init(&dbus_error); + + reply = dbus_pending_call_steal_reply(pending); + if (!reply) { + /* reply should never be null. This function shouldn't be called + * until reply is valid or timeout has occurred. If reply is NULL + * here, something is seriously wrong and we should bail out. + */ + DEBUG(0, ("A reply callback was called but no reply was received" + " and no timeout occurred\n")); + + /* Destroy this connection */ + sbus_disconnect(conn_ctx); + return; + } + + type = dbus_message_get_type(reply); + switch (type) { + case DBUS_MESSAGE_TYPE_METHOD_RETURN: + /* ok peer replied, + * set the reply timestamp into the service structure */ + + svc->last_pong = time(NULL); break; + + case DBUS_MESSAGE_TYPE_ERROR: + + dbus_error_name = dbus_message_get_error_name(reply); + + /* timeouts are handled in the main service check function */ + if (strcmp(dbus_error_name, DBUS_ERROR_TIMEOUT) == 0) + break; + + DEBUG(0,("A service PING returned an error [%s], closing connection.\n", + dbus_error_name)); + /* Falling through to default intentionally*/ + default: + /* + * Timeout or other error occurred or something + * unexpected happened. + * It doesn't matter which, because either way we + * know that this connection isn't trustworthy. + * We'll destroy it now. + */ + sbus_disconnect(conn_ctx); + return; } } + +/* service_check_alive + * This function checks if the service child is still alive + */ +static int service_check_alive(struct mt_svc *svc) +{ + int status; + pid_t pid; + + pid = waitpid(svc->pid, &status, WNOHANG); + if (pid == 0) { + return EOK; + } + + if (pid != svc->pid) { + DEBUG(1, ("bad return (%d) from waitpid() waiting for %d\n", + pid, svc->pid)); + /* TODO: what do we do now ? */ + return EINVAL; + } + + if (WIFEXITED(status)) { /* children exited on it's own */ + /* TODO: check configuration to see if it was removed + * from the list of process to run */ + DEBUG(0,("Process [%s] exited\n", svc->name)); + } + + return ECHILD; +} + diff --git a/server/nss/nsssrv.c b/server/nss/nsssrv.c index 04eead6d..bd0f761b 100644 --- a/server/nss/nsssrv.c +++ b/server/nss/nsssrv.c @@ -40,9 +40,11 @@ #include "sbus_interfaces.h" static int provide_identity(DBusMessage *message, void *data, DBusMessage **r); +static int reply_ping(DBusMessage *message, void *data, DBusMessage **r); struct sbus_method nss_sbus_methods[] = { {SERVICE_METHOD_IDENTITY, provide_identity}, + {SERVICE_METHOD_PING, reply_ping}, {NULL, NULL} }; @@ -223,6 +225,21 @@ static int provide_identity(DBusMessage *message, void *data, DBusMessage **r) return EOK; } +static int reply_ping(DBusMessage *message, void *data, DBusMessage **r) +{ + DBusMessage *reply; + dbus_bool_t ret; + + reply = dbus_message_new_method_return(message); + ret = dbus_message_append_args(reply, DBUS_TYPE_INVALID); + if (!ret) { + return EIO; + } + + *r = reply; + return EOK; +} + static int nss_sbus_init(struct nss_ctx *nctx) { struct sbus_method_ctx *cli_sm_ctx; diff --git a/server/nss/nsssrv.h b/server/nss/nsssrv.h index 300b8af3..5e264937 100644 --- a/server/nss/nsssrv.h +++ b/server/nss/nsssrv.h @@ -30,7 +30,7 @@ #include "../nss_client/sss_nss.h" #define NSS_SBUS_SERVICE_VERSION 0x0001 -#define NSS_SBUS_SERVICE_NAME "NSS" +#define NSS_SBUS_SERVICE_NAME "nss" struct nss_ldb_ctx; struct getent_ctx; diff --git a/server/sbus/sssd_dbus.h b/server/sbus/sssd_dbus.h index 1bd062d4..5510b6e4 100644 --- a/server/sbus/sssd_dbus.h +++ b/server/sbus/sssd_dbus.h @@ -21,16 +21,16 @@ #ifndef _SSSD_DBUS_H_ #define _SSSD_DBUS_H_ + struct sbus_conn_ctx; -typedef int (*sbus_msg_handler_fn)(DBusMessage *msg, void *data, - DBusMessage **reply); + +typedef int (*sbus_msg_handler_fn)(DBusMessage *, void *, DBusMessage **); /* * sbus_conn_destructor_fn * Function to be called when a connection is finalized */ -typedef int (*sbus_conn_destructor_fn)( - void *ctx); +typedef int (*sbus_conn_destructor_fn)(void *); /* * sbus_server_conn_init_fn @@ -38,8 +38,7 @@ typedef int (*sbus_conn_destructor_fn)( * This function should define the sbus_conn_destructor_fn * for this connection at a minimum */ -typedef int (*sbus_server_conn_init_fn)( - struct sbus_conn_ctx *dct_ctx); +typedef int (*sbus_server_conn_init_fn)(struct sbus_conn_ctx *, void *); enum { SBUS_CONN_TYPE_PRIVATE = 1, @@ -56,7 +55,7 @@ struct sbus_method_ctx { /*struct event_context *ev;*/ char *interface; char *path; - + /* If a non-default message_handler is desired, set it in this * object before calling sbus_conn_add_method_ctx() * Otherwise it will default to message_handler() in @@ -67,20 +66,25 @@ struct sbus_method_ctx { }; /* Server Functions */ -int sbus_new_server(struct event_context *ev, struct sbus_method_ctx *ctx, const char *address, sbus_server_conn_init_fn init_fn); +int sbus_new_server(struct event_context *ev, struct sbus_method_ctx *ctx, + const char *address, + sbus_server_conn_init_fn init_fn, void *init_pvt_data); /* Connection Functions */ -int sbus_new_connection(TALLOC_CTX *ctx, struct event_context *ev, const char *address, - struct sbus_conn_ctx **dct_ctx, - sbus_conn_destructor_fn destructor); +int sbus_new_connection(TALLOC_CTX *ctx, struct event_context *ev, + const char *address, + struct sbus_conn_ctx **conn_ctx, + sbus_conn_destructor_fn destructor); + +void sbus_conn_set_destructor(struct sbus_conn_ctx *conn_ctx, + sbus_conn_destructor_fn destructor); -void sbus_conn_set_destructor(struct sbus_conn_ctx *dct_ctx, - sbus_conn_destructor_fn destructor); int sbus_default_connection_destructor(void *ctx); -DBusConnection *sbus_get_connection(struct sbus_conn_ctx *dct_ctx); -void sbus_disconnect (struct sbus_conn_ctx *dct_ctx); -void sbus_conn_set_private_data(struct sbus_conn_ctx *dct_ctx, void *private); -int sbus_conn_add_method_ctx(struct sbus_conn_ctx *dct_ctx, struct sbus_method_ctx *method_ctx); +DBusConnection *sbus_get_connection(struct sbus_conn_ctx *conn_ctx); +void sbus_disconnect(struct sbus_conn_ctx *conn_ctx); +void sbus_conn_set_private_data(struct sbus_conn_ctx *conn_ctx, void *pvt_data); +int sbus_conn_add_method_ctx(struct sbus_conn_ctx *conn_ctx, + struct sbus_method_ctx *method_ctx); #endif /* _SSSD_DBUS_H_*/ diff --git a/server/sbus/sssd_dbus_connection.c b/server/sbus/sssd_dbus_connection.c index bd95c0ab..7769188b 100644 --- a/server/sbus/sssd_dbus_connection.c +++ b/server/sbus/sssd_dbus_connection.c @@ -15,7 +15,7 @@ struct sbus_conn_ctx { int disconnect; struct sbus_method_ctx *method_ctx_list; sbus_conn_destructor_fn destructor; - void *private; /* Private data for this connection */ + void *pvt_data; /* Private data for this connection */ }; struct sbus_conn_watch_ctx { @@ -571,6 +571,7 @@ static void sbus_unreg_object_paths(struct sbus_conn_ctx *dct_ctx) { } } -void sbus_conn_set_private_data(struct sbus_conn_ctx *dct_ctx, void *private) { - dct_ctx->private = private; +void sbus_conn_set_private_data(struct sbus_conn_ctx *conn_ctx, void *pvt_data) +{ + conn_ctx->pvt_data = pvt_data; } diff --git a/server/sbus/sssd_dbus_server.c b/server/sbus/sssd_dbus_server.c index 22dcbf39..f8396b5c 100644 --- a/server/sbus/sssd_dbus_server.c +++ b/server/sbus/sssd_dbus_server.c @@ -40,6 +40,7 @@ struct sbus_srv_ctx { struct event_context *ev; struct sbus_method_ctx *sd_ctx; sbus_server_conn_init_fn init_fn; + void *init_pvt_data; }; struct sbus_srv_watch_ctx { @@ -198,40 +199,41 @@ static void sbus_toggle_srv_timeout(DBusTimeout *timeout, void *data) * new connection or else close the connection with * dbus_connection_close() */ -static void sbus_server_init_new_connection(DBusServer *server, DBusConnection *conn, - void *data) +static void sbus_server_init_new_connection(DBusServer *server, + DBusConnection *conn, + void *data) { - struct sbus_srv_ctx *dst_ctx; - struct sbus_conn_ctx *dct_ctx; + struct sbus_srv_ctx *srv_ctx; + struct sbus_conn_ctx *conn_ctx; struct sbus_method_ctx *iter; - - /*DBusObjectPathVTable *connection_vtable;*/ int ret; - DEBUG(0,("Entering.\n")); - dst_ctx = talloc_get_type(data,struct sbus_srv_ctx); - if(dst_ctx == NULL) { + + DEBUG(3,("Entering.\n")); + srv_ctx = talloc_get_type(data,struct sbus_srv_ctx); + if (srv_ctx == NULL) { return; } - DEBUG(0,("Adding connection %lX.\n", conn)); - ret = sbus_add_connection(dst_ctx, dst_ctx->ev, conn, &dct_ctx, SBUS_CONN_TYPE_PRIVATE); + DEBUG(3,("Adding connection %lX.\n", conn)); + ret = sbus_add_connection(srv_ctx, srv_ctx->ev, conn, + &conn_ctx, SBUS_CONN_TYPE_PRIVATE); if (ret != 0) { dbus_connection_close(conn); - DEBUG(0,("Closing connection (failed setup)")); + DEBUG(3,("Closing connection (failed setup)")); return; } - + dbus_connection_ref(conn); - DEBUG(3,("Got a connection\n")); + DEBUG(2,("Got a connection\n")); /* Set up global methods */ - iter = dst_ctx->sd_ctx; + iter = srv_ctx->sd_ctx; while (iter != NULL) { - sbus_conn_add_method_ctx(dct_ctx, iter); + sbus_conn_add_method_ctx(conn_ctx, iter); iter = iter->next; } - + /* * Initialize connection-specific features * This may set a more detailed destructor, but @@ -240,7 +242,10 @@ static void sbus_server_init_new_connection(DBusServer *server, DBusConnection * * This function (or its callbacks) should also * set up connection-specific methods. */ - dst_ctx->init_fn(dct_ctx); + ret = srv_ctx->init_fn(conn_ctx, srv_ctx->init_pvt_data); + if (ret != EOK) { + DEBUG(1,("Initialization failed!\n")); + } } /* @@ -248,9 +253,11 @@ static void sbus_server_init_new_connection(DBusServer *server, DBusConnection * * Set up a D-BUS server, integrate with the event loop * for handling file descriptor and timed events */ -int sbus_new_server(struct event_context *ev, struct sbus_method_ctx *ctx, const char *address, sbus_server_conn_init_fn init_fn) +int sbus_new_server(struct event_context *ev, struct sbus_method_ctx *ctx, + const char *address, sbus_server_conn_init_fn init_fn, + void *init_pvt_data) { - struct sbus_srv_ctx *dst_ctx; + struct sbus_srv_ctx *srv_ctx; DBusServer *dbus_server; DBusServer **dbus_server_talloc; DBusError dbus_error; @@ -268,49 +275,55 @@ int sbus_new_server(struct event_context *ev, struct sbus_method_ctx *ctx, const DEBUG(2, ("D-BUS Server listening on %s\n", dbus_server_get_address(dbus_server))); - dst_ctx = talloc_zero(ev, struct sbus_srv_ctx); - if (!dst_ctx) { + srv_ctx = talloc_zero(ev, struct sbus_srv_ctx); + if (!srv_ctx) { return ENOMEM; } - - dbus_server_talloc = talloc_takeover(ctx, dbus_server, sbus_server_destructor); - dst_ctx->ev = ev; - dst_ctx->server = dbus_server; - dst_ctx->sd_ctx = ctx; - dst_ctx->init_fn = init_fn; + + dbus_server_talloc = sssd_mem_takeover(ctx, dbus_server, + sbus_server_destructor); + srv_ctx->ev = ev; + srv_ctx->server = dbus_server; + srv_ctx->sd_ctx = ctx; + srv_ctx->init_fn = init_fn; + srv_ctx->init_pvt_data = init_pvt_data; /* Set up D-BUS new connection handler */ - dbus_server_set_new_connection_function(dst_ctx->server, + dbus_server_set_new_connection_function(srv_ctx->server, sbus_server_init_new_connection, - dst_ctx, NULL); + srv_ctx, NULL); /* Set up DBusWatch functions */ - dbret = dbus_server_set_watch_functions(dst_ctx->server, sbus_add_srv_watch, - sbus_remove_watch, sbus_toggle_srv_watch, - dst_ctx, NULL); + dbret = dbus_server_set_watch_functions(srv_ctx->server, + sbus_add_srv_watch, + sbus_remove_watch, + sbus_toggle_srv_watch, + srv_ctx, NULL); if (!dbret) { DEBUG(0, ("Error setting up D-BUS server watch functions")); - talloc_free(dst_ctx); + talloc_free(srv_ctx); return EIO; } /* Set up DBusTimeout functions */ - dbret = dbus_server_set_timeout_functions(dst_ctx->server, + dbret = dbus_server_set_timeout_functions(srv_ctx->server, sbus_add_srv_timeout, sbus_remove_timeout, sbus_toggle_srv_timeout, - dst_ctx, NULL); + srv_ctx, NULL); if (!dbret) { DEBUG(0,("Error setting up D-BUS server timeout functions")); - dbus_server_set_watch_functions(dst_ctx->server, NULL, NULL, NULL, NULL, NULL); - talloc_free(dst_ctx); + dbus_server_set_watch_functions(srv_ctx->server, + NULL, NULL, NULL, NULL, NULL); + talloc_free(srv_ctx); return EIO; } return EOK; } -static int sbus_server_destructor(void **server) { +static int sbus_server_destructor(void **server) +{ dbus_server_disconnect(*server); return 0; } diff --git a/server/sbus_interfaces.h b/server/sbus_interfaces.h index 106a5495..2e6372de 100644 --- a/server/sbus_interfaces.h +++ b/server/sbus_interfaces.h @@ -36,6 +36,7 @@ /* Service Methods */ #define SERVICE_METHOD_IDENTITY "getIdentity" +#define SERVICE_METHOD_PING "ping" #define DEFAULT_SBUS_ADDRESS "unix:path=/var/lib/sss/pipes/private/dbus" |