monitor.c revision 0ae402cee3485fb5830ce0ffcf9e566c38fa287f
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher Service monitor
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek Copyright (C) Simo Sorce 2008
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek This program is free software; you can redistribute it and/or modify
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher it under the terms of the GNU General Public License as published by
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher the Free Software Foundation; either version 3 of the License, or
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (at your option) any later version.
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek This program is distributed in the hope that it will be useful,
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek but WITHOUT ANY WARRANTY; without even the implied warranty of
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher GNU General Public License for more details.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher You should have received a copy of the GNU General Public License
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher along with this program. If not, see <http://www.gnu.org/licenses/>.
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher/* Needed for res_init() */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "responder/common/responder_sbus.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* ping time cannot be less then once every few seconds or the
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher * monitor will get crazy hammering children with messages */
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher/* terminate the child after this interval by default if it
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * doesn't shutdown on receiving SIGTERM */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* TODO: get the restart related values from config */
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek/* maximum allowed number of service restarts if the restarts
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek * were less than MONITOR_RESTART_CNT_INTERVAL_RESET apart, which would
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek * indicate a crash after startup or after every request */
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher/* The services are restarted with a delay in case the restart was
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * hitting a race condition where the DP is not ready yet either.
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher * The MONITOR_MAX_RESTART_DELAY defines the maximum delay between
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* name of the monitor server instance */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#define SSSD_PIDFILE_PATH PID_PATH"/"MONITOR_NAME".pid"
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher/* Special value to leave the Kerberos Replay Cache set to use
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * the libkrb5 defaults
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#define KRB5_RCACHE_DIR_DISABLE "__LIBKRB5_DEFAULTS__"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher TALLOC_CTX *domain_ctx; /* Memory context for domain list */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher TALLOC_CTX *service_ctx; /* Memory context for services */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int start_service(struct mt_svc *mt_svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int monitor_service_init(struct sbus_connection *conn, void *data);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int service_send_ping(struct mt_svc *svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int service_signal_reset_offline(struct mt_svc *svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void ping_check(DBusPendingCall *pending, void *data);
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagherstatic void set_tasks_checker(struct mt_svc *srv);
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagherstatic int monitor_kill_service (struct mt_svc *svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int get_service_config(struct mt_ctx *ctx, const char *name,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int get_provider_config(struct mt_ctx *ctx, const char *name,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int add_new_service(struct mt_ctx *ctx,
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagherstatic int add_new_provider(struct mt_ctx *ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int mark_service_as_started(struct mt_svc *svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int monitor_cleanup(void);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void network_status_change_cb(void *cb_data)
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher struct mt_ctx *ctx = (struct mt_ctx *) cb_data;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_TRACE_INTERNAL, ("A networking status change detected "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "signaling providers to reset offline status\n"));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (iter = ctx->svc_list; iter; iter = iter->next) {
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher /* Don't signal services, only providers */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* dbus_get_monitor_version
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * Return the monitor version over D-BUS */
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagherstatic int get_monitor_version(DBusMessage *message,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher reply = dbus_message_new_method_return(message);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* send reply back */
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagherstatic int add_svc_conn_spy(struct mt_svc *svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* registers a new client.
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher * if operation is successful also sends back the Monitor version */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int client_registration(DBusMessage *message,
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher mini = talloc_get_type(data, struct mon_init_conn);
bf9abef629707167d39fcc92ec9c18a6244b27b8Jakub Hrozek DEBUG(0, ("Connection holds no valid init data\n"));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* First thing, cancel the timeout */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher dbret = dbus_message_get_args(message, &dbus_error,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(1, ("Failed to parse message, killing connection\n"));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher /* FIXME: should we just talloc_zfree(conn) ? */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(4, ("Received ID registration: (%s,%d)\n", svc_name, svc_ver));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* search this service in the list */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = strcasecmp(svc->identity, svc_name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(0, ("Unable to find peer [%s] in list of services,"
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek /* FIXME: should we just talloc_zfree(conn) ? */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* Fill in svc structure with connection data */
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek DEBUG(1, ("Failed to mark service [%s]!\n", svc_name));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* reply that all is ok */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher reply = dbus_message_new_method_return(message);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* send reply back */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* init complete, get rid of temp init context */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek struct mt_svc *svc = talloc_get_type(mem, struct mt_svc);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* try to delist service */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* Cancel any pending pings */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* svc is beeing freed, neutralize the spy */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek talloc_set_destructor((TALLOC_CTX *)svc->conn_spy, NULL);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek if (svc->type == MT_SVC_SERVICE && svc->svc_started
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek && svc->mt_ctx != NULL && svc->mt_ctx->started_services > 0) {
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek struct svc_spy *spy = talloc_get_type(mem, struct svc_spy);
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher /* svc->conn has been freed, NULL the pointer in svc */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int add_svc_conn_spy(struct mt_svc *svc)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher talloc_set_destructor((TALLOC_CTX *)spy, svc_spy_destructor);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int mark_service_as_started(struct mt_svc *svc)
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher DEBUG(5, ("Marking %s as started.\n", svc->name));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* we need to attach a spy to the connection structure so that if some code
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * frees it we can zero it out in the service structure. Otherwise we may
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek * try to access or even free, freed memory. */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* check if all providers are up */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (iter = ctx->svc_list; iter; iter = iter->next) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (iter->provider && !iter->svc_started) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(5, ("Still waiting on %s provider.\n", iter->name));
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* there are still unstarted providers */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* then start all services */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher add_new_service(ctx, ctx->services[i], 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ctx->started_services == ctx->num_services) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Initialization is complete, terminate parent process if in daemon
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher * mode. Make sure we send the signal to the right process */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ctx->parent_pid <= 1 || ctx->parent_pid != getppid()) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* the parent process was already terminated */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek DEBUG(SSSDBG_MINOR_FAILURE, ("Invalid parent pid: %d\n",
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher DEBUG(SSSDBG_TRACE_FUNC, ("SSSD is initialized, "
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher "terminating parent process\n"));
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek DEBUG(SSSDBG_FATAL_FAILURE, ("Unable to terminate parent "
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozekstatic void services_startup_timeout(struct tevent_context *ev,
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek struct mt_ctx *ctx = talloc_get_type(ptr, struct mt_ctx);
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek "forcing services startup!\n"));
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher /* then start all services */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher add_new_service(ctx, ctx->services[i], 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int add_services_startup_timeout(struct mt_ctx *ctx)
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher /* 5 seconds should be plenty */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher to = tevent_add_timer(ctx->ev, ctx, tv, services_startup_timeout, ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher { MON_SRV_METHOD_VERSION, get_monitor_version },
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher { MON_SRV_METHOD_REGISTER, client_registration },
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagherstruct sbus_interface monitor_server_interface = {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* monitor_dbus_init
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek * Set up the monitor service as a D-BUS Server */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int monitor_dbus_init(struct mt_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = monitor_get_sbus_address(ctx, &monitor_address);
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher monitor_address, &monitor_server_interface,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher false, &ctx->sbus_srv, monitor_service_init, ctx);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozekstatic void tasks_check_handler(struct tevent_context *ev,
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek struct mt_svc *svc = talloc_get_type(ptr, struct mt_svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* all fine */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek DEBUG(1,("Child (%s) not responding! (yet)\n", svc->name));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* TODO: should we tear it down ? */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek DEBUG(1,("Sending a message to service (%s) failed!!\n", svc->name));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* too long since we last heard of this process */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ("Killing service [%s], not responding to pings!\n",
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher /* Kill the service. The SIGCHLD handler will restart it */
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher /* all fine, set up the task checker again */
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagherstatic void set_tasks_checker(struct mt_svc *svc)
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher te = tevent_add_timer(svc->mt_ctx->ev, svc, tv, tasks_check_handler, svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(0, ("failed to add event, monitor offline for [%s]!\n",
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* FIXME: shutdown ? */
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagherstatic void mt_svc_sigkill(struct tevent_context *ev,
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagherstatic int monitor_kill_service (struct mt_svc *svc)
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher ("Sending signal to child (%s:%d) failed! "
7a14e8f66c0e932fe2954d792614a3b61d444bd1Jakub Hrozek "Ignore and pretend child is dead.\n",
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher /* Set up a timer to send SIGKILL if this process
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher * doesn't exit within sixty seconds
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher tv = tevent_timeval_current_ofs(svc->kill_time, 0);
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek svc->sigkill_ev = tevent_add_timer(svc->mt_ctx->ev, svc, tv,
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozekstatic void mt_svc_sigkill(struct tevent_context *ev,
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek struct mt_svc *svc = talloc_get_type(ptr, struct mt_svc);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek ("[%s][%d] is not responding to SIGTERM. Sending SIGKILL.\n",
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek ("Sending signal to child (%s:%d) failed! "
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek "Ignore and pretend child is dead.\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void reload_reply(DBusPendingCall *pending, void *data)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mt_svc *svc = talloc_get_type(data, struct mt_svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher reply = dbus_pending_call_steal_reply(pending);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* reply should never be null. This function shouldn't be called
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher * until reply is valid or timeout has occurred. If reply is NULL
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher * here, something is seriously wrong and we should bail out.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(0, ("A reply callback was called but no reply was received"
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek " and no timeout occurred\n"));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Destroy this connection */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* TODO: Handle cases where the call has timed out or returned
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * with an error.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int service_signal_dns_reload(struct mt_svc *svc);
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagherstatic int monitor_update_resolv(struct config_file_ctx *file_ctx,
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher DEBUG(2, ("Resolv.conf has been updated. Reloading.\n"));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Signal all services to reload their DNS configuration */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for(cur_svc = file_ctx->mt_ctx->svc_list; cur_svc; cur_svc = cur_svc->next) {
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozekstatic int service_signal(struct mt_svc *svc, const char *svc_signal)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (svc->provider && strcasecmp(svc->provider, "local") == 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* The local provider requires no signaling */
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher /* Avoid a race condition where we are trying to
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher * order a service to reload that hasn't started
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek DEBUG(1,("Could not signal service [%s].\n", svc->name));
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozekstatic int service_signal_dns_reload(struct mt_svc *svc)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return service_signal(svc, MON_CLI_METHOD_RES_INIT);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int service_signal_offline(struct mt_svc *svc)
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher return service_signal(svc, MON_CLI_METHOD_OFFLINE);
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagherstatic int service_signal_reset_offline(struct mt_svc *svc)
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return service_signal(svc, MON_CLI_METHOD_RESET_OFFLINE);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int service_signal_rotate(struct mt_svc *svc)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return service_signal(svc, MON_CLI_METHOD_ROTATE);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozekstatic int service_signal_clear_memcache(struct mt_svc *svc)
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher return service_signal(svc, MON_CLI_METHOD_CLEAR_MEMCACHE);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int service_signal_clear_enum_cache(struct mt_svc *svc)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return service_signal(svc, MON_CLI_METHOD_CLEAR_ENUM_CACHE);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int check_domain_ranges(struct sss_domain_info *domains)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct sss_domain_info *dom = domains, *other = NULL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (dom->id_max && dom->id_min > dom->id_max) {
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek ("Domain '%s' does not have a valid ID range\n", dom->name));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher id_max = MIN((dom->id_max ? dom->id_max : UINT32_MAX),
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher (other->id_max ? other->id_max : UINT32_MAX));
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek ("Domains '%s' and '%s' overlap in range %u - %u\n",
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic int check_local_domain_unique(struct sss_domain_info *domains)
7a14e8f66c0e932fe2954d792614a3b61d444bd1Jakub Hrozekstatic errno_t add_implicit_services(struct confdb_ctx *cdb, TALLOC_CTX *mem_ctx,
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek bool add_pac = false;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n"));
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, ("No domains configured!\n"));
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek conf_path = talloc_asprintf(tmp_ctx, CONFDB_DOMAIN_PATH_TMPL,
7a14e8f66c0e932fe2954d792614a3b61d444bd1Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, ("talloc_asprintf failed.\n"));
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher ret = confdb_get_string(cdb, tmp_ctx, conf_path,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher CONFDB_DOMAIN_ID_PROVIDER, NULL, &id_provider);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_OP_FAILURE, ("id_provider is not set for "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "domain [%s], trying next domain.\n", domain_names[c]));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (strcasecmp(id_provider, "IPA") == 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_OP_FAILURE, ("Failed to get id_provider for " \
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher "domain [%s], trying next domain.\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (BUILD_WITH_PAC_RESPONDER && add_pac &&
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher !string_in_list("pac", *_services, false)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = add_string_to_list(mem_ctx, "pac", _services);
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher DEBUG(SSSDBG_OP_FAILURE, ("add_string_to_list failed.\n"));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic char *check_services(char **services)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const char *known_services[] = { "nss", "pam", "sudo", "autofs", "ssh",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Check if services we are about to start are in the list if known */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (i = 0; services[i]; i++) {
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher if (strcasecmp(services[i], known_services[ii]) == 0) {
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher ctx->service_id_timeout = timeout_seconds * 1000; /* service_id_timeout is in ms */
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher ret = confdb_get_string_as_list(ctx->cdb, ctx->service_ctx,
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher ret = add_implicit_services(ctx->cdb, ctx->service_ctx, &ctx->services);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, ("Failed to add implicit configured " \
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek "services. Some functionality might " \
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher "be missing"));
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher DEBUG(0, ("Invalid service %s\n", badsrv));
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher for (i = 0; ctx->services[i] != NULL; i++) {
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher ret = confdb_get_domains(ctx->cdb, &ctx->domains);
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher ret = check_local_domain_unique(ctx->domains);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek DEBUG(0, ("More than one local domain configured.\n"));
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher /* Check UID/GID overlaps */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic errno_t get_ping_config(struct mt_ctx *ctx, const char *path,
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher ("Failed to get ping timeout for '%s'\n", svc->name));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* 'timeout = 0' should be translated to the default */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ("Time between service pings for [%s]: [%d]\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ("Failed to get kill timeout for %s\n", svc->name));
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* 'force_timeout = 0' should be translated to the default */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ("Time between SIGTERM and SIGKILL for [%s]: [%d]\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int get_service_config(struct mt_ctx *ctx, const char *name,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher talloc_set_destructor((TALLOC_CTX *)svc, svc_destructor);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek path = talloc_asprintf(svc, CONFDB_SERVICE_PATH_TMPL, svc->name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = confdb_get_string(ctx->cdb, svc, path,
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher DEBUG(0,("Failed to start service '%s'\n", svc->name));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher svc, "%s/sssd_%s", SSSD_LIBEXEC_PATH, svc->name
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek if (cmdline_debug_level != SSSDBG_UNRESOLVED) {
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher svc->command, " -d %#.4x", cmdline_debug_level
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek if (cmdline_debug_timestamps != SSSDBG_TIMESTAMP_UNRESOLVED) {
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher svc->command, " --debug-timestamps=%d", cmdline_debug_timestamps
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek if (cmdline_debug_microseconds != SSSDBG_MICROSECONDS_UNRESOLVED) {
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher ("Failed to get ping timeouts for %s\n", svc->name));
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher ret = get_service_config(ctx, name, &svc);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher DEBUG(0,("Failed to start service '%s'\n", svc->name));
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagherstatic int get_provider_config(struct mt_ctx *ctx, const char *name,
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek talloc_set_destructor((TALLOC_CTX *)svc, svc_destructor);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher svc->identity = talloc_asprintf(svc, "%%BE_%s", svc->name);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek path = talloc_asprintf(svc, CONFDB_DOMAIN_PATH_TMPL, name);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher ret = confdb_get_string(ctx->cdb, svc, path,
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek DEBUG(0, ("Failed to find ID provider from [%s] configuration\n", name));
056302a92862fda16351d7192600746746f38e5dStephen Gallagher DEBUG(0, ("Failed to find command from [%s] configuration\n", name));
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher ("Failed to get ping timeouts for %s\n", svc->name));
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher /* if no provider is present do not run the domain */
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher /* if there are no custom commands, build a default one */
45db68ae27147955a4be4c2c772041824c0dc00fStephen Gallagher svc, "%s/sssd_be --domain %s", SSSD_LIBEXEC_PATH, svc->name
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek if (cmdline_debug_level != SSSDBG_UNRESOLVED) {
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek if (cmdline_debug_timestamps != SSSDBG_TIMESTAMP_UNRESOLVED) {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek svc->command, " --debug-timestamps=%d", cmdline_debug_timestamps
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek if (cmdline_debug_microseconds != SSSDBG_MICROSECONDS_UNRESOLVED) {
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagherstatic int add_new_provider(struct mt_ctx *ctx,
64a424ec1b268427822c646f7781e26e56c197f6Jakub Hrozek const char *name,
7797e361155f7ce937085fd98e360469d7baf1b6Jakub Hrozek DEBUG(0, ("Could not get provider configuration for [%s]\n",
64a424ec1b268427822c646f7781e26e56c197f6Jakub Hrozek /* The LOCAL provider requires no back-end currently
64a424ec1b268427822c646f7781e26e56c197f6Jakub Hrozek * We'll add it to the service list, but we don't need
64a424ec1b268427822c646f7781e26e56c197f6Jakub Hrozek * to poll it.
64a424ec1b268427822c646f7781e26e56c197f6Jakub Hrozek DEBUG(0,("Failed to start service '%s'\n", svc->name));
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozekstatic void monitor_hup(struct tevent_context *ev,
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher struct mt_ctx *ctx = talloc_get_type(private_data, struct mt_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Send D-Bus message to other services to rotate their logs.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * NSS service receives also message to clear memory caches. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for(cur_svc = ctx->svc_list; cur_svc; cur_svc = cur_svc->next) {
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher if (!strcmp(NSS_SBUS_SERVICE_NAME, cur_svc->name)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (!strcmp(SSS_AUTOFS_SBUS_SERVICE_NAME, cur_svc->name)) {
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek ("Error removing pidfile! (%d [%s])\n", ret, strerror(ret)));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void monitor_quit(struct mt_ctx *mt_ctx, int ret)
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher DEBUG(SSSDBG_IMPORTANT_INFO, ("Returned with: %d\n", ret));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Kill all of our known children manually */
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher /* The local provider has no PID */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(1, ("Terminating [%s][%d]\n", svc->name, svc->pid));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(1, ("Couldn't kill [%s][%d]: [%s]\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher pid = waitpid(svc->pid, &status, WNOHANG);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* An error occurred while waiting */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(0, ("[%d][%s] while waiting for [%s]\n",
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher /* Forcibly kill this child */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher } else if (pid != 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(1, ("Child [%s] exited gracefully\n", svc->name));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(1, ("Child [%s] terminated with a signal\n", svc->name));
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher DEBUG(0, ("Child [%s] did not exit cleanly\n", svc->name));
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher /* Forcibly kill this child */
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek /* Sleep 10ms and try again */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Kill any remaining children in our process group, just in case
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * we have any leftover children we don't expect. For example, if
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek * a krb5_child or ldap_child is running at the same moment.
056302a92862fda16351d7192600746746f38e5dStephen Gallagherstatic void monitor_quit_signal(struct tevent_context *ev,
056302a92862fda16351d7192600746746f38e5dStephen Gallagher struct mt_ctx *mt_ctx = talloc_get_type(private_data, struct mt_ctx);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, ("Received shutdown command\n"));
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher DEBUG(SSSDBG_IMPORTANT_INFO, ("Monitor received %s: terminating "
056302a92862fda16351d7192600746746f38e5dStephen Gallagherstatic void signal_res_init(struct mt_ctx *monitor)
056302a92862fda16351d7192600746746f38e5dStephen Gallagher DEBUG(SSSDBG_OP_FAILURE, ("Reloading Resolv.conf.\n"));
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher for(cur_svc = monitor->svc_list; cur_svc; cur_svc = cur_svc->next) {
056302a92862fda16351d7192600746746f38e5dStephen Gallagherstatic void signal_offline(struct tevent_context *ev,
056302a92862fda16351d7192600746746f38e5dStephen Gallagher monitor = talloc_get_type(private_data, struct mt_ctx);
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher ("Signaling providers to go offline immediately.\n"));
056302a92862fda16351d7192600746746f38e5dStephen Gallagher /* Signal all providers to immediately go offline */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek for(cur_svc = monitor->svc_list; cur_svc; cur_svc = cur_svc->next) {
056302a92862fda16351d7192600746746f38e5dStephen Gallagher /* Don't signal services, only providers */
056302a92862fda16351d7192600746746f38e5dStephen Gallagherstatic void signal_offline_reset(struct tevent_context *ev,
64a424ec1b268427822c646f7781e26e56c197f6Jakub Hrozek monitor = talloc_get_type(private_data, struct mt_ctx);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek ("Signaling providers to reset offline immediately.\n"));
bf9abef629707167d39fcc92ec9c18a6244b27b8Jakub Hrozek for(cur_svc = monitor->svc_list; cur_svc; cur_svc = cur_svc->next) {
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek struct mt_ctx *mon = talloc_get_type(mem, struct mt_ctx);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* zero out references in svcs so that they don't try
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek * to access the monitor context on process shutdown */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek for (svc = mon->svc_list; svc; svc = svc->next) {
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozekstatic errno_t load_configuration(TALLOC_CTX *mem_ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher talloc_set_destructor((TALLOC_CTX *)ctx, monitor_ctx_destructor);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek cdb_file = talloc_asprintf(ctx, "%s/%s", DB_PATH, CONFDB_FILE);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(0,("The confdb initialization failed\n"));
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* Initialize the CDB from the configuration file */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* First-time setup */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* Purge any existing confdb in case an old
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * misconfiguration gets in the way
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = confdb_init(ctx, &ctx->cdb, cdb_file);
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher DEBUG(0,("The confdb initialization failed\n"));
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* Load special entries */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(0, ("Unable to load special entries into confdb\n"));
7a14e8f66c0e932fe2954d792614a3b61d444bd1Jakub Hrozek DEBUG(0, ("Fatal error initializing confdb\n"));
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher ret = confdb_init_db(config_file, ctx->cdb);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher DEBUG(0, ("ConfDB initialization has failed [%s]\n",
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* Validate the configuration in the database */
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher /* Read in the monitor's configuration */
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekstatic void process_config_file(struct tevent_context *ev,
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozekstatic void config_file_changed(struct tevent_context *ev,
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek file_ctx = talloc_get_type(data, struct config_file_ctx);
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek /* Skip updating. It's already queued for update.
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek /* We will queue the file for update in one second.
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek * This way, if there is a script writing to the file
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek * repeatedly, we won't be attempting to update multiple
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek te = tevent_add_timer(ev, ev, tv, process_config_file, file_ctx);
7a14e8f66c0e932fe2954d792614a3b61d444bd1Jakub Hrozek DEBUG(0, ("Unable to queue config file update! Exiting.\n"));
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozekstatic void rewatch_config_file(struct tevent_context *ev,
7a14e8f66c0e932fe2954d792614a3b61d444bd1Jakub Hrozekstatic void process_config_file(struct tevent_context *ev,
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher event_size = sizeof(struct inotify_event);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher file_ctx = talloc_get_type(ptr, struct config_file_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(1, ("Processing config file changes\n"));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher len = sss_atomic_read_s(file_ctx->mt_ctx->inotify_fd, buf, event_size);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek ("Critical error reading inotify file descriptor [%d]: %s\n",
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek /* Read in the name, even though we don't use it,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek * so that read ptr is in the right place
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher len = sss_atomic_read_s(file_ctx->mt_ctx->inotify_fd, name, in_event->len);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ("Critical error reading inotify file descriptor [%d]: %s\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (cb = file_ctx->callbacks; cb; cb = cb->next) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Some text editors will move a new file on top of the
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * existing one instead of modifying it. In this case,
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek * the kernel will send us an IN_IGNORE signal.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * We will try to open a new watch descriptor on the
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(0, ("Could not restore inotify watch. Quitting!\n"));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher tev = tevent_add_timer(ev, rw_ctx, tv, rewatch_config_file, rw_ctx);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek DEBUG(0, ("Could not restore inotify watch. Quitting!\n"));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Tell the monitor to signal the children */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghererrno_t monitor_config_file_fallback(TALLOC_CTX *mem_ctx,
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagherstatic void rewatch_config_file(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rw_ctx = talloc_get_type(ptr, struct rewatch_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Retry six times at five-second intervals before giving up */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ("Could not restore inotify watch. Switching to polling!\n"));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher err = monitor_config_file_fallback(file_ctx->parent_ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* A new callback was created in monitor_config_file_fallback()*/
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher cb->wd = inotify_add_watch(file_ctx->mt_ctx->inotify_fd,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ("Could not add inotify watch for file [%s]. Error [%d:%s]\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher tev = tevent_add_timer(ev, ev, tv, rewatch_config_file, rw_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ("Could not restore inotify watch. Quitting!\n"));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Tell the monitor to signal the children */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void poll_config_file(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher file_ctx = talloc_get_type(ptr,struct config_file_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (cb = file_ctx->callbacks; cb; cb = cb->next) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(0, ("Could not stat file [%s]. Error [%d:%s]\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* TODO: If the config file is missing, should we shut down? */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* Parse the configuration file and signal the children */
056302a92862fda16351d7192600746746f38e5dStephen Gallagher /* Note: this will fire if the modification time changes into the past
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher * as well as the future.
056302a92862fda16351d7192600746746f38e5dStephen Gallagher /* Tell the monitor to signal the children */
056302a92862fda16351d7192600746746f38e5dStephen Gallagher file_ctx->timer = tevent_add_timer(ev, file_ctx->parent_ctx, tv,
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher DEBUG(0, ("Error: Config file no longer monitored for changes!\n"));
056302a92862fda16351d7192600746746f38e5dStephen Gallagherstatic int try_inotify(struct config_file_ctx *file_ctx, const char *filename,
056302a92862fda16351d7192600746746f38e5dStephen Gallagher /* Monitoring the file descriptor should be global */
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher /* Set up inotify to monitor the config file for changes */
056302a92862fda16351d7192600746746f38e5dStephen Gallagher file_ctx->mt_ctx->inotify_fd = inotify_init();
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek DEBUG(0, ("Could not initialize inotify, error [%d:%s]\n",
056302a92862fda16351d7192600746746f38e5dStephen Gallagher fd_args = fcntl(file_ctx->mt_ctx->inotify_fd, F_GETFL, NULL);
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek /* Could not set nonblocking */
056302a92862fda16351d7192600746746f38e5dStephen Gallagher ret = fcntl(file_ctx->mt_ctx->inotify_fd, F_SETFL, fd_args);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher /* Could not set nonblocking */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* Add the inotify file descriptor to the TEvent context */
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek tfd = tevent_add_fd(file_ctx->mt_ctx->ev, file_ctx,
056302a92862fda16351d7192600746746f38e5dStephen Gallagher cb = talloc_zero(file_ctx, struct config_file_callback);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher cb->wd = inotify_add_watch(file_ctx->mt_ctx->inotify_fd,
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher DEBUG(0, ("Could not add inotify watch for file [%s]. Error [%d:%s]\n",
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagherstatic int monitor_config_file(TALLOC_CTX *mem_ctx,
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher ("file [%s] is missing. Will not update online status "
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher ("Could not stat file [%s]. Error [%d:%s]\n",
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher ctx->file_ctx = talloc_zero(mem_ctx, struct config_file_ctx);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher /* Could not monitor file with inotify, fall back to polling */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek ret = monitor_config_file_fallback(mem_ctx, ctx, file, fn, true);
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallaghererrno_t monitor_config_file_fallback(TALLOC_CTX *mem_ctx,
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek const char *file,
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek ("file [%s] is missing. Will not update online status "
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek ("Could not stat file [%s]. Error [%d:%s]\n",
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek cb = talloc_zero(ctx->file_ctx, struct config_file_callback);
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher ctx->file_ctx->timer = tevent_add_timer(ctx->ev, mem_ctx, tv,
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher /* Set up the environment variable for the Kerberos Replay Cache */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (strcmp(rcachedir, KRB5_RCACHE_DIR_DISABLE) != 0)
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher ret = setenv("KRB5RCACHEDIR", rcachedir, 1);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek ("Unable to set KRB5RCACHEDIR: %s."
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Will attempt to use libkrb5 defaults\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Set up an event handler for a SIGHUP */
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher tes = tevent_add_signal(ctx->ev, ctx, SIGHUP, 0,
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher /* Set up an event handler for a SIGINT */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher tes = tevent_add_signal(ctx->ev, ctx, SIGINT, 0,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Set up an event handler for a SIGTERM */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek tes = tevent_add_signal(ctx->ev, ctx, SIGTERM, 0,
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* Handle SIGUSR1 (tell all providers to go offline) */
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher tes = tevent_add_signal(ctx->ev, ctx, SIGUSR1, 0,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Handle SIGUSR2 (tell all providers to go reset offline) */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek tes = tevent_add_signal(ctx->ev, ctx, SIGUSR2, 0,
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher /* Set up the SIGCHLD handler */
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher ret = sss_sigchld_init(ctx, ctx->ev, &ctx->sigchld_ctx);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek This feature is incomplete and can leave the SSSD in a bad state if the
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher config file is changed while the SSSD is running.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher Uncomment this once the backends are honoring reloadConfig()
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* Watch for changes to the confdb config file */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = monitor_config_file(ctx, ctx, config_file, monitor_signal_reconf,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Watch for changes to the DNS resolv.conf */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = monitor_config_file(ctx, ctx, RESOLV_CONF_PATH,
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* Avoid a startup race condition between process.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * We need to handle DB upgrades or DB creation only
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher * in one process before all other start.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = sysdb_init(tmp_ctx, ctx->domains, true);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* Initialize D-BUS Server
bdd205037059e56484de3174951b22ff8f0f79f8Stephen Gallagher * The monitor will act as a D-BUS server for all
bdd205037059e56484de3174951b22ff8f0f79f8Stephen Gallagher * SSSD processes */
bdd205037059e56484de3174951b22ff8f0f79f8Stephen Gallagher ret = setup_netlink(ctx, ctx->ev, network_status_change_cb,
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher DEBUG(2, ("Cannot set up listening for network notifications\n"));
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher /* start providers */
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher for (dom = ctx->domains; dom; dom = get_next_domain(dom, false)) {
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher ret = add_new_provider(ctx, dom->name, 0);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* now set the services stratup timeout *
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher * (responders will be started automatically when all
486237ee009f1d84fc4c85665dce80ade76f7079Stephen Gallagher * providers are up and running or when the tomeout
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek /* No providers start services immediately
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher * Normally this means only LOCAL is configured */
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher add_new_service(ctx, ctx->services[i], 0);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagherstatic void init_timeout(struct tevent_context *ev,
7a14e8f66c0e932fe2954d792614a3b61d444bd1Jakub Hrozek DEBUG(2, ("Client timed out before Identification!\n"));
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher mini = talloc_get_type(ptr, struct mon_init_conn);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek * monitor_service_init
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek * Set up a timeout function and temporary connection structure.
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek * If the client does not identify before the timeout kicks in,
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek * the client is forcibly disconnected.
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozekstatic int monitor_service_init(struct sbus_connection *conn, void *data)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_TRACE_FUNC, ("Initializing D-BUS Service\n"));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx = talloc_get_type(data, struct mt_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mini = talloc(conn, struct mon_init_conn);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* 10 seconds should be plenty */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mini->timeout = tevent_add_timer(ctx->ev, mini, tv, init_timeout, mini);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* service_send_ping
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek * this function send a dbus ping to a service.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * It returns EOK if all is fine or ENXIO if the connection is
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher * not available (either not yet set up or teared down).
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * Returns e generic error in other cases.
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozekstatic int service_send_ping(struct mt_svc *svc)
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher DEBUG(8, ("Service not yet initialized\n"));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * Set up identity request
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * This should be a well-known path and method
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * for all services
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void ping_check(DBusPendingCall *pending, void *data)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher svc = talloc_get_type(data, struct mt_svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* The connection probably went down before the callback fired.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * Not much we can do. */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid service pointer.\n"));
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek reply = dbus_pending_call_steal_reply(pending);
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher /* reply should never be null. This function shouldn't be called
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * until reply is valid or timeout has occurred. If reply is NULL
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * here, something is seriously wrong and we should bail out.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(0, ("A reply callback was called but no reply was received"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher " and no timeout occurred\n"));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Destroy this connection */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* ok peer replied,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * make sure we reset the failure counter in the service structure */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(4,("Service %s replied to ping\n", svc->name));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher dbus_error_name = dbus_message_get_error_name(reply);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Increase failed pong count */
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher if (strnlen(dbus_error_name, len + 1) == len
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher && strncmp(dbus_error_name, DBUS_ERROR_NO_REPLY, len) == 0) {
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek ("A service PING timed out on [%s]. "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Attempt [%d]\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ("A service PING returned an error [%s], closing connection.\n",
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher /* Falling through to default intentionally*/
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * Timeout or other error occurred or something
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek * unexpected happened.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * It doesn't matter which, because either way we
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher * know that this connection isn't trustworthy.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * We'll destroy it now.
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagherstatic void service_startup_handler(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int start_service(struct mt_svc *svc)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(4,("Queueing service %s for startup\n", svc->name));
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* Add a timed event to start up the service.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * We have to do this in order to avoid a race
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * condition where the service being started forks
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * and attempts to connect to the SBUS before
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * the monitor is serving it.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher te = tevent_add_timer(svc->mt_ctx->ev, svc, tv,
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher DEBUG(0, ("Unable to queue service %s for startup\n", svc->name));
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagherstatic void mt_svc_exit_handler(int pid, int wait_status, void *pvt);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void service_startup_handler(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mt_svc = talloc_get_type(ptr, struct mt_svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(0, ("Could not fork child to start service [%s]. "
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher /* Handle process exit */
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher ("Could not register sigchld handler.\n"));
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher /* Should we exit here? For now, we'll hope this
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher * child never dies, because we can't restart it.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DLIST_ADD(mt_svc->mt_ctx->svc_list, mt_svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* If we are here, exec() has failed
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * Print errno and abort quickly */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(0,("Could not exec %s, reason: %s\n", mt_svc->command, strerror(errno)));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* We have to call _exit() instead of exit() here
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * because a bug in D-BUS will cause the server to
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * close its socket at exit() */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void mt_svc_restart(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher svc = talloc_get_type(ptr, struct mt_svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_TRACE_FUNC, ("Scheduling service %s for restart %d\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher add_new_service(svc->mt_ctx, svc->name, svc->restarts + 1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher } else if (svc->type == MT_SVC_PROVIDER) {
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher add_new_provider(svc->mt_ctx, svc->name, svc->restarts + 1);
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher /* Invalid type? */
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher ("BUG: Invalid child process type [%d]\n", svc->type));
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher /* Free the old service (which will also remove it
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher * from the child list)
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagherstatic void mt_svc_exit_handler(int pid, int wait_status, void *pvt)
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher struct mt_svc *svc = talloc_get_type(pvt, struct mt_svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ("Child [%s] exited with code [%d]\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ("Child [%s] terminated with signal [%d]\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(0, ("Child [%s] did not exit cleanly\n", svc->name));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Forcibly kill this child, just in case */
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher /* Return and let us get caught by another
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * call to the SIGCHLD handler
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((now - svc->last_restart) > MONITOR_RESTART_CNT_INTERVAL_RESET) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Restart the service */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (svc->restarts > MONITOR_MAX_SVC_RESTARTS) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ("Process [%s], definitely stopped!\n", svc->name));
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher /* exit with error */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* restarts are schedule after 0, 2, 4 seconds */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (restart_delay > MONITOR_MAX_RESTART_DELAY) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher restart_delay = MONITOR_MAX_RESTART_DELAY;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher tv = tevent_timeval_current_ofs(restart_delay, 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher te = tevent_add_timer(svc->mt_ctx->ev, svc, tv, mt_svc_restart, svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Nothing much we can do */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory?!\n"));
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek {"daemon", 'D', POPT_ARG_NONE, &opt_daemon, 0, \
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher {"interactive", 'i', POPT_ARG_NONE, &opt_interactive, 0, \
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher _("Run interactive (not a daemon)"), NULL}, \
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher {"config", 'c', POPT_ARG_STRING, &opt_config_file, 0, \
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher _("Specify a non-default config file"), NULL}, \
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher {"version", '\0', POPT_ARG_NONE, &opt_version, 0, \
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher _("Print version number and exit"), NULL }, \
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Set debug level to invalid value so we can deside if -d 0 was used. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher pc = poptGetContext(argv[0], argc, argv, long_options, 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher fprintf(stderr, "\nInvalid option %s: %s\n\n",
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher puts(VERSION""DISTRO_VERSION""PRERELEASE_VERSION);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* If the level or timestamps was passed at the command-line, we want
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher * to save it and pass it to the children later.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher cmdline_debug_timestamps = debug_timestamps;
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek cmdline_debug_microseconds = debug_microseconds;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher fprintf(stderr, "Option -i|--interactive is not allowed together with -D|--daemon\n");
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE, ("Running under %d, must be root\n", uid));
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher sss_log(SSS_LOG_ALERT, "sssd must be run as root");
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher if (opt_interactive) flags |= FLAGS_INTERACTIVE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher config_file = talloc_strdup(tmp_ctx, opt_config_file);
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher config_file = talloc_strdup(tmp_ctx, CONFDB_DEFAULT_CONFIG_FILE);
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher /* we want a pid file check */
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher /* Open before server_setup() does to have logging
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher * during configuration checking */
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher /* Do this before all the forks, it sets the session key ring so all
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher * keys are private to the daemon and cannot be read by any other process
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher /* make a new session */
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher "Could not create private keyring session. "
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher "If you store password there they may be easily accessible "
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher "to the root user. (%d, %s)", errno, strerror(errno));
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher ret = keyctl_setperm(KEY_SPEC_SESSION_KEYRING, KEY_POS_ALL);
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher "Could not set permissions on private keyring. "
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher "If you store password there they may be easily accessible "
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher "to the root user. (%d, %s)", errno, strerror(errno));
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher /* Warn if nscd seems to be running */
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher ret = check_file(NSCD_SOCKET_PATH, -1, -1, -1, CHECK_SOCK, NULL, false);
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher "nscd socket was detected. Nscd caching capabilities "
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher "may conflict with SSSD for users and groups. It is "
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher "recommended not to run nscd in parallel with SSSD, unless "
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher "nscd is configured not to cache the passwd, group and "
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher "netgroup nsswitch maps.");
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher /* Parse config file, fail if cannot be done */
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher ret = load_configuration(tmp_ctx, config_file, &monitor);
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher ("Insufficient permissions to read configuration file.\n"));
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher ("SSSD couldn't load the configuration database.\n"));
7a14e8f66c0e932fe2954d792614a3b61d444bd1Jakub Hrozek "SSSD couldn't load the configuration database [%d]: %s.\n",
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher /* set up things like debug , signals, daemonization, etc... */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher monitor->conf_path = CONFDB_MONITOR_CONF_ENTRY;
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher ret = server_setup(MONITOR_NAME, flags, monitor->conf_path, &main_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher monitor->parent_pid = main_ctx->parent_pid;
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek /* loop on main */