Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Systemd #85

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 0 additions & 3 deletions doc/nullmailer-send.8
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 0 additions & 2 deletions protocols/protocol.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 0 additions & 1 deletion protocols/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
9 changes: 1 addition & 8 deletions protocols/smtp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
61 changes: 58 additions & 3 deletions src/send.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@
#include "selfpipe.h"
#include "setenv.h"

#ifdef HAVE_SYSTEMD
#include <systemd/sd-daemon.h>

#define MAXPAUSE_DEFAULT 9*60
#else
#define MAXPAUSE_DEFAULT 24*60*60
#endif

#define MICROSECOND 1000000

const char* cli_program = "nullmailer-send";

selfpipe selfpipe;
Expand All @@ -71,6 +81,11 @@ typedef list<struct message> 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;
Expand Down Expand Up @@ -115,8 +130,8 @@ typedef list<remote> 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()
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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()) {
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down