monitor.c revision 31d97bce8f113276bf73c7d4349f720cd5edbcb8
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/*
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen SSSD
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen Service monitor
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen Copyright (C) Simo Sorce 2008
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen This program is free software; you can redistribute it and/or modify
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen it under the terms of the GNU General Public License as published by
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen the Free Software Foundation; either version 3 of the License, or
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen (at your option) any later version.
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen This program is distributed in the hope that it will be useful,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen but WITHOUT ANY WARRANTY; without even the implied warranty of
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen GNU General Public License for more details.
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen You should have received a copy of the GNU General Public License
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen along with this program. If not, see <http://www.gnu.org/licenses/>.
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen*/
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen#include "util/util.h"
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen#include "util/child_common.h"
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen#include <sys/types.h>
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen#include <sys/wait.h>
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen#include <sys/time.h>
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen#include <sys/param.h>
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen#include <time.h>
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen#include <string.h>
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen#ifdef HAVE_SYS_INOTIFY_H
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <sys/inotify.h>
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen#endif
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen#include <sys/types.h>
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen#include <sys/stat.h>
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen#include <unistd.h>
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen#include <fcntl.h>
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen/* Needed for res_init() */
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen#include <netinet/in.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <arpa/nameser.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <resolv.h>
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "popt.h"
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen#include "tevent.h"
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen#include "confdb/confdb.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "confdb/confdb_setup.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "collection.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "ini_config.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "db/sysdb.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "monitor/monitor.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "dbus/dbus.h"
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen#include "sbus/sssd_dbus.h"
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen#include "monitor/monitor_interfaces.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "responder/nss/nsssrv.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef USE_KEYRING
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen#include <keyutils.h>
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen#endif
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* ping time cannot be less then once every few seconds or the
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * monitor will get crazy hammering children with messages */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define MONITOR_DEF_PING_TIME 10
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* terminate the child after this interval by default if it
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * doesn't shutdown on receiving SIGTERM */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define MONITOR_DEF_FORCE_TIME 60
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* name of the monitor server instance */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define MONITOR_NAME "sssd"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define SSSD_PIDFILE_PATH PID_PATH"/"MONITOR_NAME".pid"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Special value to leave the Kerberos Replay Cache set to use
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen * the libkrb5 defaults
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen */
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#define KRB5_RCACHE_DIR_DISABLE "__LIBKRB5_DEFAULTS__"
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainenint cmdline_debug_level;
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainenint cmdline_debug_timestamps;
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainenint cmdline_debug_microseconds;
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstruct svc_spy;
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenenum mt_svc_type {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen MT_SVC_SERVICE,
2112c190034c937b4b1613c3689d8239adb6c310Timo Sirainen MT_SVC_PROVIDER
2112c190034c937b4b1613c3689d8239adb6c310Timo Sirainen};
2112c190034c937b4b1613c3689d8239adb6c310Timo Sirainen
2112c190034c937b4b1613c3689d8239adb6c310Timo Sirainenstruct mt_svc {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen struct mt_svc *prev;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen struct mt_svc *next;
53238473bf77147660aa6db9daa68a8a685e9381Timo Sirainen enum mt_svc_type type;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen struct sbus_connection *conn;
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen struct svc_spy *conn_spy;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct mt_ctx *mt_ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen char *provider;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen char *command;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen char *name;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen char *identity;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen pid_t pid;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen int ping_time;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen int kill_time;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen bool svc_started;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen int restarts;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen time_t last_restart;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen int failed_pongs;
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen DBusPendingCall *pending;
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen int debug_level;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct tevent_timer *ping_ev;
53238473bf77147660aa6db9daa68a8a685e9381Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct sss_child_ctx *child_ctx;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen struct tevent_timer *sigkill_ev;
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen};
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstruct config_file_callback {
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen int wd;
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen int retries;
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen monitor_reconf_fn fn;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen char *filename;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen time_t modified;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct config_file_callback *next;
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen struct config_file_callback *prev;
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen};
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstruct config_file_ctx {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen TALLOC_CTX *parent_ctx;
3b94ff5951db4d4eddb7a80ed4e3f61207202635Timo Sirainen struct tevent_timer *timer;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen bool needs_update;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct mt_ctx *mt_ctx;
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen struct config_file_callback *callbacks;
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen};
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstruct mt_ctx {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct tevent_context *ev;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct confdb_ctx *cdb;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen TALLOC_CTX *domain_ctx; /* Memory context for domain list */
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct sss_domain_info *domains;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen TALLOC_CTX *service_ctx; /* Memory context for services */
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen char **services;
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen int num_services;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen int started_services;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct mt_svc *svc_list;
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen struct sbus_connection *sbus_srv;
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen struct config_file_ctx *file_ctx;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen int inotify_fd;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen int service_id_timeout;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen bool check_children;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen bool services_started;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct netlink_ctx *nlctx;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen const char *conf_path;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct sss_sigchild_ctx *sigchld_ctx;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen bool pid_file_created;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen};
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen
ace3c14e47a5a865df8aeea2fabc993b609dd163Timo Sirainenstatic int start_service(struct mt_svc *mt_svc);
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainenstatic int monitor_service_init(struct sbus_connection *conn, void *data);
ace3c14e47a5a865df8aeea2fabc993b609dd163Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic int service_send_ping(struct mt_svc *svc);
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainenstatic int service_signal_reset_offline(struct mt_svc *svc);
ace3c14e47a5a865df8aeea2fabc993b609dd163Timo Sirainenstatic void ping_check(DBusPendingCall *pending, void *data);
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic void set_tasks_checker(struct mt_svc *srv);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenstatic int monitor_kill_service (struct mt_svc *svc);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenstatic int get_service_config(struct mt_ctx *ctx, const char *name,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct mt_svc **svc_cfg);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenstatic int get_provider_config(struct mt_ctx *ctx, const char *name,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct mt_svc **svc_cfg);
3b94ff5951db4d4eddb7a80ed4e3f61207202635Timo Sirainenstatic int add_new_service(struct mt_ctx *ctx,
ace3c14e47a5a865df8aeea2fabc993b609dd163Timo Sirainen const char *name,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen int restarts);
dd8de60250511cc729b67249e61dfc6b4debff11Timo Sirainenstatic int add_new_provider(struct mt_ctx *ctx,
dd8de60250511cc729b67249e61dfc6b4debff11Timo Sirainen const char *name,
dd8de60250511cc729b67249e61dfc6b4debff11Timo Sirainen int restarts);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenstatic int mark_service_as_started(struct mt_svc *svc);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int monitor_cleanup(void);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic void network_status_change_cb(void *cb_data)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mt_svc *iter;
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen struct mt_ctx *ctx = (struct mt_ctx *) cb_data;
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen DEBUG(SSSDBG_TRACE_INTERNAL, ("A networking status change detected "
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen "signaling providers to reset offline status\n"));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (iter = ctx->svc_list; iter; iter = iter->next) {
d8b77aef97e89f1ccc5cbdaef77be9052279e35fTimo Sirainen /* Don't signal services, only providers */
46ba60afe16f39d49100ee79f45cd8b70e0e857cTimo Sirainen if (iter->provider) {
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen service_signal_reset_offline(iter);
659fe5d24825b160cae512538088020d97a60239Timo Sirainen }
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen }
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen}
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainen/* dbus_get_monitor_version
659fe5d24825b160cae512538088020d97a60239Timo Sirainen * Return the monitor version over D-BUS */
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic int get_monitor_version(DBusMessage *message,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct sbus_connection *conn)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen{
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen dbus_uint16_t version = MONITOR_VERSION;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen DBusMessage *reply;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen dbus_bool_t ret;
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen
d8b77aef97e89f1ccc5cbdaef77be9052279e35fTimo Sirainen reply = dbus_message_new_method_return(message);
d8b77aef97e89f1ccc5cbdaef77be9052279e35fTimo Sirainen if (!reply) return ENOMEM;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen ret = dbus_message_append_args(reply,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen DBUS_TYPE_UINT16, &version,
d8b77aef97e89f1ccc5cbdaef77be9052279e35fTimo Sirainen DBUS_TYPE_INVALID);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (!ret) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen dbus_message_unref(reply);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return EIO;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
46ba60afe16f39d49100ee79f45cd8b70e0e857cTimo Sirainen
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen /* send reply back */
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen sbus_conn_send_reply(conn, reply);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen dbus_message_unref(reply);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
d8b77aef97e89f1ccc5cbdaef77be9052279e35fTimo Sirainen return EOK;
d8b77aef97e89f1ccc5cbdaef77be9052279e35fTimo Sirainen}
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstruct mon_init_conn {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mt_ctx *ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct sbus_connection *conn;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct tevent_timer *timeout;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen};
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int add_svc_conn_spy(struct mt_svc *svc);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen/* registers a new client.
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen * if operation is successful also sends back the Monitor version */
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainenstatic int client_registration(DBusMessage *message,
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen struct sbus_connection *conn)
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen{
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen dbus_uint16_t version = MONITOR_VERSION;
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen struct mon_init_conn *mini;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct mt_svc *svc;
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen void *data;
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen DBusMessage *reply;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen DBusError dbus_error;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen dbus_uint16_t svc_ver;
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen char *svc_name;
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen dbus_bool_t dbret;
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen int ret;
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen data = sbus_conn_get_private_data(conn);
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen mini = talloc_get_type(data, struct mon_init_conn);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (!mini) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen DEBUG(0, ("Connection holds no valid init data\n"));
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return EINVAL;
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen }
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen /* First thing, cancel the timeout */
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen talloc_zfree(mini->timeout);
f3a258b0930595dedaa4057d4104d99d4409a10eTimo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen dbus_error_init(&dbus_error);
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen dbret = dbus_message_get_args(message, &dbus_error,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen DBUS_TYPE_STRING, &svc_name,
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen DBUS_TYPE_UINT16, &svc_ver,
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen DBUS_TYPE_INVALID);
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen if (!dbret) {
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen DEBUG(1, ("Failed to parse message, killing connection\n"));
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen sbus_disconnect(conn);
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen /* FIXME: should we just talloc_zfree(conn) ? */
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen goto done;
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen }
f3a258b0930595dedaa4057d4104d99d4409a10eTimo Sirainen
f3a258b0930595dedaa4057d4104d99d4409a10eTimo Sirainen DEBUG(4, ("Received ID registration: (%s,%d)\n", svc_name, svc_ver));
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen /* search this service in the list */
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen svc = mini->ctx->svc_list;
f79a807865222dc8d5afd21667d2ace67f6c831bTimo Sirainen while (svc) {
f79a807865222dc8d5afd21667d2ace67f6c831bTimo Sirainen ret = strcasecmp(svc->identity, svc_name);
f79a807865222dc8d5afd21667d2ace67f6c831bTimo Sirainen if (ret == 0) {
f79a807865222dc8d5afd21667d2ace67f6c831bTimo Sirainen break;
f79a807865222dc8d5afd21667d2ace67f6c831bTimo Sirainen }
f79a807865222dc8d5afd21667d2ace67f6c831bTimo Sirainen svc = svc->next;
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen }
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen if (!svc) {
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen DEBUG(0, ("Unable to find peer [%s] in list of services,"
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen " killing connection!\n", svc_name));
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen sbus_disconnect(conn);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen /* FIXME: should we just talloc_zfree(conn) ? */
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen goto done;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen /* Fill in svc structure with connection data */
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen svc->conn = mini->conn;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen ret = mark_service_as_started(svc);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (ret) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen DEBUG(1, ("Failed to mark service [%s]!\n", svc_name));
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen goto done;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen /* reply that all is ok */
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen reply = dbus_message_new_method_return(message);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (!reply) return ENOMEM;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen dbret = dbus_message_append_args(reply,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen DBUS_TYPE_UINT16, &version,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen DBUS_TYPE_INVALID);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (!dbret) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen dbus_message_unref(reply);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return EIO;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* send reply back */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen sbus_conn_send_reply(conn, reply);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen dbus_message_unref(reply);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainendone:
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* init complete, get rid of temp init context */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen talloc_zfree(mini);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return EOK;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenstruct svc_spy {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct mt_svc *svc;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen};
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenstatic int svc_destructor(void *mem)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct mt_svc *svc = talloc_get_type(mem, struct mt_svc);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (!svc) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* ?!?!? */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return 0;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* try to delist service */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (svc->mt_ctx) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen DLIST_REMOVE(svc->mt_ctx->svc_list, svc);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* Cancel any pending pings */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (svc->pending) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen dbus_pending_call_cancel(svc->pending);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* svc is beeing freed, neutralize the spy */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (svc->conn_spy) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen talloc_set_destructor((TALLOC_CTX *)svc->conn_spy, NULL);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen talloc_zfree(svc->conn_spy);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (svc->type == MT_SVC_SERVICE && svc->svc_started
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen && svc->mt_ctx != NULL && svc->mt_ctx->started_services > 0) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen svc->mt_ctx->started_services--;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return 0;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenstatic int svc_spy_destructor(void *mem)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct svc_spy *spy = talloc_get_type(mem, struct svc_spy);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (!spy) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* ?!?!? */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return 0;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* svc->conn has been freed, NULL the pointer in svc */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen spy->svc->conn_spy = NULL;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen spy->svc->conn = NULL;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return 0;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenstatic int add_svc_conn_spy(struct mt_svc *svc)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct svc_spy *spy;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen spy = talloc(svc->conn, struct svc_spy);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (!spy) return ENOMEM;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen spy->svc = svc;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen talloc_set_destructor((TALLOC_CTX *)spy, svc_spy_destructor);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen svc->conn_spy = spy;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return EOK;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenstatic int mark_service_as_started(struct mt_svc *svc)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct mt_ctx *ctx = svc->mt_ctx;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct mt_svc *iter;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen int ret;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen int i;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen DEBUG(5, ("Marking %s as started.\n", svc->name));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen svc->svc_started = true;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* we need to attach a spy to the connection structure so that if some code
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen * frees it we can zero it out in the service structure. Otherwise we may
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen * try to access or even free, freed memory. */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ret = add_svc_conn_spy(svc);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (ret) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen DEBUG(0, ("Failed to attch spy\n"));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen goto done;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (!ctx->services_started) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* check if all providers are up */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen for (iter = ctx->svc_list; iter; iter = iter->next) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (iter->provider && !iter->svc_started) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen DEBUG(5, ("Still waiting on %s provider.\n", iter->name));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen break;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (iter) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* there are still unstarted providers */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen goto done;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ctx->services_started = true;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen DEBUG(4, ("Now starting services!\n"));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* then start all services */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen for (i = 0; ctx->services[i]; i++) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen add_new_service(ctx, ctx->services[i], 0);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (svc->type == MT_SVC_SERVICE) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ctx->started_services++;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* create the pid file if all services are alive */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (!ctx->pid_file_created && ctx->started_services == ctx->num_services) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen DEBUG(SSSDBG_TRACE_FUNC, ("All services have successfully started, "
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen "creating pid file\n"));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ret = pidfile(PID_PATH, MONITOR_NAME);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (ret != EOK) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen DEBUG(SSSDBG_FATAL_FAILURE,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ("Error creating pidfile: %s/%s.pid! (%d [%s])\n",
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen PID_PATH, MONITOR_NAME, ret, strerror(ret)));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen kill(getpid(), SIGTERM);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ctx->pid_file_created = true;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainendone:
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return ret;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenstatic void services_startup_timeout(struct tevent_context *ev,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct tevent_timer *te,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct timeval t, void *ptr)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct mt_ctx *ctx = talloc_get_type(ptr, struct mt_ctx);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen int i;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen DEBUG(6, ("Handling timeout\n"));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (!ctx->services_started) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen DEBUG(1, ("Providers did not start in time, "
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen "forcing services startup!\n"));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ctx->services_started = true;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen DEBUG(4, ("Now starting services!\n"));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* then start all services */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen for (i = 0; ctx->services[i]; i++) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen add_new_service(ctx, ctx->services[i], 0);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenstatic int add_services_startup_timeout(struct mt_ctx *ctx)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct tevent_timer *to;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct timeval tv;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* 5 seconds should be plenty */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen tv = tevent_timeval_current_ofs(5, 0);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen to = tevent_add_timer(ctx->ev, ctx, tv, services_startup_timeout, ctx);
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if (!to) {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen DEBUG(0,("Out of memory?!\n"));
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return ENOMEM;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen return EOK;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenstruct sbus_method monitor_methods[] = {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen { MON_SRV_METHOD_VERSION, get_monitor_version },
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen { MON_SRV_METHOD_REGISTER, client_registration },
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen { NULL, NULL }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen};
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenstruct sbus_interface monitor_server_interface = {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen MON_SRV_INTERFACE,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen MON_SRV_PATH,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen SBUS_DEFAULT_VTABLE,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen monitor_methods,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen NULL
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen};
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen/* monitor_dbus_init
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen * Set up the monitor service as a D-BUS Server */
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenstatic int monitor_dbus_init(struct mt_ctx *ctx)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen{
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen char *monitor_address;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen int ret;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ret = monitor_get_sbus_address(ctx, &monitor_address);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (ret != EOK) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return ret;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen ret = sbus_new_server(ctx, ctx->ev,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen monitor_address, &monitor_server_interface,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen false, &ctx->sbus_srv, monitor_service_init, ctx);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen talloc_free(monitor_address);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return ret;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenstatic void tasks_check_handler(struct tevent_context *ev,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct tevent_timer *te,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct timeval t, void *ptr)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct mt_svc *svc = talloc_get_type(ptr, struct mt_svc);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen int ret;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ret = service_send_ping(svc);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen switch (ret) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen case EOK:
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* all fine */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen break;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen case ENXIO:
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen DEBUG(1,("Child (%s) not responding! (yet)\n", svc->name));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen break;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen default:
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* TODO: should we tear it down ? */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen DEBUG(1,("Sending a message to service (%s) failed!!\n", svc->name));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen break;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (svc->failed_pongs >= 3) {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen /* too long since we last heard of this process */
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen ("Killing service [%s], not responding to pings!\n",
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen svc->name));
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* Kill the service. The SIGCHLD handler will restart it */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen monitor_kill_service(svc);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* all fine, set up the task checker again */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen set_tasks_checker(svc);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenstatic void set_tasks_checker(struct mt_svc *svc)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct tevent_timer *te = NULL;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct timeval tv;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen gettimeofday(&tv, NULL);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen tv.tv_sec += svc->ping_time;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen tv.tv_usec = 0;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen te = tevent_add_timer(svc->mt_ctx->ev, svc, tv, tasks_check_handler, svc);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (te == NULL) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen DEBUG(0, ("failed to add event, monitor offline for [%s]!\n",
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen svc->name));
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen /* FIXME: shutdown ? */
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen svc->ping_ev = te;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainenstatic void mt_svc_sigkill(struct tevent_context *ev,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct tevent_timer *te,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct timeval t, void *ptr);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic int monitor_kill_service (struct mt_svc *svc)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen int ret;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct timeval tv;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen ret = kill(svc->pid, SIGTERM);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (ret != EOK) {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen DEBUG(SSSDBG_FATAL_FAILURE,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ("Sending signal to child (%s:%d) failed! "
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen "Ignore and pretend child is dead.\n",
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen svc->name, svc->pid));
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen talloc_free(svc);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen /* Set up a timer to send SIGKILL if this process
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen * doesn't exit within sixty seconds
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen */
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen tv = tevent_timeval_current_ofs(svc->kill_time, 0);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen svc->sigkill_ev = tevent_add_timer(svc->mt_ctx->ev, svc, tv,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen mt_svc_sigkill, svc);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return ret;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen}
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenstatic void mt_svc_sigkill(struct tevent_context *ev,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct tevent_timer *te,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct timeval t, void *ptr)
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen{
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen int ret;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct mt_svc *svc = talloc_get_type(ptr, struct mt_svc);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen DEBUG(SSSDBG_FATAL_FAILURE,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen ("[%s][%d] is not responding to SIGTERM. Sending SIGKILL.\n",
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen svc->name, svc->pid));
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen ret = kill(svc->pid, SIGKILL);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (ret != EOK) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen DEBUG(SSSDBG_FATAL_FAILURE,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen ("Sending signal to child (%s:%d) failed! "
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen "Ignore and pretend child is dead.\n",
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen svc->name, svc->pid));
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen talloc_free(svc);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenstatic void reload_reply(DBusPendingCall *pending, void *data)
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen{
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen DBusMessage *reply;
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen struct mt_svc *svc = talloc_get_type(data, struct mt_svc);
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen reply = dbus_pending_call_steal_reply(pending);
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if (!reply) {
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen /* reply should never be null. This function shouldn't be called
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen * until reply is valid or timeout has occurred. If reply is NULL
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen * here, something is seriously wrong and we should bail out.
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen */
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen DEBUG(0, ("A reply callback was called but no reply was received"
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen " and no timeout occurred\n"));
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen /* Destroy this connection */
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen sbus_disconnect(svc->conn);
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen dbus_pending_call_unref(pending);
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen return;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen }
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen /* TODO: Handle cases where the call has timed out or returned
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen * with an error.
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen */
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen dbus_pending_call_unref(pending);
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen dbus_message_unref(reply);
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen}
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainenstatic int service_signal_dns_reload(struct mt_svc *svc);
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainenstatic int monitor_update_resolv(struct config_file_ctx *file_ctx,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen const char *filename)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int ret;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct mt_svc *cur_svc;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen DEBUG(2, ("Resolv.conf has been updated. Reloading.\n"));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6a675eda973195f8c00c101519521b788781ba37Timo Sirainen ret = res_init();
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen if(ret != 0) {
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen return EIO;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen /* Signal all services to reload their DNS configuration */
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen for(cur_svc = file_ctx->mt_ctx->svc_list; cur_svc; cur_svc = cur_svc->next) {
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen service_signal_dns_reload(cur_svc);
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen }
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen return EOK;
690af4a90eaf8611c2573d34126bb7a852c50a44Timo Sirainen}
690af4a90eaf8611c2573d34126bb7a852c50a44Timo Sirainen
690af4a90eaf8611c2573d34126bb7a852c50a44Timo Sirainenstatic int service_signal(struct mt_svc *svc, const char *svc_signal)
e4fb5bfcdff32d337d054cce36e00e1cdfaae9f8Timo Sirainen{
e4fb5bfcdff32d337d054cce36e00e1cdfaae9f8Timo Sirainen DBusMessage *msg;
690af4a90eaf8611c2573d34126bb7a852c50a44Timo Sirainen int ret;
690af4a90eaf8611c2573d34126bb7a852c50a44Timo Sirainen
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen if (svc->provider && strcasecmp(svc->provider, "local") == 0) {
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen /* The local provider requires no signaling */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return EOK;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ea546eaab672d441e180b7619d4750be813c08d8Timo Sirainen if (!svc->conn) {
ea546eaab672d441e180b7619d4750be813c08d8Timo Sirainen /* Avoid a race condition where we are trying to
ea546eaab672d441e180b7619d4750be813c08d8Timo Sirainen * order a service to reload that hasn't started
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen * yet.
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen */
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen DEBUG(1,("Could not signal service [%s].\n", svc->name));
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return EIO;
ea546eaab672d441e180b7619d4750be813c08d8Timo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen msg = dbus_message_new_method_call(NULL,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen MONITOR_PATH,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen MONITOR_INTERFACE,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen svc_signal);
c165abbc0344ff8a4c0553dbdeb0df2259013138Timo Sirainen if (!msg) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen DEBUG(0,("Out of memory?!\n"));
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen monitor_kill_service(svc);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen talloc_free(svc);
d9e49848cb4a08f140892d76c2b54afabb9e675aTimo Sirainen return ENOMEM;
ea546eaab672d441e180b7619d4750be813c08d8Timo Sirainen }
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen ret = sbus_conn_send(svc->conn, msg,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen svc->mt_ctx->service_id_timeout,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen reload_reply, svc, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen dbus_message_unref(msg);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen return ret;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen}
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainenstatic int service_signal_dns_reload(struct mt_svc *svc)
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen{
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen return service_signal(svc, MON_CLI_METHOD_RES_INIT);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen}
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainenstatic int service_signal_offline(struct mt_svc *svc)
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen{
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen return service_signal(svc, MON_CLI_METHOD_OFFLINE);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen}
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainenstatic int service_signal_reset_offline(struct mt_svc *svc)
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen{
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen return service_signal(svc, MON_CLI_METHOD_RESET_OFFLINE);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen}
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainenstatic int service_signal_rotate(struct mt_svc *svc)
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen{
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen return service_signal(svc, MON_CLI_METHOD_ROTATE);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen}
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainenstatic int service_signal_clear_memcache(struct mt_svc *svc)
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen{
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen return service_signal(svc, MON_CLI_METHOD_CLEAR_MEMCACHE);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen}
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainenstatic int check_domain_ranges(struct sss_domain_info *domains)
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen{
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen struct sss_domain_info *dom = domains, *other = NULL;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen uint32_t id_min, id_max;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen while (dom) {
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen other = dom->next;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen if (dom->id_max && dom->id_min > dom->id_max) {
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen ("Domain '%s' does not have a valid ID range\n", dom->name));
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen return EINVAL;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen while (other) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen id_min = MAX(dom->id_min, other->id_min);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen id_max = MIN((dom->id_max ? dom->id_max : UINT32_MAX),
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen (other->id_max ? other->id_max : UINT32_MAX));
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (id_min <= id_max) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen DEBUG(SSSDBG_MINOR_FAILURE,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ("Domains '%s' and '%s' overlap in range %u - %u\n",
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen dom->name, other->name, id_min, id_max));
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen other = other->next;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen dom = dom->next;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return EOK;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenstatic int check_local_domain_unique(struct sss_domain_info *domains)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen uint8_t count = 0;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct sss_domain_info *dom = domains;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen while (dom) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (strcasecmp(dom->provider, "local") == 0) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen count++;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (count > 1) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen dom = dom->next;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (count > 1) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return EINVAL;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return EOK;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenstatic char *check_services(char **services)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen const char *known_services[] = { "nss", "pam", "sudo", "autofs", "ssh",
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen "pac", NULL };
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen int i;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen int ii;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen /* Check if services we are about to start are in the list if known */
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen for (i = 0; services[i]; i++) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen for (ii=0; known_services[ii]; ii++) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (strcasecmp(services[i], known_services[ii]) == 0) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (known_services[ii] == NULL) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return services[i];
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return NULL;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenint get_monitor_config(struct mt_ctx *ctx)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen int ret;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen int timeout_seconds;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen char *badsrv = NULL;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen int i;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ret = confdb_get_int(ctx->cdb,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen CONFDB_MONITOR_CONF_ENTRY,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen CONFDB_MONITOR_SBUS_TIMEOUT,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen 10, &timeout_seconds);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (ret != EOK) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return ret;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ctx->service_id_timeout = timeout_seconds * 1000; /* service_id_timeout is in ms */
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ctx->service_ctx = talloc_new(ctx);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if(!ctx->service_ctx) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return ENOMEM;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ret = confdb_get_string_as_list(ctx->cdb, ctx->service_ctx,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen CONFDB_MONITOR_CONF_ENTRY,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen CONFDB_MONITOR_ACTIVE_SERVICES,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen &ctx->services);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (ret != EOK) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen DEBUG(0, ("No services configured!\n"));
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return EINVAL;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen badsrv = check_services(ctx->services);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (badsrv != NULL) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen DEBUG(0, ("Invalid service %s\n", badsrv));
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return EINVAL;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ctx->started_services = 0;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ctx->num_services = 0;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen for (i = 0; ctx->services[i] != NULL; i++) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ctx->num_services++;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ctx->domain_ctx = talloc_new(ctx);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if(!ctx->domain_ctx) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return ENOMEM;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ret = confdb_get_domains(ctx->cdb, &ctx->domains);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (ret != EOK) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen DEBUG(0, ("No domains configured.\n"));
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return ret;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ret = check_local_domain_unique(ctx->domains);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (ret != EOK) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen DEBUG(0, ("More than one local domain configured.\n"));
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return ret;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen /* Check UID/GID overlaps */
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ret = check_domain_ranges(ctx->domains);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (ret != EOK) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return ret;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return EOK;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenstatic errno_t get_ping_config(struct mt_ctx *ctx, const char *path,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct mt_svc *svc)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen errno_t ret;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ret = confdb_get_int(ctx->cdb, path,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen CONFDB_DOMAIN_TIMEOUT,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen MONITOR_DEF_PING_TIME, &svc->ping_time);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (ret != EOK) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ("Failed to get ping timeout for '%s'\n", svc->name));
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return ret;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen /* 'timeout = 0' should be translated to the default */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (svc->ping_time == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen svc->ping_time = MONITOR_DEF_PING_TIME;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
215daa7d5bf9a849849586490fd6fdd28a724dd8Timo Sirainen
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen ret = confdb_get_int(ctx->cdb, path,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen CONFDB_SERVICE_FORCE_TIMEOUT,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen MONITOR_DEF_FORCE_TIME, &svc->kill_time);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (ret != EOK) {
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen ("Failed to get kill timeout for %s\n", svc->name));
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return ret;
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen }
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen /* 'force_timeout = 0' should be translated to the default */
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen if (svc->kill_time == 0) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen svc->kill_time = MONITOR_DEF_FORCE_TIME;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen return EOK;
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen}
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen
ea546eaab672d441e180b7619d4750be813c08d8Timo Sirainenstatic int get_service_config(struct mt_ctx *ctx, const char *name,
5c1a8aee989af87bddefd71e2aa83aa2bd695155Timo Sirainen struct mt_svc **svc_cfg)
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen{
5c1a8aee989af87bddefd71e2aa83aa2bd695155Timo Sirainen int ret;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen char *path;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct mt_svc *svc;
215daa7d5bf9a849849586490fd6fdd28a724dd8Timo Sirainen time_t now = time(NULL);
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen *svc_cfg = NULL;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen svc = talloc_zero(ctx, struct mt_svc);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (!svc) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return ENOMEM;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen svc->mt_ctx = ctx;
f172291ed740e6af3ce3e7c9c2ef0fe1d3ad7963Timo Sirainen svc->type = MT_SVC_SERVICE;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen talloc_set_destructor((TALLOC_CTX *)svc, svc_destructor);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen svc->name = talloc_strdup(svc, name);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (!svc->name) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen talloc_free(svc);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return ENOMEM;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen svc->identity = talloc_strdup(svc, name);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (!svc->identity) {
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen talloc_free(svc);
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen return ENOMEM;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen path = talloc_asprintf(svc, CONFDB_SERVICE_PATH_TMPL, svc->name);
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen if (!path) {
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen talloc_free(svc);
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen return ENOMEM;
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen }
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen ret = confdb_get_string(ctx->cdb, svc, path,
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen CONFDB_SERVICE_COMMAND,
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen NULL, &svc->command);
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen if (ret != EOK) {
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen DEBUG(0,("Failed to start service '%s'\n", svc->name));
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen talloc_free(svc);
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen return ret;
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen }
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen if (!svc->command) {
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen svc->command = talloc_asprintf(
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen svc, "%s/sssd_%s", SSSD_LIBEXEC_PATH, svc->name
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen );
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (!svc->command) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen talloc_free(svc);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen return ENOMEM;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen }
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen if (cmdline_debug_level != SSSDBG_UNRESOLVED) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen svc->command = talloc_asprintf_append(
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen svc->command, " -d %#.4x", cmdline_debug_level
c165abbc0344ff8a4c0553dbdeb0df2259013138Timo Sirainen );
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen if (!svc->command) {
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen talloc_free(svc);
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen return ENOMEM;
90a6478adca64af3b909498711bb034a5ddb79a9Timo Sirainen }
90a6478adca64af3b909498711bb034a5ddb79a9Timo Sirainen }
90a6478adca64af3b909498711bb034a5ddb79a9Timo Sirainen
90a6478adca64af3b909498711bb034a5ddb79a9Timo Sirainen if (cmdline_debug_timestamps != SSSDBG_TIMESTAMP_UNRESOLVED) {
90a6478adca64af3b909498711bb034a5ddb79a9Timo Sirainen svc->command = talloc_asprintf_append(
90a6478adca64af3b909498711bb034a5ddb79a9Timo Sirainen svc->command, " --debug-timestamps=%d", cmdline_debug_timestamps
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen );
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!svc->command) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen talloc_free(svc);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return ENOMEM;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (cmdline_debug_microseconds != SSSDBG_MICROSECONDS_UNRESOLVED) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen svc->command = talloc_asprintf_append(
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen svc->command, " --debug-microseconds=%d",
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen cmdline_debug_microseconds
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen );
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen if (!svc->command) {
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen talloc_free(svc);
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen return ENOMEM;
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (debug_to_file) {
ea546eaab672d441e180b7619d4750be813c08d8Timo Sirainen svc->command = talloc_strdup_append(
ea546eaab672d441e180b7619d4750be813c08d8Timo Sirainen svc->command, " --debug-to-files"
ea546eaab672d441e180b7619d4750be813c08d8Timo Sirainen );
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (!svc->command) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen talloc_free(svc);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return ENOMEM;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen }
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen ret = get_ping_config(ctx, path, svc);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret != EOK) {
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen ("Failed to get ping timeouts for %s\n", svc->name));
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen talloc_free(svc);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return ret;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen svc->last_restart = now;
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen *svc_cfg = svc;
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen talloc_free(path);
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return EOK;
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen}
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainenstatic int add_new_service(struct mt_ctx *ctx,
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen const char *name,
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen int restarts)
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen{
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen int ret;
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen struct mt_svc *svc;
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen ret = get_service_config(ctx, name, &svc);
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen if (ret != EOK) {
5c1a8aee989af87bddefd71e2aa83aa2bd695155Timo Sirainen return ret;
5c1a8aee989af87bddefd71e2aa83aa2bd695155Timo Sirainen }
5c1a8aee989af87bddefd71e2aa83aa2bd695155Timo Sirainen svc->restarts = restarts;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
f172291ed740e6af3ce3e7c9c2ef0fe1d3ad7963Timo Sirainen ret = start_service(svc);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret != EOK) {
f172291ed740e6af3ce3e7c9c2ef0fe1d3ad7963Timo Sirainen DEBUG(0,("Failed to start service '%s'\n", svc->name));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen talloc_free(svc);
ea546eaab672d441e180b7619d4750be813c08d8Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ret;
}
static int get_provider_config(struct mt_ctx *ctx, const char *name,
struct mt_svc **svc_cfg)
{
int ret;
char *path;
struct mt_svc *svc;
time_t now = time(NULL);
*svc_cfg = NULL;
svc = talloc_zero(ctx, struct mt_svc);
if (!svc) {
return ENOMEM;
}
svc->mt_ctx = ctx;
svc->type = MT_SVC_PROVIDER;
talloc_set_destructor((TALLOC_CTX *)svc, svc_destructor);
svc->name = talloc_strdup(svc, name);
if (!svc->name) {
talloc_free(svc);
return ENOMEM;
}
svc->identity = talloc_asprintf(svc, "%%BE_%s", svc->name);
if (!svc->identity) {
talloc_free(svc);
return ENOMEM;
}
path = talloc_asprintf(svc, CONFDB_DOMAIN_PATH_TMPL, name);
if (!path) {
talloc_free(svc);
return ENOMEM;
}
ret = confdb_get_string(ctx->cdb, svc, path,
CONFDB_DOMAIN_ID_PROVIDER,
NULL, &svc->provider);
if (ret != EOK) {
DEBUG(0, ("Failed to find ID provider from [%s] configuration\n", name));
talloc_free(svc);
return ret;
}
ret = confdb_get_string(ctx->cdb, svc, path,
CONFDB_DOMAIN_COMMAND,
NULL, &svc->command);
if (ret != EOK) {
DEBUG(0, ("Failed to find command from [%s] configuration\n", name));
talloc_free(svc);
return ret;
}
ret = get_ping_config(ctx, path, svc);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
("Failed to get ping timeouts for %s\n", svc->name));
talloc_free(svc);
return ret;
}
talloc_free(path);
/* if no provider is present do not run the domain */
if (!svc->provider) {
talloc_free(svc);
return EIO;
}
/* if there are no custom commands, build a default one */
if (!svc->command) {
svc->command = talloc_asprintf(
svc, "%s/sssd_be --domain %s", SSSD_LIBEXEC_PATH, svc->name
);
if (!svc->command) {
talloc_free(svc);
return ENOMEM;
}
if (cmdline_debug_level != SSSDBG_UNRESOLVED) {
svc->command = talloc_asprintf_append(
svc->command, " -d %#.4x", cmdline_debug_level
);
if (!svc->command) {
talloc_free(svc);
return ENOMEM;
}
}
if (cmdline_debug_timestamps != SSSDBG_TIMESTAMP_UNRESOLVED) {
svc->command = talloc_asprintf_append(
svc->command, " --debug-timestamps=%d", cmdline_debug_timestamps
);
if (!svc->command) {
talloc_free(svc);
return ENOMEM;
}
}
if (cmdline_debug_microseconds != SSSDBG_MICROSECONDS_UNRESOLVED) {
svc->command = talloc_asprintf_append(
svc->command, " --debug-microseconds=%d",
cmdline_debug_microseconds
);
if (!svc->command) {
talloc_free(svc);
return ENOMEM;
}
}
if (debug_to_file) {
svc->command = talloc_strdup_append(
svc->command, " --debug-to-files"
);
if (!svc->command) {
talloc_free(svc);
return ENOMEM;
}
}
}
svc->last_restart = now;
*svc_cfg = svc;
return EOK;
}
static int add_new_provider(struct mt_ctx *ctx,
const char *name,
int restarts)
{
int ret;
struct mt_svc *svc;
ret = get_provider_config(ctx, name, &svc);
if (ret != EOK) {
DEBUG(0, ("Could not get provider configuration for [%s]\n",
name));
return ret;
}
svc->restarts = restarts;
if (strcasecmp(svc->provider, "local") == 0) {
/* The LOCAL provider requires no back-end currently
* We'll add it to the service list, but we don't need
* to poll it.
*/
svc->svc_started = true;
DLIST_ADD(ctx->svc_list, svc);
return ENOENT;
}
ret = start_service(svc);
if (ret != EOK) {
DEBUG(0,("Failed to start service '%s'\n", svc->name));
talloc_free(svc);
}
return ret;
}
static void monitor_hup(struct tevent_context *ev,
struct tevent_signal *se,
int signum,
int count,
void *siginfo,
void *private_data)
{
struct mt_ctx *ctx = talloc_get_type(private_data, struct mt_ctx);
struct mt_svc *cur_svc;
DEBUG(1, ("Received SIGHUP.\n"));
/* Send D-Bus message to other services to rotate their logs.
* NSS service receives also message to clear memory caches. */
for(cur_svc = ctx->svc_list; cur_svc; cur_svc = cur_svc->next) {
service_signal_rotate(cur_svc);
if (!strcmp(NSS_SBUS_SERVICE_NAME, cur_svc->name)) {
service_signal_clear_memcache(cur_svc);
}
}
}
static int monitor_cleanup(void)
{
int ret;
errno = 0;
ret = unlink(SSSD_PIDFILE_PATH);
if (ret == -1) {
ret = errno;
DEBUG(SSSDBG_FATAL_FAILURE,
("Error removing pidfile! (%d [%s])\n", ret, strerror(ret)));
return ret;
}
return EOK;
}
static void monitor_quit(struct tevent_context *ev,
struct tevent_signal *se,
int signum,
int count,
void *siginfo,
void *private_data)
{
struct mt_ctx *mt_ctx = talloc_get_type(private_data, struct mt_ctx);
struct mt_svc *svc;
pid_t pid;
int status;
errno_t error;
int kret;
bool killed;
DEBUG(8, ("Received shutdown command\n"));
DEBUG(0, ("Monitor received %s: terminating children\n",
strsignal(signum)));
/* Kill all of our known children manually */
DLIST_FOR_EACH(svc, mt_ctx->svc_list) {
if (svc->pid == 0) {
/* The local provider has no PID */
continue;
}
killed = false;
DEBUG(1, ("Terminating [%s][%d]\n", svc->name, svc->pid));
do {
errno = 0;
kret = kill(svc->pid, SIGTERM);
if (kret < 0) {
error = errno;
DEBUG(1, ("Couldn't kill [%s][%d]: [%s]\n",
svc->name, svc->pid, strerror(error)));
}
error = 0;
do {
errno = 0;
pid = waitpid(svc->pid, &status, WNOHANG);
if (pid == -1) {
/* An error occurred while waiting */
error = errno;
if (error != EINTR) {
DEBUG(0, ("[%d][%s] while waiting for [%s]\n",
error, strerror(error), svc->name));
/* Forcibly kill this child */
kill(svc->pid, SIGKILL);
break;
}
} else if (pid != 0) {
error = 0;
if WIFEXITED(status) {
DEBUG(1, ("Child [%s] exited gracefully\n", svc->name));
} else if WIFSIGNALED(status) {
DEBUG(1, ("Child [%s] terminated with a signal\n", svc->name));
} else {
DEBUG(0, ("Child [%s] did not exit cleanly\n", svc->name));
/* Forcibly kill this child */
kill(svc->pid, SIGKILL);
}
killed = true;
}
} while (error == EINTR);
if (!killed) {
/* Sleep 10ms and try again */
usleep(10000);
}
} while (!killed);
}
#if HAVE_GETPGRP
/* Kill any remaining children in our process group, just in case
* we have any leftover children we don't expect. For example, if
* a krb5_child or ldap_child is running at the same moment.
*/
error = 0;
if (getpgrp() == getpid()) {
kill(-getpgrp(), SIGTERM);
do {
errno = 0;
pid = waitpid(0, &status, 0);
if (pid == -1) {
error = errno;
}
} while (error == EINTR || pid > 0);
}
#endif
monitor_cleanup();
exit(0);
}
static void signal_res_init(struct mt_ctx *monitor)
{
struct mt_svc *cur_svc;
int ret;
DEBUG(SSSDBG_OP_FAILURE, ("Reloading Resolv.conf.\n"));
ret = res_init();
if (ret == 0) {
for(cur_svc = monitor->svc_list; cur_svc; cur_svc = cur_svc->next) {
service_signal_dns_reload(cur_svc);
}
}
}
static void signal_offline(struct tevent_context *ev,
struct tevent_signal *se,
int signum,
int count,
void *siginfo,
void *private_data)
{
struct mt_ctx *monitor;
struct mt_svc *cur_svc;
monitor = talloc_get_type(private_data, struct mt_ctx);
DEBUG(SSSDBG_TRACE_INTERNAL,
("Signaling providers to go offline immediately.\n"));
/* Signal all providers to immediately go offline */
for(cur_svc = monitor->svc_list; cur_svc; cur_svc = cur_svc->next) {
/* Don't signal services, only providers */
if (cur_svc->provider) {
service_signal_offline(cur_svc);
}
}
}
static void signal_offline_reset(struct tevent_context *ev,
struct tevent_signal *se,
int signum,
int count,
void *siginfo,
void *private_data)
{
struct mt_ctx *monitor;
struct mt_svc *cur_svc;
monitor = talloc_get_type(private_data, struct mt_ctx);
DEBUG(SSSDBG_TRACE_INTERNAL,
("Signaling providers to reset offline immediately.\n"));
for(cur_svc = monitor->svc_list; cur_svc; cur_svc = cur_svc->next) {
if (cur_svc->provider) {
service_signal_reset_offline(cur_svc);
}
}
signal_res_init(monitor);
}
static int monitor_ctx_destructor(void *mem)
{
struct mt_ctx *mon = talloc_get_type(mem, struct mt_ctx);
struct mt_svc *svc;
/* zero out references in svcs so that they don't try
* to access the monitor context on process shutdown */
for (svc = mon->svc_list; svc; svc = svc->next) {
svc->mt_ctx = NULL;
}
return 0;
}
static errno_t load_configuration(TALLOC_CTX *mem_ctx,
const char *config_file,
struct mt_ctx **monitor)
{
errno_t ret;
struct mt_ctx *ctx;
char *cdb_file = NULL;
ctx = talloc_zero(mem_ctx, struct mt_ctx);
if(!ctx) {
return ENOMEM;
}
ctx->pid_file_created = false;
talloc_set_destructor((TALLOC_CTX *)ctx, monitor_ctx_destructor);
cdb_file = talloc_asprintf(ctx, "%s/%s", DB_PATH, CONFDB_FILE);
if (cdb_file == NULL) {
DEBUG(0,("Out of memory, aborting!\n"));
ret = ENOMEM;
goto done;
}
ret = confdb_init(ctx, &ctx->cdb, cdb_file);
if (ret != EOK) {
DEBUG(0,("The confdb initialization failed\n"));
goto done;
}
/* Initialize the CDB from the configuration file */
ret = confdb_test(ctx->cdb);
if (ret == ENOENT) {
/* First-time setup */
/* Purge any existing confdb in case an old
* misconfiguration gets in the way
*/
talloc_zfree(ctx->cdb);
unlink(cdb_file);
ret = confdb_init(ctx, &ctx->cdb, cdb_file);
if (ret != EOK) {
DEBUG(0,("The confdb initialization failed\n"));
goto done;
}
/* Load special entries */
ret = confdb_create_base(ctx->cdb);
if (ret != EOK) {
DEBUG(0, ("Unable to load special entries into confdb\n"));
goto done;
}
} else if (ret != EOK) {
DEBUG(0, ("Fatal error initializing confdb\n"));
goto done;
}
talloc_zfree(cdb_file);
ret = confdb_init_db(config_file, ctx->cdb);
if (ret != EOK) {
DEBUG(0, ("ConfDB initialization has failed [%s]\n",
strerror(ret)));
goto done;
}
/* Validate the configuration in the database */
/* Read in the monitor's configuration */
ret = get_monitor_config(ctx);
if (ret != EOK) {
goto done;
}
*monitor = ctx;
ret = EOK;
done:
if (ret != EOK) {
talloc_free(ctx);
}
return ret;
}
#ifdef HAVE_SYS_INOTIFY_H
static void process_config_file(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval t, void *ptr);
static void config_file_changed(struct tevent_context *ev,
struct tevent_fd *fde,
uint16_t flags, void *data)
{
struct tevent_timer *te = NULL;
struct timeval tv;
struct config_file_ctx *file_ctx;
file_ctx = talloc_get_type(data, struct config_file_ctx);
if (file_ctx->needs_update) {
/* Skip updating. It's already queued for update.
*/
return;
}
/* We will queue the file for update in one second.
* This way, if there is a script writing to the file
* repeatedly, we won't be attempting to update multiple
* times.
*/
gettimeofday(&tv, NULL);
tv.tv_sec += 1;
te = tevent_add_timer(ev, ev, tv, process_config_file, file_ctx);
if (!te) {
DEBUG(0, ("Unable to queue config file update! Exiting.\n"));
kill(getpid(), SIGTERM);
return;
}
file_ctx->needs_update = 1;
}
struct rewatch_ctx {
struct config_file_callback *cb;
struct config_file_ctx *file_ctx;
};
static void rewatch_config_file(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval t, void *ptr);
static void process_config_file(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval t, void *ptr)
{
TALLOC_CTX *tmp_ctx;
struct inotify_event *in_event;
char *buf;
char *name;
ssize_t len;
ssize_t event_size;
struct config_file_ctx *file_ctx;
struct config_file_callback *cb;
struct rewatch_ctx *rw_ctx;
errno_t ret;
event_size = sizeof(struct inotify_event);
file_ctx = talloc_get_type(ptr, struct config_file_ctx);
DEBUG(1, ("Processing config file changes\n"));
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) return;
buf = talloc_size(tmp_ctx, event_size);
if (!buf) {
goto done;
}
errno = 0;
len = sss_atomic_read_s(file_ctx->mt_ctx->inotify_fd, buf, event_size);
if (len == -1) {
ret = errno;
DEBUG(SSSDBG_CRIT_FAILURE,
("Critical error reading inotify file descriptor [%d]: %s\n",
ret, strerror(ret)));
goto done;
}
in_event = (struct inotify_event *)buf;
if (in_event->len > 0) {
/* Read in the name, even though we don't use it,
* so that read ptr is in the right place
*/
name = talloc_size(tmp_ctx, in_event->len);
if (!name) {
goto done;
}
errno = 0;
len = sss_atomic_read_s(file_ctx->mt_ctx->inotify_fd, name, in_event->len);
if (len == -1) {
ret = errno;
DEBUG(SSSDBG_CRIT_FAILURE,
("Critical error reading inotify file descriptor [%d]: %s\n",
ret, strerror(ret)));
goto done;
}
}
for (cb = file_ctx->callbacks; cb; cb = cb->next) {
if (cb->wd == in_event->wd) {
break;
}
}
if (!cb) {
DEBUG(0, ("Unknown watch descriptor\n"));
goto done;
}
if (in_event->mask & IN_IGNORED) {
/* Some text editors will move a new file on top of the
* existing one instead of modifying it. In this case,
* the kernel will send us an IN_IGNORE signal.
* We will try to open a new watch descriptor on the
* new file.
*/
struct timeval tv;
struct tevent_timer *tev;
tv.tv_sec = t.tv_sec+5;
tv.tv_usec = t.tv_usec;
DEBUG(5, ("Restoring inotify watch.\n"));
cb->retries = 0;
rw_ctx = talloc(file_ctx, struct rewatch_ctx);
if(!rw_ctx) {
DEBUG(0, ("Could not restore inotify watch. Quitting!\n"));
close(file_ctx->mt_ctx->inotify_fd);
kill(getpid(), SIGTERM);
goto done;
}
rw_ctx->cb = cb;
rw_ctx->file_ctx = file_ctx;
tev = tevent_add_timer(ev, rw_ctx, tv, rewatch_config_file, rw_ctx);
if (tev == NULL) {
DEBUG(0, ("Could not restore inotify watch. Quitting!\n"));
close(file_ctx->mt_ctx->inotify_fd);
kill(getpid(), SIGTERM);
}
goto done;
}
/* Tell the monitor to signal the children */
cb->fn(file_ctx, cb->filename);
file_ctx->needs_update = 0;
done:
talloc_free(tmp_ctx);
}
errno_t monitor_config_file_fallback(TALLOC_CTX *mem_ctx,
struct mt_ctx *ctx,
const char *file,
monitor_reconf_fn fn,
bool ignore_missing);
static void rewatch_config_file(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval t, void *ptr)
{
int err;
struct tevent_timer *tev = NULL;
struct timeval tv;
struct config_file_callback *cb;
struct rewatch_ctx *rw_ctx;
struct config_file_ctx *file_ctx;
rw_ctx = talloc_get_type(ptr, struct rewatch_ctx);
cb = rw_ctx->cb;
file_ctx = rw_ctx->file_ctx;
/* Retry six times at five-second intervals before giving up */
cb->retries++;
if (cb->retries > 6) {
DEBUG(SSSDBG_FATAL_FAILURE,
("Could not restore inotify watch. Switching to polling!\n"));
close(file_ctx->mt_ctx->inotify_fd);
err = monitor_config_file_fallback(file_ctx->parent_ctx,
file_ctx->mt_ctx,
cb->filename,
cb->fn,true);
if (err != EOK)
kill(getpid(), SIGTERM);
cb->fn(file_ctx, cb->filename);
talloc_free(rw_ctx);
/* A new callback was created in monitor_config_file_fallback()*/
DLIST_REMOVE(file_ctx->callbacks, cb);
talloc_free(cb);
return;
}
cb->wd = inotify_add_watch(file_ctx->mt_ctx->inotify_fd,
cb->filename, IN_MODIFY);
if (cb->wd < 0) {
err = errno;
tv.tv_sec = t.tv_sec+5;
tv.tv_usec = t.tv_usec;
DEBUG(SSSDBG_CRIT_FAILURE,
("Could not add inotify watch for file [%s]. Error [%d:%s]\n",
cb->filename, err, strerror(err)));
tev = tevent_add_timer(ev, ev, tv, rewatch_config_file, rw_ctx);
if (tev == NULL) {
DEBUG(SSSDBG_FATAL_FAILURE,
("Could not restore inotify watch. Quitting!\n"));
close(file_ctx->mt_ctx->inotify_fd);
kill(getpid(), SIGTERM);
}
return;
}
cb->retries = 0;
/* Tell the monitor to signal the children */
cb->fn(file_ctx, cb->filename);
talloc_free(rw_ctx);
file_ctx->needs_update = 0;
}
#endif
static void poll_config_file(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval t, void *ptr)
{
int ret, err;
struct stat file_stat;
struct timeval tv;
struct config_file_ctx *file_ctx;
struct config_file_callback *cb;
file_ctx = talloc_get_type(ptr,struct config_file_ctx);
for (cb = file_ctx->callbacks; cb; cb = cb->next) {
ret = stat(cb->filename, &file_stat);
if (ret < 0) {
err = errno;
DEBUG(0, ("Could not stat file [%s]. Error [%d:%s]\n",
cb->filename, err, strerror(err)));
/* TODO: If the config file is missing, should we shut down? */
return;
}
if (file_stat.st_mtime != cb->modified) {
/* Parse the configuration file and signal the children */
/* Note: this will fire if the modification time changes into the past
* as well as the future.
*/
DEBUG(1, ("Config file changed\n"));
cb->modified = file_stat.st_mtime;
/* Tell the monitor to signal the children */
cb->fn(file_ctx, cb->filename);
}
}
gettimeofday(&tv, NULL);
tv.tv_sec += CONFIG_FILE_POLL_INTERVAL;
tv.tv_usec = 0;
file_ctx->timer = tevent_add_timer(ev, file_ctx->parent_ctx, tv,
poll_config_file, file_ctx);
if (!file_ctx->timer) {
DEBUG(0, ("Error: Config file no longer monitored for changes!\n"));
}
}
static int try_inotify(struct config_file_ctx *file_ctx, const char *filename,
monitor_reconf_fn fn)
{
#ifdef HAVE_SYS_INOTIFY_H
int err, fd_args, ret;
struct tevent_fd *tfd;
struct config_file_callback *cb;
/* Monitoring the file descriptor should be global */
if (!file_ctx->mt_ctx->inotify_fd) {
/* Set up inotify to monitor the config file for changes */
file_ctx->mt_ctx->inotify_fd = inotify_init();
if (file_ctx->mt_ctx->inotify_fd < 0) {
err = errno;
DEBUG(0, ("Could not initialize inotify, error [%d:%s]\n",
err, strerror(err)));
return err;
}
fd_args = fcntl(file_ctx->mt_ctx->inotify_fd, F_GETFL, NULL);
if (fd_args < 0) {
/* Could not set nonblocking */
close(file_ctx->mt_ctx->inotify_fd);
return EINVAL;
}
fd_args |= O_NONBLOCK;
ret = fcntl(file_ctx->mt_ctx->inotify_fd, F_SETFL, fd_args);
if (ret < 0) {
/* Could not set nonblocking */
close(file_ctx->mt_ctx->inotify_fd);
return EINVAL;
}
/* Add the inotify file descriptor to the TEvent context */
tfd = tevent_add_fd(file_ctx->mt_ctx->ev, file_ctx,
file_ctx->mt_ctx->inotify_fd,
TEVENT_FD_READ, config_file_changed,
file_ctx);
if (!tfd) {
close(file_ctx->mt_ctx->inotify_fd);
return EIO;
}
}
cb = talloc_zero(file_ctx, struct config_file_callback);
if(!cb) {
close(file_ctx->mt_ctx->inotify_fd);
return EIO;
}
cb->filename = talloc_strdup(cb, filename);
if (!cb->filename) {
close(file_ctx->mt_ctx->inotify_fd);
return ENOMEM;
}
cb->wd = inotify_add_watch(file_ctx->mt_ctx->inotify_fd,
cb->filename, IN_MODIFY);
if (cb->wd < 0) {
err = errno;
DEBUG(0, ("Could not add inotify watch for file [%s]. Error [%d:%s]\n",
cb->filename, err, strerror(err)));
close(file_ctx->mt_ctx->inotify_fd);
return err;
}
cb->fn = fn;
DLIST_ADD(file_ctx->callbacks, cb);
return EOK;
#else
return EINVAL;
#endif
}
static int monitor_config_file(TALLOC_CTX *mem_ctx,
struct mt_ctx *ctx,
const char *file,
monitor_reconf_fn fn,
bool ignore_missing)
{
int ret, err;
bool use_inotify;
struct stat file_stat;
ret = stat(file, &file_stat);
if (ret < 0) {
err = errno;
if (err == ENOENT && ignore_missing) {
DEBUG(SSSDBG_MINOR_FAILURE,
("file [%s] is missing. Will not update online status "
"based on watching the file\n", file));
return EOK;
} else {
DEBUG(SSSDBG_FATAL_FAILURE,
("Could not stat file [%s]. Error [%d:%s]\n",
file, err, strerror(err)));
return err;
}
}
if (!ctx->file_ctx) {
ctx->file_ctx = talloc_zero(mem_ctx, struct config_file_ctx);
if (!ctx->file_ctx) return ENOMEM;
ctx->file_ctx->parent_ctx = mem_ctx;
ctx->file_ctx->mt_ctx = ctx;
}
ret = confdb_get_bool(ctx->cdb,
CONFDB_MONITOR_CONF_ENTRY,
CONFDB_MONITOR_TRY_INOTIFY,
true, &use_inotify);
if (ret != EOK) {
talloc_free(ctx->file_ctx);
return ret;
}
if (use_inotify) {
ret = try_inotify(ctx->file_ctx, file, fn);
if (ret != EOK) {
use_inotify = false;
}
}
if (!use_inotify) {
/* Could not monitor file with inotify, fall back to polling */
ret = monitor_config_file_fallback(mem_ctx, ctx, file, fn, true);
}
return ret;
}
errno_t monitor_config_file_fallback(TALLOC_CTX *mem_ctx,
struct mt_ctx *ctx,
const char *file,
monitor_reconf_fn fn,
bool ignore_missing)
{
struct config_file_callback *cb = NULL;
struct stat file_stat;
int ret, err;
struct timeval tv;
ret = stat(file, &file_stat);
if (ret < 0) {
err = errno;
if (err == ENOENT && ignore_missing) {
DEBUG(SSSDBG_MINOR_FAILURE,
("file [%s] is missing. Will not update online status "
"based on watching the file\n", file));
return EOK;
} else {
DEBUG(SSSDBG_FATAL_FAILURE,
("Could not stat file [%s]. Error [%d:%s]\n",
file, err, strerror(err)));
return err;
}
}
cb = talloc_zero(ctx->file_ctx, struct config_file_callback);
if (!cb) {
talloc_free(ctx->file_ctx);
return ENOMEM;
}
cb->filename = talloc_strdup(cb, file);
if (!cb->filename) {
talloc_free(ctx->file_ctx);
return ENOMEM;
}
cb->fn = fn;
cb->modified = file_stat.st_mtime;
DLIST_ADD(ctx->file_ctx->callbacks, cb);
if(!ctx->file_ctx->timer) {
gettimeofday(&tv, NULL);
tv.tv_sec += CONFIG_FILE_POLL_INTERVAL;
tv.tv_usec = 0;
ctx->file_ctx->timer = tevent_add_timer(ctx->ev, mem_ctx, tv,
poll_config_file, ctx->file_ctx);
if (!ctx->file_ctx->timer) {
talloc_free(ctx->file_ctx);
return EIO;
}
}
return EOK;
}
int monitor_process_init(struct mt_ctx *ctx,
const char *config_file)
{
TALLOC_CTX *tmp_ctx;
struct sysdb_ctx_list *db_list;
struct tevent_signal *tes;
struct sss_domain_info *dom;
char *rcachedir;
int num_providers;
int ret;
int error;
/* Set up the environment variable for the Kerberos Replay Cache */
ret = confdb_get_string(ctx->cdb, ctx,
CONFDB_MONITOR_CONF_ENTRY,
CONFDB_MONITOR_KRB5_RCACHEDIR,
KRB5_RCACHE_DIR,
&rcachedir);
if (ret != EOK) {
return ret;
}
if (strcmp(rcachedir, KRB5_RCACHE_DIR_DISABLE) != 0)
{
errno = 0;
ret = setenv("KRB5RCACHEDIR", rcachedir, 1);
if (ret < 0) {
error = errno;
DEBUG(1,
("Unable to set KRB5RCACHEDIR: %s."
"Will attempt to use libkrb5 defaults\n",
strerror(error)));
}
talloc_zfree(rcachedir);
}
/* Set up an event handler for a SIGHUP */
tes = tevent_add_signal(ctx->ev, ctx, SIGHUP, 0,
monitor_hup, ctx);
if (tes == NULL) {
return EIO;
}
/* Set up an event handler for a SIGINT */
BlockSignals(false, SIGINT);
tes = tevent_add_signal(ctx->ev, ctx, SIGINT, 0,
monitor_quit, ctx);
if (tes == NULL) {
return EIO;
}
/* Set up an event handler for a SIGTERM */
tes = tevent_add_signal(ctx->ev, ctx, SIGTERM, 0,
monitor_quit, ctx);
if (tes == NULL) {
return EIO;
}
/* Handle SIGUSR1 (tell all providers to go offline) */
BlockSignals(false, SIGUSR1);
tes = tevent_add_signal(ctx->ev, ctx, SIGUSR1, 0,
signal_offline, ctx);
if (tes == NULL) {
return EIO;
}
/* Handle SIGUSR2 (tell all providers to go reset offline) */
BlockSignals(false, SIGUSR2);
tes = tevent_add_signal(ctx->ev, ctx, SIGUSR2, 0,
signal_offline_reset, ctx);
if (tes == NULL) {
return EIO;
}
/* Set up the SIGCHLD handler */
ret = sss_sigchld_init(ctx, ctx->ev, &ctx->sigchld_ctx);
if (ret != EOK) return ret;
#if 0
This feature is incomplete and can leave the SSSD in a bad state if the
config file is changed while the SSSD is running.
Uncomment this once the backends are honoring reloadConfig()
/* Watch for changes to the confdb config file */
ret = monitor_config_file(ctx, ctx, config_file, monitor_signal_reconf,
true);
if (ret != EOK) {
return ret;
}
#endif
/* Watch for changes to the DNS resolv.conf */
ret = monitor_config_file(ctx, ctx, RESOLV_CONF_PATH,
monitor_update_resolv,true);
if (ret != EOK) {
return ret;
}
/* Avoid a startup race condition between process.
* We need to handle DB upgrades or DB creation only
* in one process before all other start.
*/
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) {
return ENOMEM;
}
ret = sysdb_init(tmp_ctx, ctx->cdb, NULL, true, &db_list);
if (ret != EOK) {
return ret;
}
talloc_zfree(tmp_ctx);
/* Initialize D-BUS Server
* The monitor will act as a D-BUS server for all
* SSSD processes */
ret = monitor_dbus_init(ctx);
if (ret != EOK) {
return ret;
}
ret = setup_netlink(ctx, ctx->ev, network_status_change_cb,
ctx, &ctx->nlctx);
if (ret != EOK) {
DEBUG(2, ("Cannot set up listening for network notifications\n"));
return ret;
}
/* start providers */
num_providers = 0;
for (dom = ctx->domains; dom; dom = dom->next) {
ret = add_new_provider(ctx, dom->name, 0);
if (ret != EOK && ret != ENOENT) {
return ret;
}
if (ret != ENOENT) {
num_providers++;
}
}
if (num_providers > 0) {
/* now set the services stratup timeout *
* (responders will be started automatically when all
* providers are up and running or when the tomeout
* 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);
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);
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;
}
/* 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.");
}
/* Check if the SSSD is already running */
ret = check_file(SSSD_PIDFILE_PATH, 0, 0, 0600, CHECK_REG, NULL, false);
if (ret == EOK) {
DEBUG(SSSDBG_FATAL_FAILURE,
("pidfile exists at %s\n", SSSD_PIDFILE_PATH));
ERROR("SSSD is already running\n");
return 2;
}
/* 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->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;
}