monitor.c revision d19c4785215305e6eb5f2fa2fc503a2ba50d3f10
f072359f493a5209335799da85ac16d6a273303bgryzor/*
f072359f493a5209335799da85ac16d6a273303bgryzor SSSD
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor Service monitor
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor Copyright (C) Simo Sorce 2008
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor This program is free software; you can redistribute it and/or modify
f072359f493a5209335799da85ac16d6a273303bgryzor it under the terms of the GNU General Public License as published by
f072359f493a5209335799da85ac16d6a273303bgryzor the Free Software Foundation; either version 3 of the License, or
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen (at your option) any later version.
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen This program is distributed in the hope that it will be useful,
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen but WITHOUT ANY WARRANTY; without even the implied warranty of
f072359f493a5209335799da85ac16d6a273303bgryzor MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f072359f493a5209335799da85ac16d6a273303bgryzor GNU General Public License for more details.
f072359f493a5209335799da85ac16d6a273303bgryzor
d229f940abfb2490dee17979e9a5ff31b7012eb5rbowen You should have received a copy of the GNU General Public License
3f08db06526d6901aa08c110b5bc7dde6bc39905nd along with this program. If not, see <http://www.gnu.org/licenses/>.
f072359f493a5209335799da85ac16d6a273303bgryzor*/
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor#include "util/util.h"
3f08db06526d6901aa08c110b5bc7dde6bc39905nd#include "util/child_common.h"
f072359f493a5209335799da85ac16d6a273303bgryzor#include <sys/types.h>
f072359f493a5209335799da85ac16d6a273303bgryzor#include <sys/wait.h>
f072359f493a5209335799da85ac16d6a273303bgryzor#include <sys/time.h>
f072359f493a5209335799da85ac16d6a273303bgryzor#include <sys/param.h>
f072359f493a5209335799da85ac16d6a273303bgryzor#include <time.h>
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung#include <string.h>
f072359f493a5209335799da85ac16d6a273303bgryzor#ifdef HAVE_SYS_INOTIFY_H
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic#include <sys/inotify.h>
f072359f493a5209335799da85ac16d6a273303bgryzor#endif
f072359f493a5209335799da85ac16d6a273303bgryzor#include <sys/types.h>
f072359f493a5209335799da85ac16d6a273303bgryzor#include <sys/stat.h>
f072359f493a5209335799da85ac16d6a273303bgryzor#include <unistd.h>
f072359f493a5209335799da85ac16d6a273303bgryzor#include <fcntl.h>
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor/* Needed for res_init() */
f072359f493a5209335799da85ac16d6a273303bgryzor#include <netinet/in.h>
f072359f493a5209335799da85ac16d6a273303bgryzor#include <arpa/nameser.h>
f072359f493a5209335799da85ac16d6a273303bgryzor#include <resolv.h>
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor#include "popt.h"
f072359f493a5209335799da85ac16d6a273303bgryzor#include "tevent.h"
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic#include "confdb/confdb.h"
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic#include "confdb/confdb_setup.h"
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic#include "collection.h"
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic#include "ini_config.h"
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic#include "db/sysdb.h"
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic#include "monitor/monitor.h"
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic#include "dbus/dbus.h"
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic#include "sbus/sssd_dbus.h"
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic#include "monitor/monitor_interfaces.h"
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic#include "responder/nss/nsssrv.h"
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic#ifdef USE_KEYRING
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic#include <keyutils.h>
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic#endif
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic/* ping time cannot be less then once every few seconds or the
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic * monitor will get crazy hammering children with messages */
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic#define MONITOR_DEF_PING_TIME 10
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic/* terminate the child after this interval by default if it
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic * doesn't shutdown on receiving SIGTERM */
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic#define MONITOR_DEF_FORCE_TIME 60
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic/* name of the monitor server instance */
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic#define MONITOR_NAME "sssd"
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic#define SSSD_PIDFILE_PATH PID_PATH"/"MONITOR_NAME".pid"
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic/* Special value to leave the Kerberos Replay Cache set to use
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic * the libkrb5 defaults
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic */
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic#define KRB5_RCACHE_DIR_DISABLE "__LIBKRB5_DEFAULTS__"
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalicint cmdline_debug_level;
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalicint cmdline_debug_timestamps;
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalicint cmdline_debug_microseconds;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalicstruct svc_spy;
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalicenum mt_svc_type {
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic MT_SVC_SERVICE,
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim MT_SVC_PROVIDER
f072359f493a5209335799da85ac16d6a273303bgryzor};
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstruct mt_svc {
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_svc *prev;
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_svc *next;
f072359f493a5209335799da85ac16d6a273303bgryzor enum mt_svc_type type;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor struct sbus_connection *conn;
f072359f493a5209335799da85ac16d6a273303bgryzor struct svc_spy *conn_spy;
f072359f493a5209335799da85ac16d6a273303bgryzor
45a544a8bb3fa1f95e5edac9fb3e723e2bb7001drbowen struct mt_ctx *mt_ctx;
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh
f072359f493a5209335799da85ac16d6a273303bgryzor char *provider;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim char *command;
f072359f493a5209335799da85ac16d6a273303bgryzor char *name;
f072359f493a5209335799da85ac16d6a273303bgryzor char *identity;
4c47688d73a9a5ef2735cd84f334b8eb814c74f0igalic pid_t pid;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor int ping_time;
f072359f493a5209335799da85ac16d6a273303bgryzor int kill_time;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor bool svc_started;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor int restarts;
f072359f493a5209335799da85ac16d6a273303bgryzor time_t last_restart;
f072359f493a5209335799da85ac16d6a273303bgryzor int failed_pongs;
f072359f493a5209335799da85ac16d6a273303bgryzor DBusPendingCall *pending;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor int debug_level;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor struct tevent_timer *ping_ev;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor struct sss_child_ctx *child_ctx;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor struct tevent_timer *sigkill_ev;
f072359f493a5209335799da85ac16d6a273303bgryzor};
ee649f9236fe7fcf255bbfa11f2cce080f996521sf
f072359f493a5209335799da85ac16d6a273303bgryzorstruct config_file_callback {
f072359f493a5209335799da85ac16d6a273303bgryzor int wd;
f072359f493a5209335799da85ac16d6a273303bgryzor int retries;
f072359f493a5209335799da85ac16d6a273303bgryzor monitor_reconf_fn fn;
f072359f493a5209335799da85ac16d6a273303bgryzor char *filename;
f072359f493a5209335799da85ac16d6a273303bgryzor time_t modified;
f072359f493a5209335799da85ac16d6a273303bgryzor struct config_file_callback *next;
f072359f493a5209335799da85ac16d6a273303bgryzor struct config_file_callback *prev;
f072359f493a5209335799da85ac16d6a273303bgryzor};
ac2a72149b423e2e84596098d7e47af88ebd215asf
f072359f493a5209335799da85ac16d6a273303bgryzorstruct config_file_ctx {
f072359f493a5209335799da85ac16d6a273303bgryzor TALLOC_CTX *parent_ctx;
f072359f493a5209335799da85ac16d6a273303bgryzor struct tevent_timer *timer;
f072359f493a5209335799da85ac16d6a273303bgryzor bool needs_update;
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_ctx *mt_ctx;
f072359f493a5209335799da85ac16d6a273303bgryzor struct config_file_callback *callbacks;
f072359f493a5209335799da85ac16d6a273303bgryzor};
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstruct mt_ctx {
f072359f493a5209335799da85ac16d6a273303bgryzor struct tevent_context *ev;
f072359f493a5209335799da85ac16d6a273303bgryzor struct confdb_ctx *cdb;
f072359f493a5209335799da85ac16d6a273303bgryzor TALLOC_CTX *domain_ctx; /* Memory context for domain list */
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic struct sss_domain_info *domains;
f072359f493a5209335799da85ac16d6a273303bgryzor TALLOC_CTX *service_ctx; /* Memory context for services */
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic char **services;
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic int num_services;
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic int started_services;
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic struct mt_svc *svc_list;
f072359f493a5209335799da85ac16d6a273303bgryzor struct sbus_connection *sbus_srv;
f072359f493a5209335799da85ac16d6a273303bgryzor struct config_file_ctx *file_ctx;
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh int inotify_fd;
f072359f493a5209335799da85ac16d6a273303bgryzor int service_id_timeout;
f072359f493a5209335799da85ac16d6a273303bgryzor bool check_children;
f072359f493a5209335799da85ac16d6a273303bgryzor bool services_started;
f072359f493a5209335799da85ac16d6a273303bgryzor struct netlink_ctx *nlctx;
48c64aeceef385e19025b384bd719b2a9789592dnd const char *conf_path;
f072359f493a5209335799da85ac16d6a273303bgryzor struct sss_sigchild_ctx *sigchld_ctx;
f072359f493a5209335799da85ac16d6a273303bgryzor bool is_daemon;
f072359f493a5209335799da85ac16d6a273303bgryzor pid_t parent_pid;
f072359f493a5209335799da85ac16d6a273303bgryzor};
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int start_service(struct mt_svc *mt_svc);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int monitor_service_init(struct sbus_connection *conn, void *data);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int service_send_ping(struct mt_svc *svc);
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int service_signal_reset_offline(struct mt_svc *svc);
f072359f493a5209335799da85ac16d6a273303bgryzorstatic void ping_check(DBusPendingCall *pending, void *data);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic void set_tasks_checker(struct mt_svc *srv);
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int monitor_kill_service (struct mt_svc *svc);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int get_service_config(struct mt_ctx *ctx, const char *name,
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_svc **svc_cfg);
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int get_provider_config(struct mt_ctx *ctx, const char *name,
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_svc **svc_cfg);
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int add_new_service(struct mt_ctx *ctx,
f072359f493a5209335799da85ac16d6a273303bgryzor const char *name,
f072359f493a5209335799da85ac16d6a273303bgryzor int restarts);
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int add_new_provider(struct mt_ctx *ctx,
f072359f493a5209335799da85ac16d6a273303bgryzor const char *name,
f072359f493a5209335799da85ac16d6a273303bgryzor int restarts);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int mark_service_as_started(struct mt_svc *svc);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int monitor_cleanup(void);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic void network_status_change_cb(void *cb_data)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_svc *iter;
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_ctx *ctx = (struct mt_ctx *) cb_data;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_TRACE_INTERNAL, ("A networking status change detected "
f072359f493a5209335799da85ac16d6a273303bgryzor "signaling providers to reset offline status\n"));
f072359f493a5209335799da85ac16d6a273303bgryzor for (iter = ctx->svc_list; iter; iter = iter->next) {
f072359f493a5209335799da85ac16d6a273303bgryzor /* Don't signal services, only providers */
f072359f493a5209335799da85ac16d6a273303bgryzor if (iter->provider) {
f072359f493a5209335799da85ac16d6a273303bgryzor service_signal_reset_offline(iter);
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor/* dbus_get_monitor_version
f072359f493a5209335799da85ac16d6a273303bgryzor * Return the monitor version over D-BUS */
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int get_monitor_version(DBusMessage *message,
f072359f493a5209335799da85ac16d6a273303bgryzor struct sbus_connection *conn)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor dbus_uint16_t version = MONITOR_VERSION;
f072359f493a5209335799da85ac16d6a273303bgryzor DBusMessage *reply;
f072359f493a5209335799da85ac16d6a273303bgryzor dbus_bool_t ret;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor reply = dbus_message_new_method_return(message);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!reply) return ENOMEM;
f072359f493a5209335799da85ac16d6a273303bgryzor ret = dbus_message_append_args(reply,
f072359f493a5209335799da85ac16d6a273303bgryzor DBUS_TYPE_UINT16, &version,
f072359f493a5209335799da85ac16d6a273303bgryzor DBUS_TYPE_INVALID);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!ret) {
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim dbus_message_unref(reply);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim return EIO;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim /* send reply back */
2d39a41e98476f5235b7c37ce745a4aa0904b1cbrbowen sbus_conn_send_reply(conn, reply);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim dbus_message_unref(reply);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim return EOK;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim}
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjimstruct mon_init_conn {
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim struct mt_ctx *ctx;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim struct sbus_connection *conn;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim struct tevent_timer *timeout;
f072359f493a5209335799da85ac16d6a273303bgryzor};
f072359f493a5209335799da85ac16d6a273303bgryzor
ac2a72149b423e2e84596098d7e47af88ebd215asfstatic int add_svc_conn_spy(struct mt_svc *svc);
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asf/* registers a new client.
ac2a72149b423e2e84596098d7e47af88ebd215asf * if operation is successful also sends back the Monitor version */
ac2a72149b423e2e84596098d7e47af88ebd215asfstatic int client_registration(DBusMessage *message,
ac2a72149b423e2e84596098d7e47af88ebd215asf struct sbus_connection *conn)
ac2a72149b423e2e84596098d7e47af88ebd215asf{
ac2a72149b423e2e84596098d7e47af88ebd215asf dbus_uint16_t version = MONITOR_VERSION;
ac2a72149b423e2e84596098d7e47af88ebd215asf struct mon_init_conn *mini;
ac2a72149b423e2e84596098d7e47af88ebd215asf struct mt_svc *svc;
ac2a72149b423e2e84596098d7e47af88ebd215asf void *data;
ac2a72149b423e2e84596098d7e47af88ebd215asf DBusMessage *reply;
ac2a72149b423e2e84596098d7e47af88ebd215asf DBusError dbus_error;
ac2a72149b423e2e84596098d7e47af88ebd215asf dbus_uint16_t svc_ver;
ac2a72149b423e2e84596098d7e47af88ebd215asf char *svc_name;
ac2a72149b423e2e84596098d7e47af88ebd215asf dbus_bool_t dbret;
ac2a72149b423e2e84596098d7e47af88ebd215asf int ret;
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asf data = sbus_conn_get_private_data(conn);
ac2a72149b423e2e84596098d7e47af88ebd215asf mini = talloc_get_type(data, struct mon_init_conn);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim if (!mini) {
ac2a72149b423e2e84596098d7e47af88ebd215asf DEBUG(0, ("Connection holds no valid init data\n"));
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim return EINVAL;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
ac2a72149b423e2e84596098d7e47af88ebd215asf /* First thing, cancel the timeout */
ac2a72149b423e2e84596098d7e47af88ebd215asf talloc_zfree(mini->timeout);
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asf dbus_error_init(&dbus_error);
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asf dbret = dbus_message_get_args(message, &dbus_error,
ac2a72149b423e2e84596098d7e47af88ebd215asf DBUS_TYPE_STRING, &svc_name,
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim DBUS_TYPE_UINT16, &svc_ver,
ac2a72149b423e2e84596098d7e47af88ebd215asf DBUS_TYPE_INVALID);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim if (!dbret) {
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim DEBUG(1, ("Failed to parse message, killing connection\n"));
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
ac2a72149b423e2e84596098d7e47af88ebd215asf sbus_disconnect(conn);
ac2a72149b423e2e84596098d7e47af88ebd215asf /* FIXME: should we just talloc_zfree(conn) ? */
ac2a72149b423e2e84596098d7e47af88ebd215asf goto done;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim DEBUG(4, ("Received ID registration: (%s,%d)\n", svc_name, svc_ver));
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim /* search this service in the list */
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim svc = mini->ctx->svc_list;
ac2a72149b423e2e84596098d7e47af88ebd215asf while (svc) {
ac2a72149b423e2e84596098d7e47af88ebd215asf ret = strcasecmp(svc->identity, svc_name);
ac2a72149b423e2e84596098d7e47af88ebd215asf if (ret == 0) {
ac2a72149b423e2e84596098d7e47af88ebd215asf break;
ac2a72149b423e2e84596098d7e47af88ebd215asf }
ac2a72149b423e2e84596098d7e47af88ebd215asf svc = svc->next;
ac2a72149b423e2e84596098d7e47af88ebd215asf }
ac2a72149b423e2e84596098d7e47af88ebd215asf if (!svc) {
ac2a72149b423e2e84596098d7e47af88ebd215asf DEBUG(0, ("Unable to find peer [%s] in list of services,"
ac2a72149b423e2e84596098d7e47af88ebd215asf " killing connection!\n", svc_name));
ac2a72149b423e2e84596098d7e47af88ebd215asf sbus_disconnect(conn);
ac2a72149b423e2e84596098d7e47af88ebd215asf /* FIXME: should we just talloc_zfree(conn) ? */
ac2a72149b423e2e84596098d7e47af88ebd215asf goto done;
ac2a72149b423e2e84596098d7e47af88ebd215asf }
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asf /* Fill in svc structure with connection data */
ac2a72149b423e2e84596098d7e47af88ebd215asf svc->conn = mini->conn;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim ret = mark_service_as_started(svc);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim if (ret) {
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim DEBUG(1, ("Failed to mark service [%s]!\n", svc_name));
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim goto done;
ac2a72149b423e2e84596098d7e47af88ebd215asf }
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asf /* reply that all is ok */
ac2a72149b423e2e84596098d7e47af88ebd215asf reply = dbus_message_new_method_return(message);
ac2a72149b423e2e84596098d7e47af88ebd215asf if (!reply) return ENOMEM;
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asf dbret = dbus_message_append_args(reply,
ac2a72149b423e2e84596098d7e47af88ebd215asf DBUS_TYPE_UINT16, &version,
ac2a72149b423e2e84596098d7e47af88ebd215asf DBUS_TYPE_INVALID);
ac2a72149b423e2e84596098d7e47af88ebd215asf if (!dbret) {
ac2a72149b423e2e84596098d7e47af88ebd215asf dbus_message_unref(reply);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim return EIO;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim /* send reply back */
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim sbus_conn_send_reply(conn, reply);
ac2a72149b423e2e84596098d7e47af88ebd215asf dbus_message_unref(reply);
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asfdone:
ac2a72149b423e2e84596098d7e47af88ebd215asf /* init complete, get rid of temp init context */
ac2a72149b423e2e84596098d7e47af88ebd215asf talloc_zfree(mini);
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asf return EOK;
ac2a72149b423e2e84596098d7e47af88ebd215asf}
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asfstruct svc_spy {
ac2a72149b423e2e84596098d7e47af88ebd215asf struct mt_svc *svc;
ac2a72149b423e2e84596098d7e47af88ebd215asf};
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asfstatic int svc_destructor(void *mem)
ac2a72149b423e2e84596098d7e47af88ebd215asf{
ac2a72149b423e2e84596098d7e47af88ebd215asf struct mt_svc *svc = talloc_get_type(mem, struct mt_svc);
ac2a72149b423e2e84596098d7e47af88ebd215asf if (!svc) {
ac2a72149b423e2e84596098d7e47af88ebd215asf /* ?!?!? */
ac2a72149b423e2e84596098d7e47af88ebd215asf return 0;
ac2a72149b423e2e84596098d7e47af88ebd215asf }
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asf /* try to delist service */
ac2a72149b423e2e84596098d7e47af88ebd215asf if (svc->mt_ctx) {
ac2a72149b423e2e84596098d7e47af88ebd215asf DLIST_REMOVE(svc->mt_ctx->svc_list, svc);
ac2a72149b423e2e84596098d7e47af88ebd215asf }
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asf /* Cancel any pending pings */
ac2a72149b423e2e84596098d7e47af88ebd215asf if (svc->pending) {
ac2a72149b423e2e84596098d7e47af88ebd215asf dbus_pending_call_cancel(svc->pending);
ac2a72149b423e2e84596098d7e47af88ebd215asf }
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asf /* svc is beeing freed, neutralize the spy */
ac2a72149b423e2e84596098d7e47af88ebd215asf if (svc->conn_spy) {
ac2a72149b423e2e84596098d7e47af88ebd215asf talloc_set_destructor((TALLOC_CTX *)svc->conn_spy, NULL);
ac2a72149b423e2e84596098d7e47af88ebd215asf talloc_zfree(svc->conn_spy);
ac2a72149b423e2e84596098d7e47af88ebd215asf }
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asf if (svc->type == MT_SVC_SERVICE && svc->svc_started
ac2a72149b423e2e84596098d7e47af88ebd215asf && svc->mt_ctx != NULL && svc->mt_ctx->started_services > 0) {
ac2a72149b423e2e84596098d7e47af88ebd215asf svc->mt_ctx->started_services--;
ac2a72149b423e2e84596098d7e47af88ebd215asf }
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asf return 0;
ac2a72149b423e2e84596098d7e47af88ebd215asf}
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asfstatic int svc_spy_destructor(void *mem)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor struct svc_spy *spy = talloc_get_type(mem, struct svc_spy);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!spy) {
f072359f493a5209335799da85ac16d6a273303bgryzor /* ?!?!? */
f072359f493a5209335799da85ac16d6a273303bgryzor return 0;
f072359f493a5209335799da85ac16d6a273303bgryzor }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim /* svc->conn has been freed, NULL the pointer in svc */
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim spy->svc->conn_spy = NULL;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim spy->svc->conn = NULL;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim return 0;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int add_svc_conn_spy(struct mt_svc *svc)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor struct svc_spy *spy;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor spy = talloc(svc->conn, struct svc_spy);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!spy) return ENOMEM;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor spy->svc = svc;
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_set_destructor((TALLOC_CTX *)spy, svc_spy_destructor);
f072359f493a5209335799da85ac16d6a273303bgryzor svc->conn_spy = spy;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor return EOK;
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int mark_service_as_started(struct mt_svc *svc)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_ctx *ctx = svc->mt_ctx;
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_svc *iter;
f072359f493a5209335799da85ac16d6a273303bgryzor int ret;
f072359f493a5209335799da85ac16d6a273303bgryzor int i;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(5, ("Marking %s as started.\n", svc->name));
f072359f493a5209335799da85ac16d6a273303bgryzor svc->svc_started = true;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* we need to attach a spy to the connection structure so that if some code
f072359f493a5209335799da85ac16d6a273303bgryzor * frees it we can zero it out in the service structure. Otherwise we may
f072359f493a5209335799da85ac16d6a273303bgryzor * try to access or even free, freed memory. */
f072359f493a5209335799da85ac16d6a273303bgryzor ret = add_svc_conn_spy(svc);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret) {
48c64aeceef385e19025b384bd719b2a9789592dnd DEBUG(0, ("Failed to attch spy\n"));
f072359f493a5209335799da85ac16d6a273303bgryzor goto done;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor if (!ctx->services_started) {
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* check if all providers are up */
f072359f493a5209335799da85ac16d6a273303bgryzor for (iter = ctx->svc_list; iter; iter = iter->next) {
f072359f493a5209335799da85ac16d6a273303bgryzor if (iter->provider && !iter->svc_started) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(5, ("Still waiting on %s provider.\n", iter->name));
f072359f493a5209335799da85ac16d6a273303bgryzor break;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor if (iter) {
eef716e54c415709ca9d53aad4678bf9d96186e6nd /* there are still unstarted providers */
f072359f493a5209335799da85ac16d6a273303bgryzor goto done;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor ctx->services_started = true;
48c64aeceef385e19025b384bd719b2a9789592dnd
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(4, ("Now starting services!\n"));
f072359f493a5209335799da85ac16d6a273303bgryzor /* then start all services */
f072359f493a5209335799da85ac16d6a273303bgryzor for (i = 0; ctx->services[i]; i++) {
f072359f493a5209335799da85ac16d6a273303bgryzor add_new_service(ctx, ctx->services[i], 0);
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor if (svc->type == MT_SVC_SERVICE) {
f072359f493a5209335799da85ac16d6a273303bgryzor ctx->started_services++;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor if (ctx->started_services == ctx->num_services) {
f072359f493a5209335799da85ac16d6a273303bgryzor /* Initialization is complete, terminate parent process if in daemon
f072359f493a5209335799da85ac16d6a273303bgryzor * mode. Make sure we send the signal to the right process */
f072359f493a5209335799da85ac16d6a273303bgryzor if (ctx->is_daemon) {
f072359f493a5209335799da85ac16d6a273303bgryzor if (ctx->parent_pid <= 1 || ctx->parent_pid != getppid()) {
f072359f493a5209335799da85ac16d6a273303bgryzor /* the parent process was already terminated */
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_MINOR_FAILURE, ("Invalid parent pid: %d\n",
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim ctx->parent_pid));
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim goto done;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim DEBUG(SSSDBG_TRACE_FUNC, ("SSSD is initialized, "
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim "terminating parent process\n"));
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim errno = 0;
f072359f493a5209335799da85ac16d6a273303bgryzor ret = kill(ctx->parent_pid, SIGTERM);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret != 0) {
f072359f493a5209335799da85ac16d6a273303bgryzor ret = errno;
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_FATAL_FAILURE, ("Unable to terminate parent "
f072359f493a5209335799da85ac16d6a273303bgryzor "process [%d]: %s\n", ret, strerror(ret)));
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzordone:
f072359f493a5209335799da85ac16d6a273303bgryzor return ret;
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic void services_startup_timeout(struct tevent_context *ev,
f072359f493a5209335799da85ac16d6a273303bgryzor struct tevent_timer *te,
f072359f493a5209335799da85ac16d6a273303bgryzor struct timeval t, void *ptr)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_ctx *ctx = talloc_get_type(ptr, struct mt_ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor int i;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(6, ("Handling timeout\n"));
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor if (!ctx->services_started) {
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic DEBUG(1, ("Providers did not start in time, "
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic "forcing services startup!\n"));
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic ctx->services_started = true;
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic DEBUG(4, ("Now starting services!\n"));
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic /* then start all services */
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic for (i = 0; ctx->services[i]; i++) {
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic add_new_service(ctx, ctx->services[i], 0);
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic }
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic }
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic}
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int add_services_startup_timeout(struct mt_ctx *ctx)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor struct tevent_timer *to;
f072359f493a5209335799da85ac16d6a273303bgryzor struct timeval tv;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* 5 seconds should be plenty */
f072359f493a5209335799da85ac16d6a273303bgryzor tv = tevent_timeval_current_ofs(5, 0);
f072359f493a5209335799da85ac16d6a273303bgryzor to = tevent_add_timer(ctx->ev, ctx, tv, services_startup_timeout, ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!to) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(0,("Out of memory?!\n"));
f072359f493a5209335799da85ac16d6a273303bgryzor return ENOMEM;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor return EOK;
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstruct sbus_method monitor_methods[] = {
f072359f493a5209335799da85ac16d6a273303bgryzor { MON_SRV_METHOD_VERSION, get_monitor_version },
f072359f493a5209335799da85ac16d6a273303bgryzor { MON_SRV_METHOD_REGISTER, client_registration },
f072359f493a5209335799da85ac16d6a273303bgryzor { NULL, NULL }
f072359f493a5209335799da85ac16d6a273303bgryzor};
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstruct sbus_interface monitor_server_interface = {
f072359f493a5209335799da85ac16d6a273303bgryzor MON_SRV_INTERFACE,
f072359f493a5209335799da85ac16d6a273303bgryzor MON_SRV_PATH,
f072359f493a5209335799da85ac16d6a273303bgryzor SBUS_DEFAULT_VTABLE,
f072359f493a5209335799da85ac16d6a273303bgryzor monitor_methods,
f072359f493a5209335799da85ac16d6a273303bgryzor NULL
f072359f493a5209335799da85ac16d6a273303bgryzor};
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor/* monitor_dbus_init
f072359f493a5209335799da85ac16d6a273303bgryzor * Set up the monitor service as a D-BUS Server */
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int monitor_dbus_init(struct mt_ctx *ctx)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor char *monitor_address;
45a544a8bb3fa1f95e5edac9fb3e723e2bb7001drbowen int ret;
45a544a8bb3fa1f95e5edac9fb3e723e2bb7001drbowen
45a544a8bb3fa1f95e5edac9fb3e723e2bb7001drbowen ret = monitor_get_sbus_address(ctx, &monitor_address);
45a544a8bb3fa1f95e5edac9fb3e723e2bb7001drbowen if (ret != EOK) {
45a544a8bb3fa1f95e5edac9fb3e723e2bb7001drbowen return ret;
45a544a8bb3fa1f95e5edac9fb3e723e2bb7001drbowen }
45a544a8bb3fa1f95e5edac9fb3e723e2bb7001drbowen
45a544a8bb3fa1f95e5edac9fb3e723e2bb7001drbowen ret = sbus_new_server(ctx, ctx->ev,
45a544a8bb3fa1f95e5edac9fb3e723e2bb7001drbowen monitor_address, &monitor_server_interface,
45a544a8bb3fa1f95e5edac9fb3e723e2bb7001drbowen false, &ctx->sbus_srv, monitor_service_init, ctx);
45a544a8bb3fa1f95e5edac9fb3e723e2bb7001drbowen
45a544a8bb3fa1f95e5edac9fb3e723e2bb7001drbowen talloc_free(monitor_address);
45a544a8bb3fa1f95e5edac9fb3e723e2bb7001drbowen
45a544a8bb3fa1f95e5edac9fb3e723e2bb7001drbowen return ret;
45a544a8bb3fa1f95e5edac9fb3e723e2bb7001drbowen}
45a544a8bb3fa1f95e5edac9fb3e723e2bb7001drbowen
45a544a8bb3fa1f95e5edac9fb3e723e2bb7001drbowenstatic void tasks_check_handler(struct tevent_context *ev,
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh struct tevent_timer *te,
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh struct timeval t, void *ptr)
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh{
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh struct mt_svc *svc = talloc_get_type(ptr, struct mt_svc);
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh int ret;
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh ret = service_send_ping(svc);
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh switch (ret) {
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh case EOK:
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh /* all fine */
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh break;
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh case ENXIO:
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh DEBUG(1,("Child (%s) not responding! (yet)\n", svc->name));
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh break;
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh default:
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh /* TODO: should we tear it down ? */
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh DEBUG(1,("Sending a message to service (%s) failed!!\n", svc->name));
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh break;
45a544a8bb3fa1f95e5edac9fb3e723e2bb7001drbowen }
45a544a8bb3fa1f95e5edac9fb3e723e2bb7001drbowen
f072359f493a5209335799da85ac16d6a273303bgryzor if (svc->failed_pongs >= 3) {
f072359f493a5209335799da85ac16d6a273303bgryzor /* too long since we last heard of this process */
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_CRIT_FAILURE,
f072359f493a5209335799da85ac16d6a273303bgryzor ("Killing service [%s], not responding to pings!\n",
f072359f493a5209335799da85ac16d6a273303bgryzor svc->name));
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* Kill the service. The SIGCHLD handler will restart it */
f072359f493a5209335799da85ac16d6a273303bgryzor monitor_kill_service(svc);
48c64aeceef385e19025b384bd719b2a9789592dnd return;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* all fine, set up the task checker again */
f072359f493a5209335799da85ac16d6a273303bgryzor set_tasks_checker(svc);
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic void set_tasks_checker(struct mt_svc *svc)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor struct tevent_timer *te = NULL;
f072359f493a5209335799da85ac16d6a273303bgryzor struct timeval tv;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor gettimeofday(&tv, NULL);
f072359f493a5209335799da85ac16d6a273303bgryzor tv.tv_sec += svc->ping_time;
f072359f493a5209335799da85ac16d6a273303bgryzor tv.tv_usec = 0;
f072359f493a5209335799da85ac16d6a273303bgryzor te = tevent_add_timer(svc->mt_ctx->ev, svc, tv, tasks_check_handler, svc);
f072359f493a5209335799da85ac16d6a273303bgryzor if (te == NULL) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(0, ("failed to add event, monitor offline for [%s]!\n",
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim svc->name));
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim /* FIXME: shutdown ? */
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh }
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh svc->ping_ev = te;
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh}
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjimstatic void mt_svc_sigkill(struct tevent_context *ev,
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim struct tevent_timer *te,
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim struct timeval t, void *ptr);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjimstatic int monitor_kill_service (struct mt_svc *svc)
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh{
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh int ret;
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh struct timeval tv;
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh ret = kill(svc->pid, SIGTERM);
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh if (ret != EOK) {
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh DEBUG(SSSDBG_FATAL_FAILURE,
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh ("Sending signal to child (%s:%d) failed! "
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh "Ignore and pretend child is dead.\n",
15e38d431fea66258ef33960b39edee496c3c9c2humbedooh svc->name, svc->pid));
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim talloc_free(svc);
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* Set up a timer to send SIGKILL if this process
f072359f493a5209335799da85ac16d6a273303bgryzor * doesn't exit within sixty seconds
f072359f493a5209335799da85ac16d6a273303bgryzor */
f072359f493a5209335799da85ac16d6a273303bgryzor tv = tevent_timeval_current_ofs(svc->kill_time, 0);
f072359f493a5209335799da85ac16d6a273303bgryzor svc->sigkill_ev = tevent_add_timer(svc->mt_ctx->ev, svc, tv,
f072359f493a5209335799da85ac16d6a273303bgryzor mt_svc_sigkill, svc);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor return ret;
48c64aeceef385e19025b384bd719b2a9789592dnd}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic void mt_svc_sigkill(struct tevent_context *ev,
f072359f493a5209335799da85ac16d6a273303bgryzor struct tevent_timer *te,
f072359f493a5209335799da85ac16d6a273303bgryzor struct timeval t, void *ptr)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor int ret;
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_svc *svc = talloc_get_type(ptr, struct mt_svc);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim DEBUG(SSSDBG_FATAL_FAILURE,
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim ("[%s][%d] is not responding to SIGTERM. Sending SIGKILL.\n",
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim svc->name, svc->pid));
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
f072359f493a5209335799da85ac16d6a273303bgryzor ret = kill(svc->pid, SIGKILL);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret != EOK) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_FATAL_FAILURE,
f072359f493a5209335799da85ac16d6a273303bgryzor ("Sending signal to child (%s:%d) failed! "
f072359f493a5209335799da85ac16d6a273303bgryzor "Ignore and pretend child is dead.\n",
f072359f493a5209335799da85ac16d6a273303bgryzor svc->name, svc->pid));
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(svc);
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic void reload_reply(DBusPendingCall *pending, void *data)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor DBusMessage *reply;
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_svc *svc = talloc_get_type(data, struct mt_svc);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor reply = dbus_pending_call_steal_reply(pending);
3739b903eb6f5b0944056b2e98d5d8877d003c6figalic if (!reply) {
f072359f493a5209335799da85ac16d6a273303bgryzor /* reply should never be null. This function shouldn't be called
f072359f493a5209335799da85ac16d6a273303bgryzor * until reply is valid or timeout has occurred. If reply is NULL
f072359f493a5209335799da85ac16d6a273303bgryzor * here, something is seriously wrong and we should bail out.
f072359f493a5209335799da85ac16d6a273303bgryzor */
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(0, ("A reply callback was called but no reply was received"
f072359f493a5209335799da85ac16d6a273303bgryzor " and no timeout occurred\n"));
f072359f493a5209335799da85ac16d6a273303bgryzor /* Destroy this connection */
f072359f493a5209335799da85ac16d6a273303bgryzor sbus_disconnect(svc->conn);
f072359f493a5209335799da85ac16d6a273303bgryzor dbus_pending_call_unref(pending);
f072359f493a5209335799da85ac16d6a273303bgryzor return;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
e797af4d7b0cada1278d72d6c8ac77210ef78632minfrin /* TODO: Handle cases where the call has timed out or returned
eef716e54c415709ca9d53aad4678bf9d96186e6nd * with an error.
f072359f493a5209335799da85ac16d6a273303bgryzor */
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor dbus_pending_call_unref(pending);
f072359f493a5209335799da85ac16d6a273303bgryzor dbus_message_unref(reply);
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int service_signal_dns_reload(struct mt_svc *svc);
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int monitor_update_resolv(struct config_file_ctx *file_ctx,
f072359f493a5209335799da85ac16d6a273303bgryzor const char *filename)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor int ret;
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_svc *cur_svc;
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(2, ("Resolv.conf has been updated. Reloading.\n"));
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor ret = res_init();
f072359f493a5209335799da85ac16d6a273303bgryzor if(ret != 0) {
f072359f493a5209335799da85ac16d6a273303bgryzor return EIO;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* Signal all services to reload their DNS configuration */
f072359f493a5209335799da85ac16d6a273303bgryzor for(cur_svc = file_ctx->mt_ctx->svc_list; cur_svc; cur_svc = cur_svc->next) {
f072359f493a5209335799da85ac16d6a273303bgryzor service_signal_dns_reload(cur_svc);
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor return EOK;
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int service_signal(struct mt_svc *svc, const char *svc_signal)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor DBusMessage *msg;
f072359f493a5209335799da85ac16d6a273303bgryzor int ret;
f072359f493a5209335799da85ac16d6a273303bgryzor
b71e5eae594d54e9e56dc20208c6a7fb52610e29rbowen if (svc->provider && strcasecmp(svc->provider, "local") == 0) {
f072359f493a5209335799da85ac16d6a273303bgryzor /* The local provider requires no signaling */
f072359f493a5209335799da85ac16d6a273303bgryzor return EOK;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor if (!svc->conn) {
f072359f493a5209335799da85ac16d6a273303bgryzor /* Avoid a race condition where we are trying to
f072359f493a5209335799da85ac16d6a273303bgryzor * order a service to reload that hasn't started
f072359f493a5209335799da85ac16d6a273303bgryzor * yet.
f072359f493a5209335799da85ac16d6a273303bgryzor */
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(1,("Could not signal service [%s].\n", svc->name));
f072359f493a5209335799da85ac16d6a273303bgryzor return EIO;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor msg = dbus_message_new_method_call(NULL,
f072359f493a5209335799da85ac16d6a273303bgryzor MONITOR_PATH,
f072359f493a5209335799da85ac16d6a273303bgryzor MONITOR_INTERFACE,
f072359f493a5209335799da85ac16d6a273303bgryzor svc_signal);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!msg) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(0,("Out of memory?!\n"));
f072359f493a5209335799da85ac16d6a273303bgryzor monitor_kill_service(svc);
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(svc);
f072359f493a5209335799da85ac16d6a273303bgryzor return ENOMEM;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor ret = sbus_conn_send(svc->conn, msg,
f072359f493a5209335799da85ac16d6a273303bgryzor svc->mt_ctx->service_id_timeout,
f072359f493a5209335799da85ac16d6a273303bgryzor reload_reply, svc, NULL);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor dbus_message_unref(msg);
f072359f493a5209335799da85ac16d6a273303bgryzor return ret;
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int service_signal_dns_reload(struct mt_svc *svc)
3739b903eb6f5b0944056b2e98d5d8877d003c6figalic{
3739b903eb6f5b0944056b2e98d5d8877d003c6figalic return service_signal(svc, MON_CLI_METHOD_RES_INIT);
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int service_signal_offline(struct mt_svc *svc)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor return service_signal(svc, MON_CLI_METHOD_OFFLINE);
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int service_signal_reset_offline(struct mt_svc *svc)
48c64aeceef385e19025b384bd719b2a9789592dnd{
f072359f493a5209335799da85ac16d6a273303bgryzor return service_signal(svc, MON_CLI_METHOD_RESET_OFFLINE);
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int service_signal_rotate(struct mt_svc *svc)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor return service_signal(svc, MON_CLI_METHOD_ROTATE);
e797af4d7b0cada1278d72d6c8ac77210ef78632minfrin}
eef716e54c415709ca9d53aad4678bf9d96186e6ndstatic int service_signal_clear_memcache(struct mt_svc *svc)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor return service_signal(svc, MON_CLI_METHOD_CLEAR_MEMCACHE);
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int check_domain_ranges(struct sss_domain_info *domains)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor struct sss_domain_info *dom = domains, *other = NULL;
f072359f493a5209335799da85ac16d6a273303bgryzor uint32_t id_min, id_max;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor while (dom) {
f072359f493a5209335799da85ac16d6a273303bgryzor other = dom->next;
f072359f493a5209335799da85ac16d6a273303bgryzor if (dom->id_max && dom->id_min > dom->id_max) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_CRIT_FAILURE,
f072359f493a5209335799da85ac16d6a273303bgryzor ("Domain '%s' does not have a valid ID range\n", dom->name));
f072359f493a5209335799da85ac16d6a273303bgryzor return EINVAL;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor while (other) {
f072359f493a5209335799da85ac16d6a273303bgryzor id_min = MAX(dom->id_min, other->id_min);
f072359f493a5209335799da85ac16d6a273303bgryzor id_max = MIN((dom->id_max ? dom->id_max : UINT32_MAX),
f072359f493a5209335799da85ac16d6a273303bgryzor (other->id_max ? other->id_max : UINT32_MAX));
f072359f493a5209335799da85ac16d6a273303bgryzor if (id_min <= id_max) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_MINOR_FAILURE,
f072359f493a5209335799da85ac16d6a273303bgryzor ("Domains '%s' and '%s' overlap in range %u - %u\n",
eef716e54c415709ca9d53aad4678bf9d96186e6nd dom->name, other->name, id_min, id_max));
f072359f493a5209335799da85ac16d6a273303bgryzor }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim other = other->next;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim dom = dom->next;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim return EOK;
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
eef716e54c415709ca9d53aad4678bf9d96186e6ndstatic int check_local_domain_unique(struct sss_domain_info *domains)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor uint8_t count = 0;
f072359f493a5209335799da85ac16d6a273303bgryzor
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim struct sss_domain_info *dom = domains;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim while (dom) {
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim if (strcasecmp(dom->provider, "local") == 0) {
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim count++;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor if (count > 1) {
7cc5e8f14e6ab2d8b60bb0eaba4b68b00d320b29nd break;
7cc5e8f14e6ab2d8b60bb0eaba4b68b00d320b29nd }
7cc5e8f14e6ab2d8b60bb0eaba4b68b00d320b29nd
7cc5e8f14e6ab2d8b60bb0eaba4b68b00d320b29nd dom = dom->next;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
4c47688d73a9a5ef2735cd84f334b8eb814c74f0igalic if (count > 1) {
4c47688d73a9a5ef2735cd84f334b8eb814c74f0igalic return EINVAL;
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf }
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf
4c47688d73a9a5ef2735cd84f334b8eb814c74f0igalic return EOK;
4c47688d73a9a5ef2735cd84f334b8eb814c74f0igalic}
4c47688d73a9a5ef2735cd84f334b8eb814c74f0igalic
4c47688d73a9a5ef2735cd84f334b8eb814c74f0igalicstatic char *check_services(char **services)
4c47688d73a9a5ef2735cd84f334b8eb814c74f0igalic{
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf const char *known_services[] = { "nss", "pam", "sudo", "autofs", "ssh",
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf "pac", NULL };
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf int i;
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf int ii;
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf /* Check if services we are about to start are in the list if known */
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf for (i = 0; services[i]; i++) {
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf for (ii=0; known_services[ii]; ii++) {
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf if (strcasecmp(services[i], known_services[ii]) == 0) {
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf break;
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf }
4c47688d73a9a5ef2735cd84f334b8eb814c74f0igalic }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor if (known_services[ii] == NULL) {
f072359f493a5209335799da85ac16d6a273303bgryzor return services[i];
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor return NULL;
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
48c64aeceef385e19025b384bd719b2a9789592dndint get_monitor_config(struct mt_ctx *ctx)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor int ret;
f072359f493a5209335799da85ac16d6a273303bgryzor int timeout_seconds;
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic char *badsrv = NULL;
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic int i;
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic
f072359f493a5209335799da85ac16d6a273303bgryzor ret = confdb_get_int(ctx->cdb,
f072359f493a5209335799da85ac16d6a273303bgryzor CONFDB_MONITOR_CONF_ENTRY,
f072359f493a5209335799da85ac16d6a273303bgryzor CONFDB_MONITOR_SBUS_TIMEOUT,
f072359f493a5209335799da85ac16d6a273303bgryzor 10, &timeout_seconds);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret != EOK) {
f072359f493a5209335799da85ac16d6a273303bgryzor return ret;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor ctx->service_id_timeout = timeout_seconds * 1000; /* service_id_timeout is in ms */
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor ctx->service_ctx = talloc_new(ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor if(!ctx->service_ctx) {
f072359f493a5209335799da85ac16d6a273303bgryzor return ENOMEM;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor ret = confdb_get_string_as_list(ctx->cdb, ctx->service_ctx,
f072359f493a5209335799da85ac16d6a273303bgryzor CONFDB_MONITOR_CONF_ENTRY,
f072359f493a5209335799da85ac16d6a273303bgryzor CONFDB_MONITOR_ACTIVE_SERVICES,
f072359f493a5209335799da85ac16d6a273303bgryzor &ctx->services);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret != EOK) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(0, ("No services configured!\n"));
f072359f493a5209335799da85ac16d6a273303bgryzor return EINVAL;
f072359f493a5209335799da85ac16d6a273303bgryzor }
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick badsrv = check_services(ctx->services);
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick if (badsrv != NULL) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(0, ("Invalid service %s\n", badsrv));
f072359f493a5209335799da85ac16d6a273303bgryzor return EINVAL;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick ctx->started_services = 0;
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick ctx->num_services = 0;
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick for (i = 0; ctx->services[i] != NULL; i++) {
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick ctx->num_services++;
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick }
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick ctx->domain_ctx = talloc_new(ctx);
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick if(!ctx->domain_ctx) {
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick return ENOMEM;
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick }
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick ret = confdb_get_domains(ctx->cdb, &ctx->domains);
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick if (ret != EOK) {
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick DEBUG(0, ("No domains configured.\n"));
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick return ret;
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick }
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick ret = check_local_domain_unique(ctx->domains);
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick if (ret != EOK) {
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick DEBUG(0, ("More than one local domain configured.\n"));
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick return ret;
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick }
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick /* Check UID/GID overlaps */
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick ret = check_domain_ranges(ctx->domains);
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick if (ret != EOK) {
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick return ret;
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick }
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick return EOK;
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick}
f072359f493a5209335799da85ac16d6a273303bgryzor
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjimstatic errno_t get_ping_config(struct mt_ctx *ctx, const char *path,
3739b903eb6f5b0944056b2e98d5d8877d003c6figalic struct mt_svc *svc)
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim{
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim errno_t ret;
f072359f493a5209335799da85ac16d6a273303bgryzor
3739b903eb6f5b0944056b2e98d5d8877d003c6figalic ret = confdb_get_int(ctx->cdb, path,
3739b903eb6f5b0944056b2e98d5d8877d003c6figalic CONFDB_DOMAIN_TIMEOUT,
f072359f493a5209335799da85ac16d6a273303bgryzor MONITOR_DEF_PING_TIME, &svc->ping_time);
3739b903eb6f5b0944056b2e98d5d8877d003c6figalic if (ret != EOK) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_CRIT_FAILURE,
f072359f493a5209335799da85ac16d6a273303bgryzor ("Failed to get ping timeout for '%s'\n", svc->name));
f072359f493a5209335799da85ac16d6a273303bgryzor return ret;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
f072359f493a5209335799da85ac16d6a273303bgryzor
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim /* 'timeout = 0' should be translated to the default */
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim if (svc->ping_time == 0) {
f072359f493a5209335799da85ac16d6a273303bgryzor svc->ping_time = MONITOR_DEF_PING_TIME;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor ret = confdb_get_int(ctx->cdb, path,
f072359f493a5209335799da85ac16d6a273303bgryzor CONFDB_SERVICE_FORCE_TIMEOUT,
f072359f493a5209335799da85ac16d6a273303bgryzor MONITOR_DEF_FORCE_TIME, &svc->kill_time);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret != EOK) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_CRIT_FAILURE,
f072359f493a5209335799da85ac16d6a273303bgryzor ("Failed to get kill timeout for %s\n", svc->name));
f072359f493a5209335799da85ac16d6a273303bgryzor return ret;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* 'force_timeout = 0' should be translated to the default */
f072359f493a5209335799da85ac16d6a273303bgryzor if (svc->kill_time == 0) {
f072359f493a5209335799da85ac16d6a273303bgryzor svc->kill_time = MONITOR_DEF_FORCE_TIME;
48c64aeceef385e19025b384bd719b2a9789592dnd }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor return EOK;
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int get_service_config(struct mt_ctx *ctx, const char *name,
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_svc **svc_cfg)
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim{
f072359f493a5209335799da85ac16d6a273303bgryzor int ret;
f072359f493a5209335799da85ac16d6a273303bgryzor char *path;
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_svc *svc;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim time_t now = time(NULL);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
f072359f493a5209335799da85ac16d6a273303bgryzor *svc_cfg = NULL;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor svc = talloc_zero(ctx, struct mt_svc);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!svc) {
f072359f493a5209335799da85ac16d6a273303bgryzor return ENOMEM;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor svc->mt_ctx = ctx;
f072359f493a5209335799da85ac16d6a273303bgryzor svc->type = MT_SVC_SERVICE;
f072359f493a5209335799da85ac16d6a273303bgryzor
92fd3fe66fb218b9fdf129e7555bd851e5cbf487rbowen talloc_set_destructor((TALLOC_CTX *)svc, svc_destructor);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor svc->name = talloc_strdup(svc, name);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!svc->name) {
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(svc);
f072359f493a5209335799da85ac16d6a273303bgryzor return ENOMEM;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor svc->identity = talloc_strdup(svc, name);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!svc->identity) {
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(svc);
f072359f493a5209335799da85ac16d6a273303bgryzor return ENOMEM;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor path = talloc_asprintf(svc, CONFDB_SERVICE_PATH_TMPL, svc->name);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!path) {
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(svc);
f072359f493a5209335799da85ac16d6a273303bgryzor return ENOMEM;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor ret = confdb_get_string(ctx->cdb, svc, path,
f072359f493a5209335799da85ac16d6a273303bgryzor CONFDB_SERVICE_COMMAND,
f072359f493a5209335799da85ac16d6a273303bgryzor NULL, &svc->command);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret != EOK) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(0,("Failed to start service '%s'\n", svc->name));
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(svc);
f072359f493a5209335799da85ac16d6a273303bgryzor return ret;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor if (!svc->command) {
f072359f493a5209335799da85ac16d6a273303bgryzor svc->command = talloc_asprintf(
f072359f493a5209335799da85ac16d6a273303bgryzor svc, "%s/sssd_%s", SSSD_LIBEXEC_PATH, svc->name
f072359f493a5209335799da85ac16d6a273303bgryzor );
f072359f493a5209335799da85ac16d6a273303bgryzor if (!svc->command) {
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(svc);
f072359f493a5209335799da85ac16d6a273303bgryzor return ENOMEM;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor if (cmdline_debug_level != SSSDBG_UNRESOLVED) {
f072359f493a5209335799da85ac16d6a273303bgryzor svc->command = talloc_asprintf_append(
f072359f493a5209335799da85ac16d6a273303bgryzor svc->command, " -d %#.4x", cmdline_debug_level
f072359f493a5209335799da85ac16d6a273303bgryzor );
f072359f493a5209335799da85ac16d6a273303bgryzor if (!svc->command) {
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(svc);
f072359f493a5209335799da85ac16d6a273303bgryzor return ENOMEM;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor if (cmdline_debug_timestamps != SSSDBG_TIMESTAMP_UNRESOLVED) {
f072359f493a5209335799da85ac16d6a273303bgryzor svc->command = talloc_asprintf_append(
f072359f493a5209335799da85ac16d6a273303bgryzor svc->command, " --debug-timestamps=%d", cmdline_debug_timestamps
f072359f493a5209335799da85ac16d6a273303bgryzor );
f072359f493a5209335799da85ac16d6a273303bgryzor if (!svc->command) {
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(svc);
f072359f493a5209335799da85ac16d6a273303bgryzor return ENOMEM;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor if (cmdline_debug_microseconds != SSSDBG_MICROSECONDS_UNRESOLVED) {
f072359f493a5209335799da85ac16d6a273303bgryzor svc->command = talloc_asprintf_append(
f072359f493a5209335799da85ac16d6a273303bgryzor svc->command, " --debug-microseconds=%d",
f072359f493a5209335799da85ac16d6a273303bgryzor cmdline_debug_microseconds
f072359f493a5209335799da85ac16d6a273303bgryzor );
f072359f493a5209335799da85ac16d6a273303bgryzor if (!svc->command) {
7cc5e8f14e6ab2d8b60bb0eaba4b68b00d320b29nd talloc_free(svc);
7cc5e8f14e6ab2d8b60bb0eaba4b68b00d320b29nd return ENOMEM;
7cc5e8f14e6ab2d8b60bb0eaba4b68b00d320b29nd }
7cc5e8f14e6ab2d8b60bb0eaba4b68b00d320b29nd }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor if (debug_to_file) {
f072359f493a5209335799da85ac16d6a273303bgryzor svc->command = talloc_strdup_append(
f072359f493a5209335799da85ac16d6a273303bgryzor svc->command, " --debug-to-files"
f072359f493a5209335799da85ac16d6a273303bgryzor );
f072359f493a5209335799da85ac16d6a273303bgryzor if (!svc->command) {
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(svc);
f072359f493a5209335799da85ac16d6a273303bgryzor return ENOMEM;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor }
48c64aeceef385e19025b384bd719b2a9789592dnd
f072359f493a5209335799da85ac16d6a273303bgryzor ret = get_ping_config(ctx, path, svc);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret != EOK) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_CRIT_FAILURE,
f072359f493a5209335799da85ac16d6a273303bgryzor ("Failed to get ping timeouts for %s\n", svc->name));
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(svc);
f072359f493a5209335799da85ac16d6a273303bgryzor return ret;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor svc->last_restart = now;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
f072359f493a5209335799da85ac16d6a273303bgryzor *svc_cfg = svc;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim talloc_free(path);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
f072359f493a5209335799da85ac16d6a273303bgryzor return EOK;
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int add_new_service(struct mt_ctx *ctx,
f072359f493a5209335799da85ac16d6a273303bgryzor const char *name,
48c64aeceef385e19025b384bd719b2a9789592dnd int restarts)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor int ret;
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_svc *svc;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor ret = get_service_config(ctx, name, &svc);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret != EOK) {
f072359f493a5209335799da85ac16d6a273303bgryzor return ret;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor svc->restarts = restarts;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor ret = start_service(svc);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret != EOK) {
44a442483c2ae67ab94061b87ca3312bc83b059crbowen DEBUG(0,("Failed to start service '%s'\n", svc->name));
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(svc);
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor return ret;
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int get_provider_config(struct mt_ctx *ctx, const char *name,
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_svc **svc_cfg)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor int ret;
f072359f493a5209335799da85ac16d6a273303bgryzor char *path;
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_svc *svc;
f072359f493a5209335799da85ac16d6a273303bgryzor time_t now = time(NULL);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor *svc_cfg = NULL;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor svc = talloc_zero(ctx, struct mt_svc);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!svc) {
eef716e54c415709ca9d53aad4678bf9d96186e6nd return ENOMEM;
f072359f493a5209335799da85ac16d6a273303bgryzor }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim svc->mt_ctx = ctx;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim svc->type = MT_SVC_PROVIDER;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim talloc_set_destructor((TALLOC_CTX *)svc, svc_destructor);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim svc->name = talloc_strdup(svc, name);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!svc->name) {
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(svc);
eef716e54c415709ca9d53aad4678bf9d96186e6nd return ENOMEM;
eef716e54c415709ca9d53aad4678bf9d96186e6nd }
f072359f493a5209335799da85ac16d6a273303bgryzor
44a442483c2ae67ab94061b87ca3312bc83b059crbowen svc->identity = talloc_asprintf(svc, "%%BE_%s", svc->name);
44a442483c2ae67ab94061b87ca3312bc83b059crbowen if (!svc->identity) {
44a442483c2ae67ab94061b87ca3312bc83b059crbowen talloc_free(svc);
44a442483c2ae67ab94061b87ca3312bc83b059crbowen return ENOMEM;
92fd3fe66fb218b9fdf129e7555bd851e5cbf487rbowen }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
92fd3fe66fb218b9fdf129e7555bd851e5cbf487rbowen path = talloc_asprintf(svc, CONFDB_DOMAIN_PATH_TMPL, name);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim if (!path) {
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim talloc_free(svc);
92fd3fe66fb218b9fdf129e7555bd851e5cbf487rbowen return ENOMEM;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor ret = confdb_get_string(ctx->cdb, svc, path,
f072359f493a5209335799da85ac16d6a273303bgryzor CONFDB_DOMAIN_ID_PROVIDER,
f072359f493a5209335799da85ac16d6a273303bgryzor NULL, &svc->provider);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret != EOK) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(0, ("Failed to find ID provider from [%s] configuration\n", name));
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(svc);
f072359f493a5209335799da85ac16d6a273303bgryzor return ret;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor ret = confdb_get_string(ctx->cdb, svc, path,
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim CONFDB_DOMAIN_COMMAND,
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim NULL, &svc->command);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim if (ret != EOK) {
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim DEBUG(0, ("Failed to find command from [%s] configuration\n", name));
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim talloc_free(svc);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim return ret;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim ret = get_ping_config(ctx, path, svc);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim if (ret != EOK) {
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim DEBUG(SSSDBG_CRIT_FAILURE,
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim ("Failed to get ping timeouts for %s\n", svc->name));
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim talloc_free(svc);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim return ret;
92fd3fe66fb218b9fdf129e7555bd851e5cbf487rbowen }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(path);
eef716e54c415709ca9d53aad4678bf9d96186e6nd
f072359f493a5209335799da85ac16d6a273303bgryzor /* if no provider is present do not run the domain */
f072359f493a5209335799da85ac16d6a273303bgryzor if (!svc->provider) {
ac2a72149b423e2e84596098d7e47af88ebd215asf talloc_free(svc);
ac2a72149b423e2e84596098d7e47af88ebd215asf return EIO;
ac2a72149b423e2e84596098d7e47af88ebd215asf }
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asf /* if there are no custom commands, build a default one */
ac2a72149b423e2e84596098d7e47af88ebd215asf if (!svc->command) {
ac2a72149b423e2e84596098d7e47af88ebd215asf svc->command = talloc_asprintf(
ac2a72149b423e2e84596098d7e47af88ebd215asf svc, "%s/sssd_be --domain %s", SSSD_LIBEXEC_PATH, svc->name
92fd3fe66fb218b9fdf129e7555bd851e5cbf487rbowen );
92fd3fe66fb218b9fdf129e7555bd851e5cbf487rbowen if (!svc->command) {
92fd3fe66fb218b9fdf129e7555bd851e5cbf487rbowen talloc_free(svc);
92fd3fe66fb218b9fdf129e7555bd851e5cbf487rbowen return ENOMEM;
ac2a72149b423e2e84596098d7e47af88ebd215asf }
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asf if (cmdline_debug_level != SSSDBG_UNRESOLVED) {
ac2a72149b423e2e84596098d7e47af88ebd215asf svc->command = talloc_asprintf_append(
ac2a72149b423e2e84596098d7e47af88ebd215asf svc->command, " -d %#.4x", cmdline_debug_level
ac2a72149b423e2e84596098d7e47af88ebd215asf );
f072359f493a5209335799da85ac16d6a273303bgryzor if (!svc->command) {
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe talloc_free(svc);
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe return ENOMEM;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe }
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe }
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe if (cmdline_debug_timestamps != SSSDBG_TIMESTAMP_UNRESOLVED) {
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe svc->command = talloc_asprintf_append(
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe svc->command, " --debug-timestamps=%d", cmdline_debug_timestamps
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe );
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe if (!svc->command) {
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe talloc_free(svc);
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe return ENOMEM;
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe }
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe }
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe if (cmdline_debug_microseconds != SSSDBG_MICROSECONDS_UNRESOLVED) {
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe svc->command = talloc_asprintf_append(
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe svc->command, " --debug-microseconds=%d",
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe cmdline_debug_microseconds
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe );
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe if (!svc->command) {
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe talloc_free(svc);
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe return ENOMEM;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe }
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe }
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe
f072359f493a5209335799da85ac16d6a273303bgryzor if (debug_to_file) {
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick svc->command = talloc_strdup_append(
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe svc->command, " --debug-to-files"
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim );
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawick if (!svc->command) {
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(svc);
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf return ENOMEM;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor svc->last_restart = now;
f072359f493a5209335799da85ac16d6a273303bgryzor
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe *svc_cfg = svc;
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe return EOK;
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe}
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowestatic int add_new_provider(struct mt_ctx *ctx,
f072359f493a5209335799da85ac16d6a273303bgryzor const char *name,
f072359f493a5209335799da85ac16d6a273303bgryzor int restarts)
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe{
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe int ret;
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe struct mt_svc *svc;
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe ret = get_provider_config(ctx, name, &svc);
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe if (ret != EOK) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(0, ("Could not get provider configuration for [%s]\n",
f072359f493a5209335799da85ac16d6a273303bgryzor name));
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe return ret;
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe }
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe svc->restarts = restarts;
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe if (strcasecmp(svc->provider, "local") == 0) {
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe /* The LOCAL provider requires no back-end currently
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe * We'll add it to the service list, but we don't need
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe * to poll it.
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe */
f072359f493a5209335799da85ac16d6a273303bgryzor svc->svc_started = true;
f072359f493a5209335799da85ac16d6a273303bgryzor DLIST_ADD(ctx->svc_list, svc);
f072359f493a5209335799da85ac16d6a273303bgryzor return ENOENT;
f072359f493a5209335799da85ac16d6a273303bgryzor }
48c64aeceef385e19025b384bd719b2a9789592dnd
f072359f493a5209335799da85ac16d6a273303bgryzor ret = start_service(svc);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret != EOK) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(0,("Failed to start service '%s'\n", svc->name));
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(svc);
f072359f493a5209335799da85ac16d6a273303bgryzor }
48c64aeceef385e19025b384bd719b2a9789592dnd
f072359f493a5209335799da85ac16d6a273303bgryzor return ret;
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic void monitor_hup(struct tevent_context *ev,
f072359f493a5209335799da85ac16d6a273303bgryzor struct tevent_signal *se,
f072359f493a5209335799da85ac16d6a273303bgryzor int signum,
f072359f493a5209335799da85ac16d6a273303bgryzor int count,
f072359f493a5209335799da85ac16d6a273303bgryzor void *siginfo,
f072359f493a5209335799da85ac16d6a273303bgryzor void *private_data)
f072359f493a5209335799da85ac16d6a273303bgryzor{
48c64aeceef385e19025b384bd719b2a9789592dnd struct mt_ctx *ctx = talloc_get_type(private_data, struct mt_ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_svc *cur_svc;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(1, ("Received SIGHUP.\n"));
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* Send D-Bus message to other services to rotate their logs.
f072359f493a5209335799da85ac16d6a273303bgryzor * NSS service receives also message to clear memory caches. */
f072359f493a5209335799da85ac16d6a273303bgryzor for(cur_svc = ctx->svc_list; cur_svc; cur_svc = cur_svc->next) {
f072359f493a5209335799da85ac16d6a273303bgryzor service_signal_rotate(cur_svc);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!strcmp(NSS_SBUS_SERVICE_NAME, cur_svc->name)) {
f072359f493a5209335799da85ac16d6a273303bgryzor service_signal_clear_memcache(cur_svc);
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int monitor_cleanup(void)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor int ret;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor errno = 0;
f072359f493a5209335799da85ac16d6a273303bgryzor ret = unlink(SSSD_PIDFILE_PATH);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret == -1) {
f072359f493a5209335799da85ac16d6a273303bgryzor ret = errno;
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_FATAL_FAILURE,
f072359f493a5209335799da85ac16d6a273303bgryzor ("Error removing pidfile! (%d [%s])\n", ret, strerror(ret)));
f072359f493a5209335799da85ac16d6a273303bgryzor return ret;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor return EOK;
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic void monitor_quit(struct mt_ctx *mt_ctx, int ret)
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic{
48c64aeceef385e19025b384bd719b2a9789592dnd struct mt_svc *svc;
f072359f493a5209335799da85ac16d6a273303bgryzor pid_t pid;
f072359f493a5209335799da85ac16d6a273303bgryzor int status;
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic errno_t error;
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic int kret;
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic bool killed;
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic DEBUG(SSSDBG_IMPORTANT_INFO, ("Returned with: %d\n", ret));
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic /* Kill all of our known children manually */
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic DLIST_FOR_EACH(svc, mt_ctx->svc_list) {
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic if (svc->pid == 0) {
f072359f493a5209335799da85ac16d6a273303bgryzor /* The local provider has no PID */
f072359f493a5209335799da85ac16d6a273303bgryzor continue;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor killed = false;
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(1, ("Terminating [%s][%d]\n", svc->name, svc->pid));
f072359f493a5209335799da85ac16d6a273303bgryzor do {
f072359f493a5209335799da85ac16d6a273303bgryzor errno = 0;
f072359f493a5209335799da85ac16d6a273303bgryzor kret = kill(svc->pid, SIGTERM);
f072359f493a5209335799da85ac16d6a273303bgryzor if (kret < 0) {
ac2a72149b423e2e84596098d7e47af88ebd215asf error = errno;
ac2a72149b423e2e84596098d7e47af88ebd215asf DEBUG(1, ("Couldn't kill [%s][%d]: [%s]\n",
ac2a72149b423e2e84596098d7e47af88ebd215asf svc->name, svc->pid, strerror(error)));
ac2a72149b423e2e84596098d7e47af88ebd215asf }
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asf error = 0;
ac2a72149b423e2e84596098d7e47af88ebd215asf do {
ac2a72149b423e2e84596098d7e47af88ebd215asf errno = 0;
ac2a72149b423e2e84596098d7e47af88ebd215asf pid = waitpid(svc->pid, &status, WNOHANG);
ac2a72149b423e2e84596098d7e47af88ebd215asf if (pid == -1) {
ac2a72149b423e2e84596098d7e47af88ebd215asf /* An error occurred while waiting */
ac2a72149b423e2e84596098d7e47af88ebd215asf error = errno;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim if (error != EINTR) {
ac2a72149b423e2e84596098d7e47af88ebd215asf DEBUG(0, ("[%d][%s] while waiting for [%s]\n",
f072359f493a5209335799da85ac16d6a273303bgryzor error, strerror(error), svc->name));
f072359f493a5209335799da85ac16d6a273303bgryzor /* Forcibly kill this child */
ac2a72149b423e2e84596098d7e47af88ebd215asf kill(svc->pid, SIGKILL);
ac2a72149b423e2e84596098d7e47af88ebd215asf break;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor } else if (pid != 0) {
f072359f493a5209335799da85ac16d6a273303bgryzor error = 0;
f072359f493a5209335799da85ac16d6a273303bgryzor if WIFEXITED(status) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(1, ("Child [%s] exited gracefully\n", svc->name));
f072359f493a5209335799da85ac16d6a273303bgryzor } else if WIFSIGNALED(status) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(1, ("Child [%s] terminated with a signal\n", svc->name));
f072359f493a5209335799da85ac16d6a273303bgryzor } else {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(0, ("Child [%s] did not exit cleanly\n", svc->name));
f072359f493a5209335799da85ac16d6a273303bgryzor /* Forcibly kill this child */
f072359f493a5209335799da85ac16d6a273303bgryzor kill(svc->pid, SIGKILL);
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor killed = true;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor } while (error == EINTR);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!killed) {
f072359f493a5209335799da85ac16d6a273303bgryzor /* Sleep 10ms and try again */
f072359f493a5209335799da85ac16d6a273303bgryzor usleep(10000);
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor } while (!killed);
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor#if HAVE_GETPGRP
f072359f493a5209335799da85ac16d6a273303bgryzor /* Kill any remaining children in our process group, just in case
48c64aeceef385e19025b384bd719b2a9789592dnd * we have any leftover children we don't expect. For example, if
f072359f493a5209335799da85ac16d6a273303bgryzor * a krb5_child or ldap_child is running at the same moment.
f072359f493a5209335799da85ac16d6a273303bgryzor */
f072359f493a5209335799da85ac16d6a273303bgryzor error = 0;
f072359f493a5209335799da85ac16d6a273303bgryzor if (getpgrp() == getpid()) {
f072359f493a5209335799da85ac16d6a273303bgryzor kill(-getpgrp(), SIGTERM);
f072359f493a5209335799da85ac16d6a273303bgryzor do {
f072359f493a5209335799da85ac16d6a273303bgryzor errno = 0;
f072359f493a5209335799da85ac16d6a273303bgryzor pid = waitpid(0, &status, 0);
f072359f493a5209335799da85ac16d6a273303bgryzor if (pid == -1) {
f072359f493a5209335799da85ac16d6a273303bgryzor error = errno;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor } while (error == EINTR || pid > 0);
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor#endif
f072359f493a5209335799da85ac16d6a273303bgryzor
f4fa200e8481572da4d572759152b7c7c68facb4rbowen monitor_cleanup();
f4fa200e8481572da4d572759152b7c7c68facb4rbowen
f4fa200e8481572da4d572759152b7c7c68facb4rbowen exit(ret);
f4fa200e8481572da4d572759152b7c7c68facb4rbowen}
f4fa200e8481572da4d572759152b7c7c68facb4rbowen
f4fa200e8481572da4d572759152b7c7c68facb4rbowenstatic void monitor_quit_signal(struct tevent_context *ev,
f4fa200e8481572da4d572759152b7c7c68facb4rbowen struct tevent_signal *se,
f4fa200e8481572da4d572759152b7c7c68facb4rbowen int signum,
f4fa200e8481572da4d572759152b7c7c68facb4rbowen int count,
f4fa200e8481572da4d572759152b7c7c68facb4rbowen void *siginfo,
f4fa200e8481572da4d572759152b7c7c68facb4rbowen void *private_data)
f4fa200e8481572da4d572759152b7c7c68facb4rbowen{
f4fa200e8481572da4d572759152b7c7c68facb4rbowen struct mt_ctx *mt_ctx = talloc_get_type(private_data, struct mt_ctx);
f4fa200e8481572da4d572759152b7c7c68facb4rbowen
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_TRACE_INTERNAL, ("Received shutdown command\n"));
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_IMPORTANT_INFO, ("Monitor received %s: terminating "
f072359f493a5209335799da85ac16d6a273303bgryzor "children\n", strsignal(signum)));
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor monitor_quit(mt_ctx, 0);
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
48c64aeceef385e19025b384bd719b2a9789592dndstatic void signal_res_init(struct mt_ctx *monitor)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_svc *cur_svc;
f072359f493a5209335799da85ac16d6a273303bgryzor int ret;
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_OP_FAILURE, ("Reloading Resolv.conf.\n"));
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf ret = res_init();
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf if (ret == 0) {
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf for(cur_svc = monitor->svc_list; cur_svc; cur_svc = cur_svc->next) {
f072359f493a5209335799da85ac16d6a273303bgryzor service_signal_dns_reload(cur_svc);
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic void signal_offline(struct tevent_context *ev,
f072359f493a5209335799da85ac16d6a273303bgryzor struct tevent_signal *se,
f072359f493a5209335799da85ac16d6a273303bgryzor int signum,
f072359f493a5209335799da85ac16d6a273303bgryzor int count,
f072359f493a5209335799da85ac16d6a273303bgryzor void *siginfo,
f072359f493a5209335799da85ac16d6a273303bgryzor void *private_data)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_ctx *monitor;
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_svc *cur_svc;
f072359f493a5209335799da85ac16d6a273303bgryzor
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf monitor = talloc_get_type(private_data, struct mt_ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_TRACE_INTERNAL,
f072359f493a5209335799da85ac16d6a273303bgryzor ("Signaling providers to go offline immediately.\n"));
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* Signal all providers to immediately go offline */
f072359f493a5209335799da85ac16d6a273303bgryzor for(cur_svc = monitor->svc_list; cur_svc; cur_svc = cur_svc->next) {
f072359f493a5209335799da85ac16d6a273303bgryzor /* Don't signal services, only providers */
f072359f493a5209335799da85ac16d6a273303bgryzor if (cur_svc->provider) {
f072359f493a5209335799da85ac16d6a273303bgryzor service_signal_offline(cur_svc);
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic void signal_offline_reset(struct tevent_context *ev,
f072359f493a5209335799da85ac16d6a273303bgryzor struct tevent_signal *se,
f072359f493a5209335799da85ac16d6a273303bgryzor int signum,
f072359f493a5209335799da85ac16d6a273303bgryzor int count,
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic void *siginfo,
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic void *private_data)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_ctx *monitor;
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_svc *cur_svc;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor monitor = talloc_get_type(private_data, struct mt_ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_TRACE_INTERNAL,
f072359f493a5209335799da85ac16d6a273303bgryzor ("Signaling providers to reset offline immediately.\n"));
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor for(cur_svc = monitor->svc_list; cur_svc; cur_svc = cur_svc->next) {
f072359f493a5209335799da85ac16d6a273303bgryzor if (cur_svc->provider) {
f072359f493a5209335799da85ac16d6a273303bgryzor service_signal_reset_offline(cur_svc);
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor signal_res_init(monitor);
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int monitor_ctx_destructor(void *mem)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_ctx *mon = talloc_get_type(mem, struct mt_ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_svc *svc;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* zero out references in svcs so that they don't try
f072359f493a5209335799da85ac16d6a273303bgryzor * to access the monitor context on process shutdown */
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor for (svc = mon->svc_list; svc; svc = svc->next) {
f072359f493a5209335799da85ac16d6a273303bgryzor svc->mt_ctx = NULL;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor return 0;
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic errno_t load_configuration(TALLOC_CTX *mem_ctx,
f072359f493a5209335799da85ac16d6a273303bgryzor const char *config_file,
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_ctx **monitor)
f072359f493a5209335799da85ac16d6a273303bgryzor{
ac2a72149b423e2e84596098d7e47af88ebd215asf errno_t ret;
ac2a72149b423e2e84596098d7e47af88ebd215asf struct mt_ctx *ctx;
ac2a72149b423e2e84596098d7e47af88ebd215asf char *cdb_file = NULL;
ac2a72149b423e2e84596098d7e47af88ebd215asf
ac2a72149b423e2e84596098d7e47af88ebd215asf ctx = talloc_zero(mem_ctx, struct mt_ctx);
ac2a72149b423e2e84596098d7e47af88ebd215asf if(!ctx) {
ac2a72149b423e2e84596098d7e47af88ebd215asf return ENOMEM;
ac2a72149b423e2e84596098d7e47af88ebd215asf }
f072359f493a5209335799da85ac16d6a273303bgryzor
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf talloc_set_destructor((TALLOC_CTX *)ctx, monitor_ctx_destructor);
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf cdb_file = talloc_asprintf(ctx, "%s/%s", DB_PATH, CONFDB_FILE);
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf if (cdb_file == NULL) {
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf DEBUG(0,("Out of memory, aborting!\n"));
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf ret = ENOMEM;
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf goto done;
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf }
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf ret = confdb_init(ctx, &ctx->cdb, cdb_file);
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf if (ret != EOK) {
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf DEBUG(0,("The confdb initialization failed\n"));
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf goto done;
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf }
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf /* Initialize the CDB from the configuration file */
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf ret = confdb_test(ctx->cdb);
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf if (ret == ENOENT) {
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim /* First-time setup */
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf
7159c12b7697fe9f5ab3a533cc6dfc3d57803053igalic /* Purge any existing confdb in case an old
7159c12b7697fe9f5ab3a533cc6dfc3d57803053igalic * misconfiguration gets in the way
7159c12b7697fe9f5ab3a533cc6dfc3d57803053igalic */
7159c12b7697fe9f5ab3a533cc6dfc3d57803053igalic talloc_zfree(ctx->cdb);
7159c12b7697fe9f5ab3a533cc6dfc3d57803053igalic unlink(cdb_file);
7159c12b7697fe9f5ab3a533cc6dfc3d57803053igalic
7159c12b7697fe9f5ab3a533cc6dfc3d57803053igalic ret = confdb_init(ctx, &ctx->cdb, cdb_file);
7159c12b7697fe9f5ab3a533cc6dfc3d57803053igalic if (ret != EOK) {
7159c12b7697fe9f5ab3a533cc6dfc3d57803053igalic DEBUG(0,("The confdb initialization failed\n"));
7159c12b7697fe9f5ab3a533cc6dfc3d57803053igalic goto done;
7f0952c0239ea2d6e37b472db6fde4ef2718343dsf }
f072359f493a5209335799da85ac16d6a273303bgryzor
5479b5fa65d8ec88ea9c4389fd1b2c2728585571nd /* Load special entries */
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim ret = confdb_create_base(ctx->cdb);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim if (ret != EOK) {
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim DEBUG(0, ("Unable to load special entries into confdb\n"));
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim goto done;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim } else if (ret != EOK) {
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim DEBUG(0, ("Fatal error initializing confdb\n"));
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim goto done;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim talloc_zfree(cdb_file);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
f072359f493a5209335799da85ac16d6a273303bgryzor ret = confdb_init_db(config_file, ctx->cdb);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret != EOK) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(0, ("ConfDB initialization has failed [%s]\n",
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim strerror(ret)));
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim goto done;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim /* Validate the configuration in the database */
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim /* Read in the monitor's configuration */
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim ret = get_monitor_config(ctx);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim if (ret != EOK) {
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim goto done;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
f072359f493a5209335799da85ac16d6a273303bgryzor *monitor = ctx;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor ret = EOK;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzordone:
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret != EOK) {
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor return ret;
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor#ifdef HAVE_SYS_INOTIFY_H
f072359f493a5209335799da85ac16d6a273303bgryzorstatic void process_config_file(struct tevent_context *ev,
f072359f493a5209335799da85ac16d6a273303bgryzor struct tevent_timer *te,
f072359f493a5209335799da85ac16d6a273303bgryzor struct timeval t, void *ptr);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic void config_file_changed(struct tevent_context *ev,
f072359f493a5209335799da85ac16d6a273303bgryzor struct tevent_fd *fde,
f072359f493a5209335799da85ac16d6a273303bgryzor uint16_t flags, void *data)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor struct tevent_timer *te = NULL;
44a442483c2ae67ab94061b87ca3312bc83b059crbowen struct timeval tv;
44a442483c2ae67ab94061b87ca3312bc83b059crbowen struct config_file_ctx *file_ctx;
44a442483c2ae67ab94061b87ca3312bc83b059crbowen
44a442483c2ae67ab94061b87ca3312bc83b059crbowen file_ctx = talloc_get_type(data, struct config_file_ctx);
44a442483c2ae67ab94061b87ca3312bc83b059crbowen if (file_ctx->needs_update) {
44a442483c2ae67ab94061b87ca3312bc83b059crbowen /* Skip updating. It's already queued for update.
f072359f493a5209335799da85ac16d6a273303bgryzor */
f072359f493a5209335799da85ac16d6a273303bgryzor return;
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe }
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe /* We will queue the file for update in one second.
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe * This way, if there is a script writing to the file
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe * repeatedly, we won't be attempting to update multiple
f072359f493a5209335799da85ac16d6a273303bgryzor * times.
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic */
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic gettimeofday(&tv, NULL);
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic tv.tv_sec += 1;
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic
f072359f493a5209335799da85ac16d6a273303bgryzor te = tevent_add_timer(ev, ev, tv, process_config_file, file_ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!te) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(0, ("Unable to queue config file update! Exiting.\n"));
f072359f493a5209335799da85ac16d6a273303bgryzor kill(getpid(), SIGTERM);
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic return;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor file_ctx->needs_update = 1;
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstruct rewatch_ctx {
f072359f493a5209335799da85ac16d6a273303bgryzor struct config_file_callback *cb;
f072359f493a5209335799da85ac16d6a273303bgryzor struct config_file_ctx *file_ctx;
f072359f493a5209335799da85ac16d6a273303bgryzor};
f072359f493a5209335799da85ac16d6a273303bgryzorstatic void rewatch_config_file(struct tevent_context *ev,
f072359f493a5209335799da85ac16d6a273303bgryzor struct tevent_timer *te,
f072359f493a5209335799da85ac16d6a273303bgryzor struct timeval t, void *ptr);
f072359f493a5209335799da85ac16d6a273303bgryzorstatic void process_config_file(struct tevent_context *ev,
f072359f493a5209335799da85ac16d6a273303bgryzor struct tevent_timer *te,
f072359f493a5209335799da85ac16d6a273303bgryzor struct timeval t, void *ptr)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor TALLOC_CTX *tmp_ctx;
f072359f493a5209335799da85ac16d6a273303bgryzor struct inotify_event *in_event;
f072359f493a5209335799da85ac16d6a273303bgryzor char *buf;
f072359f493a5209335799da85ac16d6a273303bgryzor char *name;
f072359f493a5209335799da85ac16d6a273303bgryzor ssize_t len;
f072359f493a5209335799da85ac16d6a273303bgryzor ssize_t event_size;
f072359f493a5209335799da85ac16d6a273303bgryzor struct config_file_ctx *file_ctx;
f072359f493a5209335799da85ac16d6a273303bgryzor struct config_file_callback *cb;
f072359f493a5209335799da85ac16d6a273303bgryzor struct rewatch_ctx *rw_ctx;
f072359f493a5209335799da85ac16d6a273303bgryzor errno_t ret;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor event_size = sizeof(struct inotify_event);
9534272616b71aaea50aeec4162e749a96aebd7fsf file_ctx = talloc_get_type(ptr, struct config_file_ctx);
9534272616b71aaea50aeec4162e749a96aebd7fsf
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(1, ("Processing config file changes\n"));
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor tmp_ctx = talloc_new(NULL);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!tmp_ctx) return;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor buf = talloc_size(tmp_ctx, event_size);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!buf) {
f072359f493a5209335799da85ac16d6a273303bgryzor goto done;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor errno = 0;
f072359f493a5209335799da85ac16d6a273303bgryzor len = sss_atomic_read_s(file_ctx->mt_ctx->inotify_fd, buf, event_size);
f072359f493a5209335799da85ac16d6a273303bgryzor if (len == -1) {
f072359f493a5209335799da85ac16d6a273303bgryzor ret = errno;
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_CRIT_FAILURE,
f072359f493a5209335799da85ac16d6a273303bgryzor ("Critical error reading inotify file descriptor [%d]: %s\n",
f072359f493a5209335799da85ac16d6a273303bgryzor ret, strerror(ret)));
f072359f493a5209335799da85ac16d6a273303bgryzor goto done;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor in_event = (struct inotify_event *)buf;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor if (in_event->len > 0) {
f072359f493a5209335799da85ac16d6a273303bgryzor /* Read in the name, even though we don't use it,
eef716e54c415709ca9d53aad4678bf9d96186e6nd * so that read ptr is in the right place
f072359f493a5209335799da85ac16d6a273303bgryzor */
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim name = talloc_size(tmp_ctx, in_event->len);
eef716e54c415709ca9d53aad4678bf9d96186e6nd if (!name) {
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim goto done;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor errno = 0;
eef716e54c415709ca9d53aad4678bf9d96186e6nd len = sss_atomic_read_s(file_ctx->mt_ctx->inotify_fd, name, in_event->len);
eef716e54c415709ca9d53aad4678bf9d96186e6nd if (len == -1) {
f072359f493a5209335799da85ac16d6a273303bgryzor ret = errno;
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_CRIT_FAILURE,
f072359f493a5209335799da85ac16d6a273303bgryzor ("Critical error reading inotify file descriptor [%d]: %s\n",
f072359f493a5209335799da85ac16d6a273303bgryzor ret, strerror(ret)));
f072359f493a5209335799da85ac16d6a273303bgryzor goto done;
f072359f493a5209335799da85ac16d6a273303bgryzor }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
eef716e54c415709ca9d53aad4678bf9d96186e6nd
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim for (cb = file_ctx->callbacks; cb; cb = cb->next) {
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim if (cb->wd == in_event->wd) {
f072359f493a5209335799da85ac16d6a273303bgryzor break;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor if (!cb) {
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim DEBUG(0, ("Unknown watch descriptor\n"));
eef716e54c415709ca9d53aad4678bf9d96186e6nd goto done;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
f072359f493a5209335799da85ac16d6a273303bgryzor if (in_event->mask & IN_IGNORED) {
f072359f493a5209335799da85ac16d6a273303bgryzor /* Some text editors will move a new file on top of the
f072359f493a5209335799da85ac16d6a273303bgryzor * existing one instead of modifying it. In this case,
f072359f493a5209335799da85ac16d6a273303bgryzor * the kernel will send us an IN_IGNORE signal.
f072359f493a5209335799da85ac16d6a273303bgryzor * We will try to open a new watch descriptor on the
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe * new file.
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe */
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe struct timeval tv;
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe struct tevent_timer *tev;
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe tv.tv_sec = t.tv_sec+5;
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe tv.tv_usec = t.tv_usec;
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe DEBUG(5, ("Restoring inotify watch.\n"));
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe
db8dceaf53a26fba6048c2ad4d86c5507344187drbowen cb->retries = 0;
db8dceaf53a26fba6048c2ad4d86c5507344187drbowen rw_ctx = talloc(file_ctx, struct rewatch_ctx);
db8dceaf53a26fba6048c2ad4d86c5507344187drbowen if(!rw_ctx) {
db8dceaf53a26fba6048c2ad4d86c5507344187drbowen DEBUG(0, ("Could not restore inotify watch. Quitting!\n"));
db8dceaf53a26fba6048c2ad4d86c5507344187drbowen close(file_ctx->mt_ctx->inotify_fd);
db8dceaf53a26fba6048c2ad4d86c5507344187drbowen kill(getpid(), SIGTERM);
db8dceaf53a26fba6048c2ad4d86c5507344187drbowen goto done;
db8dceaf53a26fba6048c2ad4d86c5507344187drbowen }
db8dceaf53a26fba6048c2ad4d86c5507344187drbowen rw_ctx->cb = cb;
db8dceaf53a26fba6048c2ad4d86c5507344187drbowen rw_ctx->file_ctx = file_ctx;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor tev = tevent_add_timer(ev, rw_ctx, tv, rewatch_config_file, rw_ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor if (tev == NULL) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(0, ("Could not restore inotify watch. Quitting!\n"));
f072359f493a5209335799da85ac16d6a273303bgryzor close(file_ctx->mt_ctx->inotify_fd);
f072359f493a5209335799da85ac16d6a273303bgryzor kill(getpid(), SIGTERM);
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor goto done;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* Tell the monitor to signal the children */
f072359f493a5209335799da85ac16d6a273303bgryzor cb->fn(file_ctx, cb->filename);
48c64aeceef385e19025b384bd719b2a9789592dnd file_ctx->needs_update = 0;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzordone:
48c64aeceef385e19025b384bd719b2a9789592dnd talloc_free(tmp_ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorerrno_t monitor_config_file_fallback(TALLOC_CTX *mem_ctx,
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_ctx *ctx,
f072359f493a5209335799da85ac16d6a273303bgryzor const char *file,
f072359f493a5209335799da85ac16d6a273303bgryzor monitor_reconf_fn fn,
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim bool ignore_missing);
737a1f4117ce00c29a1b78b93db08e4a273ab2edtrawickstatic void rewatch_config_file(struct tevent_context *ev,
f072359f493a5209335799da85ac16d6a273303bgryzor struct tevent_timer *te,
f072359f493a5209335799da85ac16d6a273303bgryzor struct timeval t, void *ptr)
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim{
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim int err;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim struct tevent_timer *tev = NULL;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim struct timeval tv;
f072359f493a5209335799da85ac16d6a273303bgryzor struct config_file_callback *cb;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor struct rewatch_ctx *rw_ctx;
f072359f493a5209335799da85ac16d6a273303bgryzor struct config_file_ctx *file_ctx;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor rw_ctx = talloc_get_type(ptr, struct rewatch_ctx);
eef716e54c415709ca9d53aad4678bf9d96186e6nd
f072359f493a5209335799da85ac16d6a273303bgryzor cb = rw_ctx->cb;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim file_ctx = rw_ctx->file_ctx;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim /* Retry six times at five-second intervals before giving up */
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim cb->retries++;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim if (cb->retries > 6) {
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim DEBUG(SSSDBG_FATAL_FAILURE,
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim ("Could not restore inotify watch. Switching to polling!\n"));
f072359f493a5209335799da85ac16d6a273303bgryzor close(file_ctx->mt_ctx->inotify_fd);
f072359f493a5209335799da85ac16d6a273303bgryzor err = monitor_config_file_fallback(file_ctx->parent_ctx,
eef716e54c415709ca9d53aad4678bf9d96186e6nd file_ctx->mt_ctx,
eef716e54c415709ca9d53aad4678bf9d96186e6nd cb->filename,
f072359f493a5209335799da85ac16d6a273303bgryzor cb->fn,true);
f072359f493a5209335799da85ac16d6a273303bgryzor if (err != EOK)
eef716e54c415709ca9d53aad4678bf9d96186e6nd kill(getpid(), SIGTERM);
eef716e54c415709ca9d53aad4678bf9d96186e6nd
eef716e54c415709ca9d53aad4678bf9d96186e6nd cb->fn(file_ctx, cb->filename);
48c64aeceef385e19025b384bd719b2a9789592dnd talloc_free(rw_ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* A new callback was created in monitor_config_file_fallback()*/
f072359f493a5209335799da85ac16d6a273303bgryzor DLIST_REMOVE(file_ctx->callbacks, cb);
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(cb);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor return;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor cb->wd = inotify_add_watch(file_ctx->mt_ctx->inotify_fd,
f072359f493a5209335799da85ac16d6a273303bgryzor cb->filename, IN_MODIFY);
f072359f493a5209335799da85ac16d6a273303bgryzor if (cb->wd < 0) {
f072359f493a5209335799da85ac16d6a273303bgryzor err = errno;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor tv.tv_sec = t.tv_sec+5;
f072359f493a5209335799da85ac16d6a273303bgryzor tv.tv_usec = t.tv_usec;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_CRIT_FAILURE,
f072359f493a5209335799da85ac16d6a273303bgryzor ("Could not add inotify watch for file [%s]. Error [%d:%s]\n",
f072359f493a5209335799da85ac16d6a273303bgryzor cb->filename, err, strerror(err)));
f072359f493a5209335799da85ac16d6a273303bgryzor
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe tev = tevent_add_timer(ev, ev, tv, rewatch_config_file, rw_ctx);
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe if (tev == NULL) {
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe DEBUG(SSSDBG_FATAL_FAILURE,
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe ("Could not restore inotify watch. Quitting!\n"));
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe close(file_ctx->mt_ctx->inotify_fd);
7e9c796f2dc0dba993a817b3a58cfd56b4e511edwrowe kill(getpid(), SIGTERM);
f072359f493a5209335799da85ac16d6a273303bgryzor }
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic return;
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic }
70f5253b24dd333c67fb6502d557a8b48ad3ba87igalic cb->retries = 0;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* Tell the monitor to signal the children */
f072359f493a5209335799da85ac16d6a273303bgryzor cb->fn(file_ctx, cb->filename);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(rw_ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor file_ctx->needs_update = 0;
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor#endif
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic void poll_config_file(struct tevent_context *ev,
f072359f493a5209335799da85ac16d6a273303bgryzor struct tevent_timer *te,
f072359f493a5209335799da85ac16d6a273303bgryzor struct timeval t, void *ptr)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor int ret, err;
f072359f493a5209335799da85ac16d6a273303bgryzor struct stat file_stat;
f072359f493a5209335799da85ac16d6a273303bgryzor struct timeval tv;
f072359f493a5209335799da85ac16d6a273303bgryzor struct config_file_ctx *file_ctx;
f072359f493a5209335799da85ac16d6a273303bgryzor struct config_file_callback *cb;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor file_ctx = talloc_get_type(ptr,struct config_file_ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor for (cb = file_ctx->callbacks; cb; cb = cb->next) {
f072359f493a5209335799da85ac16d6a273303bgryzor ret = stat(cb->filename, &file_stat);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret < 0) {
f072359f493a5209335799da85ac16d6a273303bgryzor err = errno;
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(0, ("Could not stat file [%s]. Error [%d:%s]\n",
f072359f493a5209335799da85ac16d6a273303bgryzor cb->filename, err, strerror(err)));
f072359f493a5209335799da85ac16d6a273303bgryzor /* TODO: If the config file is missing, should we shut down? */
f072359f493a5209335799da85ac16d6a273303bgryzor return;
f072359f493a5209335799da85ac16d6a273303bgryzor }
9534272616b71aaea50aeec4162e749a96aebd7fsf
9534272616b71aaea50aeec4162e749a96aebd7fsf if (file_stat.st_mtime != cb->modified) {
9534272616b71aaea50aeec4162e749a96aebd7fsf /* Parse the configuration file and signal the children */
9534272616b71aaea50aeec4162e749a96aebd7fsf /* Note: this will fire if the modification time changes into the past
9534272616b71aaea50aeec4162e749a96aebd7fsf * as well as the future.
9534272616b71aaea50aeec4162e749a96aebd7fsf */
9534272616b71aaea50aeec4162e749a96aebd7fsf DEBUG(1, ("Config file changed\n"));
9534272616b71aaea50aeec4162e749a96aebd7fsf cb->modified = file_stat.st_mtime;
9534272616b71aaea50aeec4162e749a96aebd7fsf
9534272616b71aaea50aeec4162e749a96aebd7fsf /* Tell the monitor to signal the children */
9534272616b71aaea50aeec4162e749a96aebd7fsf cb->fn(file_ctx, cb->filename);
9534272616b71aaea50aeec4162e749a96aebd7fsf }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
9534272616b71aaea50aeec4162e749a96aebd7fsf
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim gettimeofday(&tv, NULL);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim tv.tv_sec += CONFIG_FILE_POLL_INTERVAL;
9534272616b71aaea50aeec4162e749a96aebd7fsf tv.tv_usec = 0;
9534272616b71aaea50aeec4162e749a96aebd7fsf file_ctx->timer = tevent_add_timer(ev, file_ctx->parent_ctx, tv,
9534272616b71aaea50aeec4162e749a96aebd7fsf poll_config_file, file_ctx);
9534272616b71aaea50aeec4162e749a96aebd7fsf if (!file_ctx->timer) {
9534272616b71aaea50aeec4162e749a96aebd7fsf DEBUG(0, ("Error: Config file no longer monitored for changes!\n"));
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int try_inotify(struct config_file_ctx *file_ctx, const char *filename,
f072359f493a5209335799da85ac16d6a273303bgryzor monitor_reconf_fn fn)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor#ifdef HAVE_SYS_INOTIFY_H
f072359f493a5209335799da85ac16d6a273303bgryzor int err, fd_args, ret;
f072359f493a5209335799da85ac16d6a273303bgryzor struct tevent_fd *tfd;
201fc52d132d8f375e6c4351921367897fb5265and struct config_file_callback *cb;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* Monitoring the file descriptor should be global */
48c64aeceef385e19025b384bd719b2a9789592dnd if (!file_ctx->mt_ctx->inotify_fd) {
3c13a815670b54d1c17bf02954f7d2b066cde95cnd /* Set up inotify to monitor the config file for changes */
f072359f493a5209335799da85ac16d6a273303bgryzor file_ctx->mt_ctx->inotify_fd = inotify_init();
f072359f493a5209335799da85ac16d6a273303bgryzor if (file_ctx->mt_ctx->inotify_fd < 0) {
f072359f493a5209335799da85ac16d6a273303bgryzor err = errno;
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(0, ("Could not initialize inotify, error [%d:%s]\n",
f072359f493a5209335799da85ac16d6a273303bgryzor err, strerror(err)));
f072359f493a5209335799da85ac16d6a273303bgryzor return err;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor fd_args = fcntl(file_ctx->mt_ctx->inotify_fd, F_GETFL, NULL);
f072359f493a5209335799da85ac16d6a273303bgryzor if (fd_args < 0) {
f072359f493a5209335799da85ac16d6a273303bgryzor /* Could not set nonblocking */
f072359f493a5209335799da85ac16d6a273303bgryzor close(file_ctx->mt_ctx->inotify_fd);
f072359f493a5209335799da85ac16d6a273303bgryzor return EINVAL;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor fd_args |= O_NONBLOCK;
f072359f493a5209335799da85ac16d6a273303bgryzor ret = fcntl(file_ctx->mt_ctx->inotify_fd, F_SETFL, fd_args);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret < 0) {
f072359f493a5209335799da85ac16d6a273303bgryzor /* Could not set nonblocking */
f072359f493a5209335799da85ac16d6a273303bgryzor close(file_ctx->mt_ctx->inotify_fd);
f072359f493a5209335799da85ac16d6a273303bgryzor return EINVAL;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* Add the inotify file descriptor to the TEvent context */
f072359f493a5209335799da85ac16d6a273303bgryzor tfd = tevent_add_fd(file_ctx->mt_ctx->ev, file_ctx,
f072359f493a5209335799da85ac16d6a273303bgryzor file_ctx->mt_ctx->inotify_fd,
f072359f493a5209335799da85ac16d6a273303bgryzor TEVENT_FD_READ, config_file_changed,
f072359f493a5209335799da85ac16d6a273303bgryzor file_ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!tfd) {
f072359f493a5209335799da85ac16d6a273303bgryzor close(file_ctx->mt_ctx->inotify_fd);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim return EIO;
f072359f493a5209335799da85ac16d6a273303bgryzor }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
f072359f493a5209335799da85ac16d6a273303bgryzor cb = talloc_zero(file_ctx, struct config_file_callback);
f072359f493a5209335799da85ac16d6a273303bgryzor if(!cb) {
f072359f493a5209335799da85ac16d6a273303bgryzor close(file_ctx->mt_ctx->inotify_fd);
f072359f493a5209335799da85ac16d6a273303bgryzor return EIO;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor cb->filename = talloc_strdup(cb, filename);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!cb->filename) {
f072359f493a5209335799da85ac16d6a273303bgryzor close(file_ctx->mt_ctx->inotify_fd);
f072359f493a5209335799da85ac16d6a273303bgryzor return ENOMEM;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor cb->wd = inotify_add_watch(file_ctx->mt_ctx->inotify_fd,
f072359f493a5209335799da85ac16d6a273303bgryzor cb->filename, IN_MODIFY);
f072359f493a5209335799da85ac16d6a273303bgryzor if (cb->wd < 0) {
f072359f493a5209335799da85ac16d6a273303bgryzor err = errno;
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(0, ("Could not add inotify watch for file [%s]. Error [%d:%s]\n",
f072359f493a5209335799da85ac16d6a273303bgryzor cb->filename, err, strerror(err)));
f072359f493a5209335799da85ac16d6a273303bgryzor close(file_ctx->mt_ctx->inotify_fd);
f072359f493a5209335799da85ac16d6a273303bgryzor return err;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor cb->fn = fn;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor DLIST_ADD(file_ctx->callbacks, cb);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor return EOK;
f072359f493a5209335799da85ac16d6a273303bgryzor#else
f072359f493a5209335799da85ac16d6a273303bgryzor return EINVAL;
6d20aeba2c4aa0938bc6e0659d13adc7670ff421poirier#endif
6d20aeba2c4aa0938bc6e0659d13adc7670ff421poirier}
6d20aeba2c4aa0938bc6e0659d13adc7670ff421poirier
f072359f493a5209335799da85ac16d6a273303bgryzorstatic int monitor_config_file(TALLOC_CTX *mem_ctx,
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim struct mt_ctx *ctx,
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim const char *file,
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim monitor_reconf_fn fn,
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim bool ignore_missing)
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim{
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim int ret, err;
f072359f493a5209335799da85ac16d6a273303bgryzor bool use_inotify;
f072359f493a5209335799da85ac16d6a273303bgryzor struct stat file_stat;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor ret = stat(file, &file_stat);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret < 0) {
f072359f493a5209335799da85ac16d6a273303bgryzor err = errno;
f072359f493a5209335799da85ac16d6a273303bgryzor if (err == ENOENT && ignore_missing) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_MINOR_FAILURE,
f072359f493a5209335799da85ac16d6a273303bgryzor ("file [%s] is missing. Will not update online status "
f072359f493a5209335799da85ac16d6a273303bgryzor "based on watching the file\n", file));
f072359f493a5209335799da85ac16d6a273303bgryzor return EOK;
f072359f493a5209335799da85ac16d6a273303bgryzor } else {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_FATAL_FAILURE,
f072359f493a5209335799da85ac16d6a273303bgryzor ("Could not stat file [%s]. Error [%d:%s]\n",
f072359f493a5209335799da85ac16d6a273303bgryzor file, err, strerror(err)));
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor return err;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor if (!ctx->file_ctx) {
f072359f493a5209335799da85ac16d6a273303bgryzor ctx->file_ctx = talloc_zero(mem_ctx, struct config_file_ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!ctx->file_ctx) return ENOMEM;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor ctx->file_ctx->parent_ctx = mem_ctx;
f072359f493a5209335799da85ac16d6a273303bgryzor ctx->file_ctx->mt_ctx = ctx;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor ret = confdb_get_bool(ctx->cdb,
f072359f493a5209335799da85ac16d6a273303bgryzor CONFDB_MONITOR_CONF_ENTRY,
f072359f493a5209335799da85ac16d6a273303bgryzor CONFDB_MONITOR_TRY_INOTIFY,
f072359f493a5209335799da85ac16d6a273303bgryzor true, &use_inotify);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret != EOK) {
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(ctx->file_ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor return ret;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor if (use_inotify) {
f072359f493a5209335799da85ac16d6a273303bgryzor ret = try_inotify(ctx->file_ctx, file, fn);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret != EOK) {
f072359f493a5209335799da85ac16d6a273303bgryzor use_inotify = false;
48c64aeceef385e19025b384bd719b2a9789592dnd }
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor if (!use_inotify) {
f072359f493a5209335799da85ac16d6a273303bgryzor /* Could not monitor file with inotify, fall back to polling */
f072359f493a5209335799da85ac16d6a273303bgryzor ret = monitor_config_file_fallback(mem_ctx, ctx, file, fn, true);
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor return ret;
f072359f493a5209335799da85ac16d6a273303bgryzor}
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzorerrno_t monitor_config_file_fallback(TALLOC_CTX *mem_ctx,
f072359f493a5209335799da85ac16d6a273303bgryzor struct mt_ctx *ctx,
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim const char *file,
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim monitor_reconf_fn fn,
f57afe001aa9064dc2199b261ddeb161ff12c381humbedooh bool ignore_missing)
f072359f493a5209335799da85ac16d6a273303bgryzor{
f072359f493a5209335799da85ac16d6a273303bgryzor struct config_file_callback *cb = NULL;
f072359f493a5209335799da85ac16d6a273303bgryzor struct stat file_stat;
f072359f493a5209335799da85ac16d6a273303bgryzor int ret, err;
f072359f493a5209335799da85ac16d6a273303bgryzor struct timeval tv;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor ret = stat(file, &file_stat);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret < 0) {
f072359f493a5209335799da85ac16d6a273303bgryzor err = errno;
f072359f493a5209335799da85ac16d6a273303bgryzor if (err == ENOENT && ignore_missing) {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_MINOR_FAILURE,
f072359f493a5209335799da85ac16d6a273303bgryzor ("file [%s] is missing. Will not update online status "
f072359f493a5209335799da85ac16d6a273303bgryzor "based on watching the file\n", file));
f072359f493a5209335799da85ac16d6a273303bgryzor return EOK;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor } else {
f072359f493a5209335799da85ac16d6a273303bgryzor DEBUG(SSSDBG_FATAL_FAILURE,
f072359f493a5209335799da85ac16d6a273303bgryzor ("Could not stat file [%s]. Error [%d:%s]\n",
f072359f493a5209335799da85ac16d6a273303bgryzor file, err, strerror(err)));
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor return err;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor cb = talloc_zero(ctx->file_ctx, struct config_file_callback);
48c64aeceef385e19025b384bd719b2a9789592dnd if (!cb) {
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(ctx->file_ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor return ENOMEM;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor cb->filename = talloc_strdup(cb, file);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!cb->filename) {
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_free(ctx->file_ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor return ENOMEM;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor cb->fn = fn;
f072359f493a5209335799da85ac16d6a273303bgryzor cb->modified = file_stat.st_mtime;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim DLIST_ADD(ctx->file_ctx->callbacks, cb);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim if(!ctx->file_ctx->timer) {
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim gettimeofday(&tv, NULL);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim tv.tv_sec += CONFIG_FILE_POLL_INTERVAL;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim tv.tv_usec = 0;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim ctx->file_ctx->timer = tevent_add_timer(ctx->ev, mem_ctx, tv,
f072359f493a5209335799da85ac16d6a273303bgryzor poll_config_file, ctx->file_ctx);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim if (!ctx->file_ctx->timer) {
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim talloc_free(ctx->file_ctx);
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim return EIO;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim }
f072359f493a5209335799da85ac16d6a273303bgryzor
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim return EOK;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim}
f072359f493a5209335799da85ac16d6a273303bgryzor
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjimint monitor_process_init(struct mt_ctx *ctx,
f072359f493a5209335799da85ac16d6a273303bgryzor const char *config_file)
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim{
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim TALLOC_CTX *tmp_ctx;
f072359f493a5209335799da85ac16d6a273303bgryzor struct sysdb_ctx_list *db_list;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim struct tevent_signal *tes;
27a7b74f8c50bd6074b0c71fae9927a71fde5b3fjim struct sss_domain_info *dom;
f072359f493a5209335799da85ac16d6a273303bgryzor char *rcachedir;
f072359f493a5209335799da85ac16d6a273303bgryzor int num_providers;
f072359f493a5209335799da85ac16d6a273303bgryzor int ret;
f072359f493a5209335799da85ac16d6a273303bgryzor int error;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* Set up the environment variable for the Kerberos Replay Cache */
f072359f493a5209335799da85ac16d6a273303bgryzor ret = confdb_get_string(ctx->cdb, ctx,
f072359f493a5209335799da85ac16d6a273303bgryzor CONFDB_MONITOR_CONF_ENTRY,
f072359f493a5209335799da85ac16d6a273303bgryzor CONFDB_MONITOR_KRB5_RCACHEDIR,
f072359f493a5209335799da85ac16d6a273303bgryzor KRB5_RCACHE_DIR,
f072359f493a5209335799da85ac16d6a273303bgryzor &rcachedir);
ee649f9236fe7fcf255bbfa11f2cce080f996521sf if (ret != EOK) {
ee649f9236fe7fcf255bbfa11f2cce080f996521sf return ret;
0844fff26cb7719e0f0a368d88544156ed6374b6sf }
0844fff26cb7719e0f0a368d88544156ed6374b6sf
0844fff26cb7719e0f0a368d88544156ed6374b6sf if (strcmp(rcachedir, KRB5_RCACHE_DIR_DISABLE) != 0)
ee649f9236fe7fcf255bbfa11f2cce080f996521sf {
ee649f9236fe7fcf255bbfa11f2cce080f996521sf errno = 0;
ee649f9236fe7fcf255bbfa11f2cce080f996521sf ret = setenv("KRB5RCACHEDIR", rcachedir, 1);
0844fff26cb7719e0f0a368d88544156ed6374b6sf if (ret < 0) {
0844fff26cb7719e0f0a368d88544156ed6374b6sf error = errno;
0844fff26cb7719e0f0a368d88544156ed6374b6sf DEBUG(1,
0844fff26cb7719e0f0a368d88544156ed6374b6sf ("Unable to set KRB5RCACHEDIR: %s."
0844fff26cb7719e0f0a368d88544156ed6374b6sf "Will attempt to use libkrb5 defaults\n",
0844fff26cb7719e0f0a368d88544156ed6374b6sf strerror(error)));
0844fff26cb7719e0f0a368d88544156ed6374b6sf }
0844fff26cb7719e0f0a368d88544156ed6374b6sf talloc_zfree(rcachedir);
ee649f9236fe7fcf255bbfa11f2cce080f996521sf }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* Set up an event handler for a SIGHUP */
f072359f493a5209335799da85ac16d6a273303bgryzor tes = tevent_add_signal(ctx->ev, ctx, SIGHUP, 0,
f072359f493a5209335799da85ac16d6a273303bgryzor monitor_hup, ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor if (tes == NULL) {
f072359f493a5209335799da85ac16d6a273303bgryzor return EIO;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* Set up an event handler for a SIGINT */
f072359f493a5209335799da85ac16d6a273303bgryzor BlockSignals(false, SIGINT);
f072359f493a5209335799da85ac16d6a273303bgryzor tes = tevent_add_signal(ctx->ev, ctx, SIGINT, 0,
f072359f493a5209335799da85ac16d6a273303bgryzor monitor_quit_signal, ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor if (tes == NULL) {
f072359f493a5209335799da85ac16d6a273303bgryzor return EIO;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* Set up an event handler for a SIGTERM */
f072359f493a5209335799da85ac16d6a273303bgryzor tes = tevent_add_signal(ctx->ev, ctx, SIGTERM, 0,
f072359f493a5209335799da85ac16d6a273303bgryzor monitor_quit_signal, ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor if (tes == NULL) {
f072359f493a5209335799da85ac16d6a273303bgryzor return EIO;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* Handle SIGUSR1 (tell all providers to go offline) */
f072359f493a5209335799da85ac16d6a273303bgryzor BlockSignals(false, SIGUSR1);
f072359f493a5209335799da85ac16d6a273303bgryzor tes = tevent_add_signal(ctx->ev, ctx, SIGUSR1, 0,
f072359f493a5209335799da85ac16d6a273303bgryzor signal_offline, ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor if (tes == NULL) {
f072359f493a5209335799da85ac16d6a273303bgryzor return EIO;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
48c64aeceef385e19025b384bd719b2a9789592dnd /* Handle SIGUSR2 (tell all providers to go reset offline) */
f072359f493a5209335799da85ac16d6a273303bgryzor BlockSignals(false, SIGUSR2);
f072359f493a5209335799da85ac16d6a273303bgryzor tes = tevent_add_signal(ctx->ev, ctx, SIGUSR2, 0,
f072359f493a5209335799da85ac16d6a273303bgryzor signal_offline_reset, ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor if (tes == NULL) {
f072359f493a5209335799da85ac16d6a273303bgryzor return EIO;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* Set up the SIGCHLD handler */
f072359f493a5209335799da85ac16d6a273303bgryzor ret = sss_sigchld_init(ctx, ctx->ev, &ctx->sigchld_ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret != EOK) return ret;
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor#if 0
f072359f493a5209335799da85ac16d6a273303bgryzor This feature is incomplete and can leave the SSSD in a bad state if the
f072359f493a5209335799da85ac16d6a273303bgryzor config file is changed while the SSSD is running.
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor Uncomment this once the backends are honoring reloadConfig()
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* Watch for changes to the confdb config file */
f072359f493a5209335799da85ac16d6a273303bgryzor ret = monitor_config_file(ctx, ctx, config_file, monitor_signal_reconf,
f072359f493a5209335799da85ac16d6a273303bgryzor true);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret != EOK) {
f072359f493a5209335799da85ac16d6a273303bgryzor return ret;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor#endif
f072359f493a5209335799da85ac16d6a273303bgryzor /* Watch for changes to the DNS resolv.conf */
f072359f493a5209335799da85ac16d6a273303bgryzor ret = monitor_config_file(ctx, ctx, RESOLV_CONF_PATH,
f072359f493a5209335799da85ac16d6a273303bgryzor monitor_update_resolv,true);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret != EOK) {
f072359f493a5209335799da85ac16d6a273303bgryzor return ret;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* Avoid a startup race condition between process.
f072359f493a5209335799da85ac16d6a273303bgryzor * We need to handle DB upgrades or DB creation only
f072359f493a5209335799da85ac16d6a273303bgryzor * in one process before all other start.
f072359f493a5209335799da85ac16d6a273303bgryzor */
f072359f493a5209335799da85ac16d6a273303bgryzor tmp_ctx = talloc_new(NULL);
f072359f493a5209335799da85ac16d6a273303bgryzor if (!tmp_ctx) {
f072359f493a5209335799da85ac16d6a273303bgryzor return ENOMEM;
48c64aeceef385e19025b384bd719b2a9789592dnd }
48c64aeceef385e19025b384bd719b2a9789592dnd ret = sysdb_init(tmp_ctx, ctx->cdb, NULL, true, &db_list);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret != EOK) {
f072359f493a5209335799da85ac16d6a273303bgryzor return ret;
f072359f493a5209335799da85ac16d6a273303bgryzor }
f072359f493a5209335799da85ac16d6a273303bgryzor talloc_zfree(tmp_ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor
f072359f493a5209335799da85ac16d6a273303bgryzor /* Initialize D-BUS Server
f072359f493a5209335799da85ac16d6a273303bgryzor * The monitor will act as a D-BUS server for all
f072359f493a5209335799da85ac16d6a273303bgryzor * SSSD processes */
f072359f493a5209335799da85ac16d6a273303bgryzor ret = monitor_dbus_init(ctx);
f072359f493a5209335799da85ac16d6a273303bgryzor if (ret != EOK) {
f072359f493a5209335799da85ac16d6a273303bgryzor return ret;
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung }
727872d18412fc021f03969b8641810d8896820bhumbedooh
0d0ba3a410038e179b695446bb149cce6264e0abnd ret = setup_netlink(ctx, ctx->ev, network_status_change_cb,
727872d18412fc021f03969b8641810d8896820bhumbedooh ctx, &ctx->nlctx);
cc7e1025de9ac63bd4db6fe7f71c158b2cf09fe4humbedooh if (ret != EOK) {
0d0ba3a410038e179b695446bb149cce6264e0abnd DEBUG(2, ("Cannot set up listening for network notifications\n"));
cc7e1025de9ac63bd4db6fe7f71c158b2cf09fe4humbedooh return ret;
727872d18412fc021f03969b8641810d8896820bhumbedooh }
0d0ba3a410038e179b695446bb149cce6264e0abnd
0d0ba3a410038e179b695446bb149cce6264e0abnd /* start providers */
0d0ba3a410038e179b695446bb149cce6264e0abnd num_providers = 0;
ac082aefa89416cbdc9a1836eaf3bed9698201c8humbedooh for (dom = ctx->domains; dom; dom = dom->next) {
0d0ba3a410038e179b695446bb149cce6264e0abnd ret = add_new_provider(ctx, dom->name, 0);
0d0ba3a410038e179b695446bb149cce6264e0abnd if (ret != EOK && ret != ENOENT) {
0d0ba3a410038e179b695446bb149cce6264e0abnd return ret;
727872d18412fc021f03969b8641810d8896820bhumbedooh }
0d0ba3a410038e179b695446bb149cce6264e0abnd if (ret != ENOENT) {
0d0ba3a410038e179b695446bb149cce6264e0abnd num_providers++;
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh }
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
d229f940abfb2490dee17979e9a5ff31b7012eb5rbowen
0d0ba3a410038e179b695446bb149cce6264e0abnd if (num_providers > 0) {
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd /* now set the services stratup timeout *
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd * (responders will be started automatically when all
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd * providers are up and running or when the tomeout
f072359f493a5209335799da85ac16d6a273303bgryzor * expires) */
ret = add_services_startup_timeout(ctx);
if (ret != EOK) {
return ret;
}
} else {
int i;
ctx->services_started = true;
/* No providers start services immediately
* Normally this means only LOCAL is configured */
for (i = 0; ctx->services[i]; i++) {
add_new_service(ctx, ctx->services[i], 0);
}
}
return EOK;
}
static void init_timeout(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval t, void *ptr)
{
struct mon_init_conn *mini;
DEBUG(2, ("Client timed out before Identification!\n"));
mini = talloc_get_type(ptr, struct mon_init_conn);
sbus_disconnect(mini->conn);
talloc_zfree(mini);
}
/*
* monitor_service_init
* Set up a timeout function and temporary connection structure.
* If the client does not identify before the timeout kicks in,
* the client is forcibly disconnected.
*/
static int monitor_service_init(struct sbus_connection *conn, void *data)
{
struct mt_ctx *ctx;
struct mon_init_conn *mini;
struct timeval tv;
DEBUG(SSSDBG_TRACE_FUNC, ("Initializing D-BUS Service\n"));
ctx = talloc_get_type(data, struct mt_ctx);
mini = talloc(conn, struct mon_init_conn);
if (!mini) {
DEBUG(0,("Out of memory?!\n"));
talloc_zfree(conn);
return ENOMEM;
}
mini->ctx = ctx;
mini->conn = conn;
/* 10 seconds should be plenty */
tv = tevent_timeval_current_ofs(10, 0);
mini->timeout = tevent_add_timer(ctx->ev, mini, tv, init_timeout, mini);
if (!mini->timeout) {
DEBUG(0,("Out of memory?!\n"));
talloc_zfree(conn);
return ENOMEM;
}
sbus_conn_set_private_data(conn, mini);
return EOK;
}
/* 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;
int ret;
if (!svc->conn) {
DEBUG(8, ("Service not yet initialized\n"));
return ENXIO;
}
DEBUG(4,("Pinging %s\n", svc->name));
/*
* Set up identity request
* This should be a well-known path and method
* for all services
*/
msg = dbus_message_new_method_call(NULL,
MONITOR_PATH,
MONITOR_INTERFACE,
MON_CLI_METHOD_PING);
if (!msg) {
DEBUG(0,("Out of memory?!\n"));
talloc_zfree(svc->conn);
return ENOMEM;
}
ret = sbus_conn_send(svc->conn, msg,
svc->ping_time * 1000, /* milliseconds */
ping_check, svc, &svc->pending);
dbus_message_unref(msg);
return ret;
}
static void ping_check(DBusPendingCall *pending, void *data)
{
struct mt_svc *svc;
DBusMessage *reply;
const char *dbus_error_name;
size_t len;
int type;
svc = talloc_get_type(data, struct mt_svc);
if (!svc) {
/* The connection probably went down before the callback fired.
* Not much we can do. */
DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid service pointer.\n"));
return;
}
svc->pending = NULL;
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(svc->conn);
goto done;
}
type = dbus_message_get_type(reply);
switch (type) {
case DBUS_MESSAGE_TYPE_METHOD_RETURN:
/* ok peer replied,
* make sure we reset the failure counter in the service structure */
DEBUG(4,("Service %s replied to ping\n", svc->name));
svc->failed_pongs = 0;
break;
case DBUS_MESSAGE_TYPE_ERROR:
dbus_error_name = dbus_message_get_error_name(reply);
if (!dbus_error_name) {
dbus_error_name = "<UNKNOWN>";
}
len = strlen(DBUS_ERROR_NO_REPLY);
/* Increase failed pong count */
if (strnlen(dbus_error_name, len + 1) == len
&& strncmp(dbus_error_name, DBUS_ERROR_NO_REPLY, len) == 0) {
DEBUG(SSSDBG_CRIT_FAILURE,
("A service PING timed out on [%s]. "
"Attempt [%d]\n",
svc->name, svc->failed_pongs));
svc->failed_pongs++;
break;
}
DEBUG(SSSDBG_FATAL_FAILURE,
("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(svc->conn);
}
done:
dbus_pending_call_unref(pending);
dbus_message_unref(reply);
}
static void service_startup_handler(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval t, void *ptr);
static int start_service(struct mt_svc *svc)
{
struct tevent_timer *te;
struct timeval tv;
DEBUG(4,("Queueing service %s for startup\n", svc->name));
tv = tevent_timeval_current();
/* Add a timed event to start up the service.
* We have to do this in order to avoid a race
* condition where the service being started forks
* and attempts to connect to the SBUS before
* the monitor is serving it.
*/
te = tevent_add_timer(svc->mt_ctx->ev, svc, tv,
service_startup_handler, svc);
if (te == NULL) {
DEBUG(0, ("Unable to queue service %s for startup\n", svc->name));
return ENOMEM;
}
return EOK;
}
static void mt_svc_exit_handler(int pid, int wait_status, void *pvt);
static void service_startup_handler(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval t, void *ptr)
{
errno_t ret;
struct mt_svc *mt_svc;
char **args;
mt_svc = talloc_get_type(ptr, struct mt_svc);
if (mt_svc == NULL) {
return;
}
mt_svc->pid = fork();
if (mt_svc->pid != 0) {
if (mt_svc->pid == -1) {
DEBUG(0, ("Could not fork child to start service [%s]. "
"Continuing.\n", mt_svc->name));
return;
}
/* Parent */
mt_svc->mt_ctx->check_children = true;
mt_svc->failed_pongs = 0;
/* Handle process exit */
ret = sss_child_register(mt_svc,
mt_svc->mt_ctx->sigchld_ctx,
mt_svc->pid,
mt_svc_exit_handler,
mt_svc,
&mt_svc->child_ctx);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE,
("Could not register sigchld handler.\n"));
/* Should we exit here? For now, we'll hope this
* child never dies, because we can't restart it.
*/
}
DLIST_ADD(mt_svc->mt_ctx->svc_list, mt_svc);
set_tasks_checker(mt_svc);
return;
}
/* child */
args = parse_args(mt_svc->command);
execvp(args[0], args);
/* If we are here, exec() has failed
* Print errno and abort quickly */
DEBUG(0,("Could not exec %s, reason: %s\n", mt_svc->command, strerror(errno)));
/* We have to call _exit() instead of exit() here
* because a bug in D-BUS will cause the server to
* close its socket at exit() */
_exit(1);
}
static void mt_svc_exit_handler(int pid, int wait_status, void *pvt)
{
struct mt_svc *svc = talloc_get_type(pvt, struct mt_svc);
struct mt_ctx *mt_ctx = svc->mt_ctx;
time_t now = time(NULL);
if WIFEXITED(wait_status) {
DEBUG(SSSDBG_OP_FAILURE,
("Child [%s] exited with code [%d]\n",
svc->name, WEXITSTATUS(wait_status)));
} else if WIFSIGNALED(wait_status) {
DEBUG(SSSDBG_OP_FAILURE,
("Child [%s] terminated with signal [%d]\n",
svc->name, WTERMSIG(wait_status)));
} else {
DEBUG(0, ("Child [%s] did not exit cleanly\n", svc->name));
/* Forcibly kill this child, just in case */
kill(svc->pid, SIGKILL);
/* Return and let us get caught by another
* call to the SIGCHLD handler
*/
return;
}
if ((now - svc->last_restart) > 30) { /* TODO: get val from config */
svc->restarts = 0;
}
/* Restart the service */
if (svc->restarts > 2) { /* TODO: get val from config */
DEBUG(SSSDBG_FATAL_FAILURE,
("Process [%s], definitely stopped!\n", svc->name));
talloc_free(svc);
/* exit with error */
monitor_quit(mt_ctx, 1);
return;
}
if (svc->type == MT_SVC_SERVICE) {
add_new_service(svc->mt_ctx, svc->name, svc->restarts + 1);
} else if (svc->type == MT_SVC_PROVIDER) {
add_new_provider(svc->mt_ctx, svc->name, svc->restarts + 1);
} else {
/* Invalid type? */
DEBUG(SSSDBG_CRIT_FAILURE,
("BUG: Invalid child process type [%d]\n", svc->type));
}
/* Free the old service (which will also remove it
* from the child list)
*/
talloc_free(svc);
}
int main(int argc, const char *argv[])
{
int opt;
poptContext pc;
int opt_daemon = 0;
int opt_interactive = 0;
int opt_version = 0;
char *opt_config_file = NULL;
char *config_file = NULL;
int flags = 0;
struct main_context *main_ctx;
TALLOC_CTX *tmp_ctx;
struct mt_ctx *monitor;
int ret;
uid_t uid;
struct poptOption long_options[] = {
POPT_AUTOHELP
SSSD_MAIN_OPTS
{"daemon", 'D', POPT_ARG_NONE, &opt_daemon, 0, \
_("Become a daemon (default)"), NULL }, \
{"interactive", 'i', POPT_ARG_NONE, &opt_interactive, 0, \
_("Run interactive (not a daemon)"), NULL}, \
{"config", 'c', POPT_ARG_STRING, &opt_config_file, 0, \
_("Specify a non-default config file"), NULL}, \
{"version", '\0', POPT_ARG_NONE, &opt_version, 0, \
_("Print version number and exit"), NULL }, \
POPT_TABLEEND
};
/* Set debug level to invalid value so we can deside if -d 0 was used. */
debug_level = SSSDBG_INVALID;
pc = poptGetContext(argv[0], argc, argv, long_options, 0);
while((opt = poptGetNextOpt(pc)) != -1) {
switch(opt) {
default:
fprintf(stderr, "\nInvalid option %s: %s\n\n",
poptBadOption(pc, 0), poptStrerror(opt));
poptPrintUsage(pc, stderr, 0);
return 1;
}
}
DEBUG_INIT(debug_level);
if (opt_version) {
puts(VERSION""DISTRO_VERSION""PRERELEASE_VERSION);
return EXIT_SUCCESS;
}
/* If the level or timestamps was passed at the command-line, we want
* to save it and pass it to the children later.
*/
cmdline_debug_level = debug_level;
cmdline_debug_timestamps = debug_timestamps;
cmdline_debug_microseconds = debug_microseconds;
if (opt_daemon && opt_interactive) {
fprintf(stderr, "Option -i|--interactive is not allowed together with -D|--daemon\n");
poptPrintUsage(pc, stderr, 0);
return 1;
}
if (!opt_daemon && !opt_interactive) {
opt_daemon = 1;
}
poptFreeContext(pc);
uid = getuid();
if (uid != 0) {
DEBUG(SSSDBG_FATAL_FAILURE, ("Running under %d, must be root\n", uid));
sss_log(SSS_LOG_ALERT, "sssd must be run as root");
return 8;
}
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) {
return 7;
}
if (opt_daemon) flags |= FLAGS_DAEMON;
if (opt_interactive) flags |= FLAGS_INTERACTIVE;
if (opt_config_file) {
config_file = talloc_strdup(tmp_ctx, opt_config_file);
} else {
config_file = talloc_strdup(tmp_ctx, CONFDB_DEFAULT_CONFIG_FILE);
}
if (!config_file) {
return 6;
}
/* we want a pid file check */
flags |= FLAGS_PID_FILE;
/* Open before server_setup() does to have logging
* during configuration checking */
if (debug_to_file) {
ret = open_debug_file();
if (ret) {
return 7;
}
}
#ifdef USE_KEYRING
/* Do this before all the forks, it sets the session key ring so all
* keys are private to the daemon and cannot be read by any other process
* tree */
/* make a new session */
ret = keyctl_join_session_keyring(NULL);
if (ret == -1) {
sss_log(SSS_LOG_ALERT,
"Could not create private keyring session. "
"If you store password there they may be easily accessible "
"to the root user. (%d, %s)", errno, strerror(errno));
}
ret = keyctl_setperm(KEY_SPEC_SESSION_KEYRING, KEY_POS_ALL);
if (ret == -1) {
sss_log(SSS_LOG_ALERT,
"Could not set permissions on private keyring. "
"If you store password there they may be easily accessible "
"to the root user. (%d, %s)", errno, strerror(errno));
}
#endif
/* Warn if nscd seems to be running */
ret = check_file(NSCD_SOCKET_PATH, -1, -1, -1, CHECK_SOCK, NULL, false);
if (ret == EOK) {
sss_log(SSS_LOG_NOTICE,
"nscd socket was detected. Nscd caching capabilities "
"may conflict with SSSD for users and groups. It is "
"recommended not to run nscd in parallel with SSSD, unless "
"nscd is configured not to cache the passwd, group and "
"netgroup nsswitch maps.");
}
/* Parse config file, fail if cannot be done */
ret = load_configuration(tmp_ctx, config_file, &monitor);
if (ret != EOK) {
/* if debug level has not been set, set it manually to make these
* critical failures visible */
if (debug_level == SSSDBG_UNRESOLVED) {
debug_level = SSSDBG_MASK_ALL;
}
if (ret == EPERM) {
DEBUG(1, ("Cannot read configuration file %s\n", config_file));
sss_log(SSS_LOG_ALERT,
"Cannot read config file %s, please check if permissions "
"are 0600 and the file is owned by root.root", config_file);
} else {
DEBUG(SSSDBG_CRIT_FAILURE, ("Error loading configuration database: "
"[%d]: %s\n", ret, strerror(ret)));
sss_log(SSS_LOG_ALERT, "Cannot load configuration database");
}
return 4;
}
/* set up things like debug , signals, daemonization, etc... */
monitor->conf_path = CONFDB_MONITOR_CONF_ENTRY;
ret = server_setup(MONITOR_NAME, flags, monitor->conf_path, &main_ctx);
if (ret != EOK) return 2;
monitor->is_daemon = !opt_interactive;
monitor->parent_pid = main_ctx->parent_pid;
monitor->ev = main_ctx->event_ctx;
talloc_steal(main_ctx, monitor);
ret = monitor_process_init(monitor,
config_file);
if (ret != EOK) return 3;
talloc_free(tmp_ctx);
/* loop on main */
server_loop(main_ctx);
ret = monitor_cleanup();
if (ret != EOK) return 5;
return 0;
}