commit 52627a1: [Fix] Support listening on systemd sockets by name
Peter Wu
peter at lekensteyn.nl
Sun Feb 16 16:42:17 UTC 2020
Author: Peter Wu
Date: 2020-02-15 19:05:37 +0000
URL: https://github.com/rspamd/rspamd/commit/52627a18288ba460387444d8c2f0fa2477b1a286 (refs/pull/3265/head)
[Fix] Support listening on systemd sockets by name
* Add support for looking up sockets by the systemd socket name, e.g.
`systemd:rspamd-proxy.socket` or the name from `FileDescriptorName`.
https://www.freedesktop.org/software/systemd/man/sd_listen_fds.html
* Replace EOVERFLOW error code to avoid confusing error messages.
Fixes: #2035
---
src/libserver/cfg_utils.c | 10 ++++++----
src/rspamd.c | 51 +++++++++++++++++++++++++++++++++++++----------
2 files changed, 46 insertions(+), 15 deletions(-)
diff --git a/src/libserver/cfg_utils.c b/src/libserver/cfg_utils.c
index be1d948a7..b74759229 100644
--- a/src/libserver/cfg_utils.c
+++ b/src/libserver/cfg_utils.c
@@ -98,7 +98,7 @@ rspamd_parse_bind_line (struct rspamd_config *cfg,
const gchar *str)
{
struct rspamd_worker_bind_conf *cnf;
- gchar *err;
+ const gchar *fdname;
gboolean ret = TRUE;
if (str == NULL) {
@@ -112,11 +112,13 @@ rspamd_parse_bind_line (struct rspamd_config *cfg,
if (g_ascii_strncasecmp (str, "systemd:", sizeof ("systemd:") - 1) == 0) {
/* The actual socket will be passed by systemd environment */
+ fdname = str + sizeof ("systemd:") - 1;
cnf->is_systemd = TRUE;
- cnf->cnt = strtoul (str + sizeof ("systemd:") - 1, &err, 10);
- cnf->addrs = g_ptr_array_new ();
+ cnf->addrs = g_ptr_array_new_full (1, g_free);
- if (err == NULL || *err == '\0') {
+ if (fdname[0]) {
+ g_ptr_array_add (cnf->addrs, g_strdup (fdname));
+ cnf->cnt = cnf->addrs->len;
cnf->name = g_strdup (str);
LL_PREPEND (cf->bind_conf, cnf);
}
diff --git a/src/rspamd.c b/src/rspamd.c
index 3a889ec69..511408f23 100644
--- a/src/rspamd.c
+++ b/src/rspamd.c
@@ -433,15 +433,15 @@ create_listen_socket (GPtrArray *addrs, guint cnt,
}
static GList *
-systemd_get_socket (struct rspamd_main *rspamd_main, gint number)
+systemd_get_socket (struct rspamd_main *rspamd_main, const gchar *fdname)
{
- int sock, num_passed, flags;
+ int number, sock, num_passed, flags;
GList *result = NULL;
const gchar *e;
- gchar *err;
+ gchar **fdnames;
+ gchar *end;
struct stat st;
- /* XXX: can we trust the current choice ? */
- static const int sd_listen_fds_start = 3;
+ static const int sd_listen_fds_start = 3; /* SD_LISTEN_FDS_START */
struct rspamd_worker_listen_socket *ls;
union {
@@ -451,11 +451,39 @@ systemd_get_socket (struct rspamd_main *rspamd_main, gint number)
socklen_t slen = sizeof (addr_storage);
gint stype;
+ number = strtoul (fdname, &end, 10);
+ if (end != NULL && *end != '\0') {
+ /* Cannot parse as number, assume a name in LISTEN_FDNAMES. */
+ e = getenv ("LISTEN_FDNAMES");
+ if (!e) {
+ msg_err_main ("cannot get systemd variable 'LISTEN_FDNAMES'");
+ errno = ENOENT;
+ return NULL;
+ }
+
+ fdnames = g_strsplit (e, ":", -1);
+ for (number = 0; fdnames[number]; number++) {
+ if (!strcmp (fdnames[number], fdname)) {
+ break;
+ }
+ }
+ if (!fdnames[number]) {
+ number = -1;
+ }
+ g_strfreev (fdnames);
+ }
+
+ if (number < 0) {
+ msg_warn_main ("cannot find systemd socket: %s", fdname);
+ errno = ENOENT;
+ return NULL;
+ }
+
e = getenv ("LISTEN_FDS");
if (e != NULL) {
errno = 0;
- num_passed = strtoul (e, &err, 10);
- if ((err == NULL || *err == '\0') && num_passed > number) {
+ num_passed = strtoul (e, &end, 10);
+ if ((end == NULL || *end == '\0') && num_passed > number) {
sock = number + sd_listen_fds_start;
if (fstat (sock, &st) == -1) {
msg_warn_main ("cannot stat systemd descriptor %d", sock);
@@ -506,7 +534,7 @@ systemd_get_socket (struct rspamd_main *rspamd_main, gint number)
else if (num_passed <= number) {
msg_err_main ("systemd LISTEN_FDS does not contain the expected fd: %d",
num_passed);
- errno = EOVERFLOW;
+ errno = EINVAL;
}
}
else {
@@ -543,8 +571,8 @@ make_listen_key (struct rspamd_worker_bind_conf *cf)
rspamd_cryptobox_fast_hash_init (&st, rspamd_hash_seed ());
if (cf->is_systemd) {
- rspamd_cryptobox_fast_hash_update (&st, "systemd", sizeof ("systemd"));
- rspamd_cryptobox_fast_hash_update (&st, &cf->cnt, sizeof (cf->cnt));
+ /* Something like 'systemd:0' or 'systemd:controller'. */
+ rspamd_cryptobox_fast_hash_update (&st, cf->name, strlen (cf->name));
}
else {
rspamd_cryptobox_fast_hash_update (&st, cf->name, strlen (cf->name));
@@ -643,7 +671,8 @@ spawn_workers (struct rspamd_main *rspamd_main, struct ev_loop *ev_base)
cf->worker->listen_type);
}
else {
- ls = systemd_get_socket (rspamd_main, bcf->cnt);
+ ls = systemd_get_socket (rspamd_main,
+ g_ptr_array_index (bcf->addrs, 0));
}
if (ls == NULL) {
More information about the Commits
mailing list