summaryrefslogtreecommitdiffstats
path: root/src/master/master_wakeup.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/master/master_wakeup.c')
-rw-r--r--src/master/master_wakeup.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/src/master/master_wakeup.c b/src/master/master_wakeup.c
new file mode 100644
index 0000000..cc50924
--- /dev/null
+++ b/src/master/master_wakeup.c
@@ -0,0 +1,192 @@
+/*++
+/* NAME
+/* master_wakeup 3
+/* SUMMARY
+/* Postfix master - start/stop service wakeup timers
+/* SYNOPSIS
+/* #include "master.h"
+/*
+/* void master_wakeup_init(serv)
+/* MASTER_SERV *serv;
+/*
+/* void master_wakeup_cleanup(serv)
+/* MASTER_SERV *serv;
+/* DESCRIPTION
+/* This module implements automatic service wakeup. In order to
+/* wakeup a service, a wakeup trigger is sent to the corresponding
+/* service port or FIFO, and a timer is started to repeat this sequence
+/* after a configurable amount of time.
+/*
+/* master_wakeup_init() wakes up the named service. No wakeup
+/* is done or scheduled when a zero wakeup time is given, or when
+/* the service has been throttled in the mean time.
+/* It is OK to call master_wakeup_init() while a timer is already
+/* running for the named service. The effect is to restart the
+/* wakeup timer.
+/*
+/* master_wakeup_cleanup() cancels the wakeup timer for the named
+/* service. It is an error to disable a service while it still has
+/* an active wakeup timer (doing so would cause a dangling reference
+/* to a non-existent service).
+/* It is OK to call master_wakeup_cleanup() even when no timer is
+/* active for the named service.
+/* DIAGNOSTICS
+/* BUGS
+/* SEE ALSO
+/* inet_trigger(3), internet-domain client
+/* unix_trigger(3), unix-domain client
+/* fifo_trigger(3), fifo client
+/* upass_trigger(3), file descriptor passing client
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <trigger.h>
+#include <events.h>
+#include <set_eugid.h>
+#include <set_ugid.h>
+
+/* Global library. */
+
+#include <mail_proto.h> /* triggers */
+#include <mail_params.h>
+
+/* Application-specific. */
+
+#include "mail_server.h"
+#include "master.h"
+
+/* master_wakeup_timer_event - wakeup event handler */
+
+static void master_wakeup_timer_event(int unused_event, void *context)
+{
+ const char *myname = "master_wakeup_timer_event";
+ MASTER_SERV *serv = (MASTER_SERV *) context;
+ int status;
+ static char wakeup = TRIGGER_REQ_WAKEUP;
+
+ /*
+ * Don't wakeup services whose automatic wakeup feature was turned off in
+ * the mean time.
+ */
+ if (serv->wakeup_time == 0)
+ return;
+
+ /*
+ * Don't wake up services that are throttled. Find out what transport to
+ * use. We can't block here so we choose a short timeout.
+ */
+#define BRIEFLY 1
+
+ if (MASTER_THROTTLED(serv) == 0) {
+ if (msg_verbose)
+ msg_info("%s: service %s", myname, serv->name);
+
+ switch (serv->type) {
+ case MASTER_SERV_TYPE_INET:
+ status = inet_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
+ break;
+ case MASTER_SERV_TYPE_UNIX:
+ status = LOCAL_TRIGGER(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
+ break;
+ case MASTER_SERV_TYPE_UXDG:
+ status = -1;
+ errno = EOPNOTSUPP;
+ break;
+#ifdef MASTER_SERV_TYPE_PASS
+ case MASTER_SERV_TYPE_PASS:
+ status = pass_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
+ break;
+#endif
+
+ /*
+ * If someone compromises the postfix account then this must not
+ * overwrite files outside the chroot jail. Countermeasures:
+ *
+ * - Limit the damage by accessing the FIFO as postfix not root.
+ *
+ * - Have fifo_trigger() call safe_open() so we won't follow
+ * arbitrary hard/symlinks to files in/outside the chroot jail.
+ *
+ * - All non-chroot postfix-related files must be root owned (or
+ * postfix check complains).
+ *
+ * - The postfix user and group ID must not be shared with other
+ * applications (says the INSTALL documentation).
+ *
+ * Result of a discussion with Michael Tokarev, who received his
+ * insights from Solar Designer, who tested Postfix with a kernel
+ * module that is paranoid about open() calls.
+ */
+ case MASTER_SERV_TYPE_FIFO:
+ set_eugid(var_owner_uid, var_owner_gid);
+ status = fifo_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
+ set_ugid(getuid(), getgid());
+ break;
+ default:
+ msg_panic("%s: unknown service type: %d", myname, serv->type);
+ }
+ if (status < 0)
+ msg_warn("%s: service %s(%s): %m",
+ myname, serv->ext_name, serv->name);
+ }
+
+ /*
+ * Schedule another wakeup event.
+ */
+ event_request_timer(master_wakeup_timer_event, (void *) serv,
+ serv->wakeup_time);
+}
+
+/* master_wakeup_init - start automatic service wakeup */
+
+void master_wakeup_init(MASTER_SERV *serv)
+{
+ const char *myname = "master_wakeup_init";
+
+ if (serv->wakeup_time == 0 || (serv->flags & MASTER_FLAG_CONDWAKE))
+ return;
+ if (msg_verbose)
+ msg_info("%s: service %s time %d",
+ myname, serv->name, serv->wakeup_time);
+ master_wakeup_timer_event(0, (void *) serv);
+}
+
+/* master_wakeup_cleanup - cancel wakeup timer */
+
+void master_wakeup_cleanup(MASTER_SERV *serv)
+{
+ const char *myname = "master_wakeup_cleanup";
+
+ /*
+ * Cleanup, even when the wakeup feature has been turned off. There might
+ * still be a pending timer. Don't depend on the code that reloads the
+ * config file to reset the wakeup timer when things change.
+ */
+ if (msg_verbose)
+ msg_info("%s: service %s", myname, serv->name);
+
+ event_cancel_timer(master_wakeup_timer_event, (void *) serv);
+}