diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2014-02-20 16:30:27 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2014-02-20 16:30:27 +0000 |
commit | 6039f81e4886071d61e5cfebc3b16e9ab0b8f01f (patch) | |
tree | 93f7d92f733015e6bef331538d79fcdace1b3ae7 | |
parent | 5c026b66583e20f4f1455f7f0da773f64c26992d (diff) | |
download | rspamd-6039f81e4886071d61e5cfebc3b16e9ab0b8f01f.tar.gz rspamd-6039f81e4886071d61e5cfebc3b16e9ab0b8f01f.zip |
Support accepting listening sockets from systemd.
-rw-r--r-- | src/cfg_file.h | 1 | ||||
-rw-r--r-- | src/cfg_utils.c | 10 | ||||
-rw-r--r-- | src/main.c | 54 |
3 files changed, 61 insertions, 4 deletions
diff --git a/src/cfg_file.h b/src/cfg_file.h index 13acb158f..c1ebfd93c 100644 --- a/src/cfg_file.h +++ b/src/cfg_file.h @@ -227,6 +227,7 @@ struct rspamd_worker_bind_conf { gchar *bind_host; guint16 bind_port; gint ai; + gboolean is_systemd; struct rspamd_worker_bind_conf *next; }; diff --git a/src/cfg_utils.c b/src/cfg_utils.c index 8575b254b..dbd4f0f83 100644 --- a/src/cfg_utils.c +++ b/src/cfg_utils.c @@ -196,7 +196,7 @@ gboolean parse_bind_line (struct config_file *cfg, struct worker_conf *cf, const gchar *str) { struct rspamd_worker_bind_conf *cnf; - gchar **tokens, *tmp; + gchar **tokens, *tmp, *err; gboolean ret; if (str == NULL) { @@ -238,6 +238,14 @@ parse_bind_line (struct config_file *cfg, struct worker_conf *cf, const gchar *s } tokens[0] = tmp; } + else if (strcmp (tokens[0], "systemd") == 0) { + /* The actual socket will be passed by systemd environment */ + cnf->bind_host = memory_pool_strdup (cfg->cfg_pool, str); + cnf->ai = strtoul (tokens[1], &err, 10); + if (err == NULL || *err == '\0') { + LL_PREPEND (cf->bind_conf, cnf); + } + } else { if ((ret = parse_host_port_priority_strv (cfg->cfg_pool, tokens, &cnf->bind_host, &cnf->bind_port, NULL, DEFAULT_BIND_PORT))) { diff --git a/src/main.c b/src/main.c index ae4d5d409..a8196ef06 100644 --- a/src/main.c +++ b/src/main.c @@ -549,6 +549,48 @@ create_listen_socket (const gchar *addr, gint port, gint listen_type) return result; } +static GList * +systemd_get_socket (gint number, gint listen_type) +{ + int sock, max; + GList *result = NULL; + const gchar *e; + gchar *err; + struct stat st; + /* XXX: can we trust the current choice ? */ + static const int sd_listen_fds_start = 3; + + e = getenv ("LISTEN_FDS"); + if (e != NULL) { + errno = 0; + max = strtoul (e, &err, 10); + if ((e == NULL || *e == '\0') && max > number + sd_listen_fds_start) { + sock = number + sd_listen_fds_start; + if (fstat (sock, &st) == -1) { + return NULL; + } + if (!S_ISSOCK (st.st_mode)) { + errno = EINVAL; + return NULL; + } + if (listen_type != SOCK_DGRAM) { + if (listen (sock, -1) == -1) { + return NULL; + } + } + result = g_list_prepend (result, GINT_TO_POINTER (sock)); + } + else if (max <= number + sd_listen_fds_start) { + errno = EOVERFLOW; + } + } + else { + errno = ENOENT; + } + + return result; +} + static void fork_delayed (struct rspamd_main *rspamd) { @@ -599,10 +641,16 @@ spawn_workers (struct rspamd_main *rspamd) LL_FOREACH (cf->bind_conf, bcf) { key = make_listen_key (bcf->ai, bcf->bind_host, bcf->bind_port); if ((p = g_hash_table_lookup (listen_sockets, GINT_TO_POINTER (key))) == NULL) { - /* Create listen socket */ - ls = create_listen_socket (bcf->bind_host, bcf->bind_port, - cf->worker->listen_type); + if (!bcf->is_systemd) { + /* Create listen socket */ + ls = create_listen_socket (bcf->bind_host, bcf->bind_port, + cf->worker->listen_type); + } + else { + ls = systemd_get_socket (bcf->ai, cf->worker->listen_type); + } if (ls == NULL) { + msg_err ("cannot listen on socket %s: %s", bcf->bind_host, strerror (errno)); exit (-errno); } g_hash_table_insert (listen_sockets, GINT_TO_POINTER (key), ls); |