diff --git a/configure.ac b/configure.ac index aec9978..9b7fbf3 100644 --- a/configure.ac +++ b/configure.ac @@ -86,5 +86,32 @@ if $tls; then [AC_DEFINE(HAVE_GNUTLS_PRIORITY_SET_DIRECT, 1, [libgnutls has gnutls_priority_set_direct])]) fi +AC_ARG_ENABLE(systemd, + AS_HELP_STRING( + [--enable-systemd], + [build with systemd watchdog support]), + enable_systemd=$enableval,enable_systemd=auto) + +dnl systemd detection +if test x$enable_systemd = xno ; then + have_systemd=no; +else + PKG_CHECK_MODULES([SYSTEMD], + [libsystemd >= 209], + [have_systemd=yes], + [PKG_CHECK_MODULES([SYSTEMD], + [libsystemd-daemon >= 32], + [have_systemd=yes], + [have_systemd=no])]) +fi + +if test x$have_systemd = xyes; then + AC_DEFINE(HAVE_SYSTEMD,1,[Have systemd]) +fi + +if test x$enable_systemd = xyes -a x$have_systemd != xyes ; then + AC_MSG_ERROR([Explicitly requested systemd support, but systemd not found]) +fi + AC_CONFIG_FILES([Makefile doc/Makefile lib/Makefile lib/cli++/Makefile lib/fdbuf/Makefile lib/mystring/Makefile protocols/Makefile src/Makefile test/Makefile]) AC_OUTPUT diff --git a/doc/nullmailer-send.8 b/doc/nullmailer-send.8 index 85b705c..34e5f96 100644 --- a/doc/nullmailer-send.8 +++ b/doc/nullmailer-send.8 @@ -137,9 +137,6 @@ Set the source address for connections to the remote host. .B auth-login Force SMTP "AUTH LOGIN" mode instead of auto-detecting. .TP -.B auth-external -Use SMTP "AUTH EXTERNAL" for TLS client certificate authentication. -.TP .B tls Connect using TLS. This will automatically switch the default port to diff --git a/protocols/protocol.cc b/protocols/protocol.cc index edf9cfc..6c43d55 100644 --- a/protocols/protocol.cc +++ b/protocols/protocol.cc @@ -55,8 +55,6 @@ cli_option cli_options[] = { { 0, "source", cli_option::string, 0, &source, "Source address for connections", 0 }, #ifdef HAVE_TLS - { 0, "auth-external", cli_option::flag, AUTH_EXTERNAL, &auth_method, - "Use AUTH EXTERNAL for certificate based authentication", 0 }, { 0, "tls", cli_option::flag, 1, &use_tls, "Connect using TLS (on an alternate port by default)", 0 }, { 0, "ssl", cli_option::flag, 1, &use_tls, diff --git a/protocols/protocol.h b/protocols/protocol.h index 1a13e0a..2b1c9f6 100644 --- a/protocols/protocol.h +++ b/protocols/protocol.h @@ -13,7 +13,6 @@ extern void protocol_succ(const char* msg); #define AUTH_DETECT 0 #define AUTH_LOGIN 1 #define AUTH_PLAIN 2 -#define AUTH_EXTERNAL 3 extern const char* user; extern const char* pass; extern int auth_method; diff --git a/protocols/smtp.cc b/protocols/smtp.cc index 00f076e..de6be32 100644 --- a/protocols/smtp.cc +++ b/protocols/smtp.cc @@ -231,14 +231,7 @@ void protocol_send(fdibuf& in, fdibuf& netin, fdobuf& netout) if (!did_starttls) conn.docmd("", 200); - if (auth_method == AUTH_EXTERNAL) { - conn.dohelo(true); - if (conn.hascap("AUTH", "EXTERNAL")) - conn.docmd("AUTH EXTERNAL =", 200, ERR_AUTH_FAILED); - else - protocol_fail(ERR_MSG_TEMPFAIL, "Server does not advertise certificate authentication"); - } - else if (user != 0 && pass != 0) { + if (user != 0 && pass != 0) { conn.dohelo(true); if (auth_method == AUTH_LOGIN) conn.auth_login(); diff --git a/src/Makefile.am b/src/Makefile.am index 4a742c2..a70078c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -25,7 +25,7 @@ nullmailer_queue_SOURCES = queue.cc nullmailer_queue_LDADD = ../lib/libnullmailer.a ../lib/cli++/libcli++.a nullmailer_send_SOURCES = send.cc -nullmailer_send_LDADD = ../lib/libnullmailer.a ../lib/cli++/libcli++.a +nullmailer_send_LDADD = ../lib/libnullmailer.a ../lib/cli++/libcli++.a $(SYSTEMD_LIBS) nullmailer_smtpd_SOURCES = smtpd.cc nullmailer_smtpd_LDADD = ../lib/libnullmailer.a diff --git a/src/send.cc b/src/send.cc index 95f8400..0946396 100644 --- a/src/send.cc +++ b/src/send.cc @@ -45,6 +45,16 @@ #include "selfpipe.h" #include "setenv.h" +#ifdef HAVE_SYSTEMD +#include + +#define MAXPAUSE_DEFAULT 9*60 +#else +#define MAXPAUSE_DEFAULT 24*60*60 +#endif + +#define MICROSECOND 1000000 + const char* cli_program = "nullmailer-send"; selfpipe selfpipe; @@ -71,6 +81,11 @@ typedef list msglist; static mystring trigger_path; static mystring msg_dir; +#ifdef HAVE_SYSTEMD +static int watchdog_enabled = 0; +static uint64_t watchdog_timeout = 0; +#endif + struct remote { static const mystring default_proto; @@ -115,8 +130,8 @@ typedef list rlist; static rlist remotes; static int minpause = 60; static int pausetime = minpause; -static int maxpause = 24*60*60; -static int sendtimeout = 60*60; +static int maxpause = MAXPAUSE_DEFAULT; +static int sendtimeout = 5*60; // reduced from 60*60 static int queuelifetime = 7*24*60*60; bool load_remotes() @@ -149,7 +164,7 @@ bool load_config() if(!config_readint("pausetime", minpause)) minpause = 60; if(!config_readint("maxpause", maxpause)) - maxpause = 24*60*60; + maxpause = MAXPAUSE_DEFAULT; if(!config_readint("sendtimeout", sendtimeout)) sendtimeout = 60*60; if(!config_readint("queuelifetime", queuelifetime)) @@ -375,6 +390,38 @@ bool bounce_msg(const message& msg, const remote& remote, const mystring& output return true; } +#ifdef HAVE_SYSTEMD +/* update maxpause so select will return before we need to send our next notification + maxpause is in seconds, watchdog_timeout is microseconds */ +int get_maxpause() +{ + int new_maxpause = (watchdog_timeout/(2*MICROSECOND)); + if (new_maxpause < 1) { + fout << "systemd watchdog timeout is too short, disabling" << endl; + watchdog_enabled = false; + return maxpause; + } + return new_maxpause; +} + +void systemd_notify_ready() +{ + watchdog_enabled = sd_watchdog_enabled(0, &watchdog_timeout); + if (watchdog_enabled) { + fout << "systemd watchdog enabled every " << (int)(watchdog_timeout/MICROSECOND) << " seconds" << endl; + sd_notify(0, "READY=1"); + maxpause = get_maxpause(); + } +} + +void systemd_notify_heartbeat() +{ + if (watchdog_enabled) { + sd_notify(0, "WATCHDOG=1"); + } +} +#endif // HAVE_SYSTEMD + void send_all() { if(!load_config()) { @@ -395,6 +442,7 @@ void send_all() while(msg) { switch (send_one((*msg).filename, *remote, output)) { case tempfail: + systemd_notify_heartbeat(); if (time(0) - (*msg).timestamp > queuelifetime) { if (bounce_msg(*msg, *remote, output)) { messages.remove(msg); @@ -468,6 +516,10 @@ bool do_select() if (pausetime > maxpause) pausetime = maxpause; +#ifdef HAVE_SYSTEMD + systemd_notify_heartbeat(); +#endif + int s = select(trigger+1, &readfds, 0, 0, &timeout); if(s == 1) { fout << "Trigger pulled." << endl; @@ -508,6 +560,9 @@ int main(int, char*[]) signal(SIGHUP, SIG_IGN); load_config(); load_messages(); +#ifdef HAVE_SYSTEMD + systemd_notify_ready(); +#endif for(;;) { send_all(); if (minpause == 0) break;