journal-remote.c revision ce30c8dcb41dfe9264f79f30c7f51c0e74576638
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/***
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen This file is part of systemd.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Copyright 2012 Zbigniew Jędrzejewski-Szmek
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen systemd is free software; you can redistribute it and/or modify it
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen under the terms of the GNU Lesser General Public License as published by
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen the Free Software Foundation; either version 2.1 of the License, or
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen (at your option) any later version.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen systemd is distributed in the hope that it will be useful, but
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen WITHOUT ANY WARRANTY; without even the implied warranty of
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Lesser General Public License for more details.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen You should have received a copy of the GNU Lesser General Public License
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen***/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <errno.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <fcntl.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <stdio.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <stdlib.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <string.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <sys/prctl.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <sys/socket.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <unistd.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <getopt.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "sd-daemon.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "signal-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "journal-file.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "journald-native.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "socket-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "build.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "macro.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "strv.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "fileio.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "conf-parser.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#ifdef HAVE_GNUTLS
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <gnutls/gnutls.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#endif
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "journal-remote.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "journal-remote-write.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#define REMOTE_JOURNAL_PATH "/var/log/journal/remote"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-remote.pem"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#define CERT_FILE CERTIFICATE_ROOT "/certs/journal-remote.pem"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#define TRUST_FILE CERTIFICATE_ROOT "/ca/trusted.pem"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic char* arg_url = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic char* arg_getter = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic char* arg_listen_raw = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic char* arg_listen_http = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic char* arg_listen_https = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic char** arg_files = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int arg_compress = true;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int arg_seal = false;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int http_socket = -1, https_socket = -1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic char** arg_gnutls_log = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic JournalWriteSplitMode arg_split_mode = JOURNAL_WRITE_SPLIT_HOST;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic char* arg_output = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic char *arg_key = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic char *arg_cert = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic char *arg_trust = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic bool arg_trust_all = false;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/**********************************************************************
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen **********************************************************************
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen **********************************************************************/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int spawn_child(const char* child, char** argv) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int fd[2];
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen pid_t parent_pid, child_pid;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (pipe(fd) < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_error_errno(errno, "Failed to create pager pipe: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen parent_pid = getpid();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen child_pid = fork();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (child_pid < 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = -errno;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(errno, "Failed to fork: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen safe_close_pair(fd);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* In the child */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (child_pid == 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen (void) reset_all_signal_handlers();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen (void) reset_signal_mask();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = dup2(fd[1], STDOUT_FILENO);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(errno, "Failed to dup pipe to stdout: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _exit(EXIT_FAILURE);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen safe_close_pair(fd);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Make sure the child goes away when the parent dies */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _exit(EXIT_FAILURE);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Check whether our parent died before we were able
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen * to set the death signal */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (getppid() != parent_pid)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _exit(EXIT_SUCCESS);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen execvp(child, argv);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(errno, "Failed to exec child %s: %m", child);
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen _exit(EXIT_FAILURE);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = close(fd[1]);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_warning_errno(errno, "Failed to close write end of pipe: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return fd[0];
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int spawn_curl(const char* url) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen char **argv = STRV_MAKE("curl",
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen "-HAccept: application/vnd.fdo.journal",
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen "--silent",
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen "--show-error",
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen url);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = spawn_child("curl", argv);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(errno, "Failed to spawn curl: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int spawn_getter(const char *getter, const char *url) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_strv_free_ char **words = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(getter);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = strv_split_quoted(&words, getter, 0);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_error_errno(r, "Failed to split getter option: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = strv_extend(&words, url);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_error_errno(r, "Failed to create command line: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = spawn_child(words[0], words);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(errno, "Failed to spawn getter %s: %m", getter);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen return r;
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#define filename_escape(s) xescape((s), "/ ")
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int open_output(Writer *w, const char* host) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_free_ char *_output = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *output;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen switch (arg_split_mode) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case JOURNAL_WRITE_SPLIT_NONE:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen output = arg_output ?: REMOTE_JOURNAL_PATH "/remote.journal";
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen break;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case JOURNAL_WRITE_SPLIT_HOST: {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_free_ char *name;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(host);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
d171ed1c50ba64928b7fb30ee2ae729fdfe0826bThomas Hindoe Paaboel Andersen name = filename_escape(host);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!name)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_oom();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = asprintf(&_output, "%s/remote-%s.journal",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen arg_output ?: REMOTE_JOURNAL_PATH,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_oom();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen output = _output;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen break;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen default:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert_not_reached("what?");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = journal_file_open_reliably(output,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen O_RDWR|O_CREAT, 0640,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen arg_compress, arg_seal,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen &w->metrics,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen w->mmap,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen NULL, &w->journal);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(r, "Failed to open output journal %s: %m",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen output);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Opened output file %s", w->journal->path);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/**********************************************************************
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen **********************************************************************
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen **********************************************************************/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int init_writer_hashmap(RemoteServer *s) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen static const struct hash_ops *hash_ops[] = {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [JOURNAL_WRITE_SPLIT_NONE] = NULL,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [JOURNAL_WRITE_SPLIT_HOST] = &string_hash_ops,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen };
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(arg_split_mode >= 0 && arg_split_mode < (int) ELEMENTSOF(hash_ops));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen s->writers = hashmap_new(hash_ops[arg_split_mode]);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!s->writers)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_oom();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int get_writer(RemoteServer *s, const char *host,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Writer **writer) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const void *key;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_writer_unref_ Writer *w = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen switch(arg_split_mode) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case JOURNAL_WRITE_SPLIT_NONE:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen key = "one and only";
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen break;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case JOURNAL_WRITE_SPLIT_HOST:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(host);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen key = host;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen break;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen default:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert_not_reached("what split mode?");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen w = hashmap_get(s->writers, key);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (w)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen writer_ref(w);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen w = writer_new(s);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!w)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_oom();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (arg_split_mode == JOURNAL_WRITE_SPLIT_HOST) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen w->hashmap_key = strdup(key);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!w->hashmap_key)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_oom();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = open_output(w, host);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = hashmap_put(s->writers, w->hashmap_key ?: key, w);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen *writer = w;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen w = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/**********************************************************************
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen **********************************************************************
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen **********************************************************************/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/* This should go away as soon as µhttpd allows state to be passed around. */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic RemoteServer *server;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int dispatch_raw_source_event(sd_event_source *event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int fd,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen uint32_t revents,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen void *userdata);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int dispatch_raw_source_until_block(sd_event_source *event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen void *userdata);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int dispatch_blocking_source_event(sd_event_source *event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen void *userdata);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int dispatch_raw_connection_event(sd_event_source *event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int fd,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen uint32_t revents,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen void *userdata);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int dispatch_http_event(sd_event_source *event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int fd,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen uint32_t revents,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen void *userdata);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int get_source_for_fd(RemoteServer *s,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int fd, char *name, RemoteSource **source) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Writer *writer;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* This takes ownership of name, but only on success. */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(fd >= 0);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(source);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!GREEDY_REALLOC0(s->sources, s->sources_size, fd + 1))
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_oom();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = get_writer(s, name, &writer);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_warning_errno(r, "Failed to get writer for source %s: %m",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (s->sources[fd] == NULL) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen s->sources[fd] = source_new(fd, false, name, writer);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!s->sources[fd]) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen writer_unref(writer);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_oom();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen s->active++;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen *source = s->sources[fd];
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int remove_source(RemoteServer *s, int fd) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen RemoteSource *source;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(s);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(fd >= 0 && fd < (ssize_t) s->sources_size);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen source = s->sources[fd];
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (source) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* this closes fd too */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen source_free(source);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen s->sources[fd] = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen s->active--;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int add_source(RemoteServer *s, int fd, char* name, bool own_name) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen RemoteSource *source = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* This takes ownership of name, even on failure, if own_name is true. */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(s);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(fd >= 0);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!own_name) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen name = strdup(name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!name)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_oom();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = get_source_for_fd(s, fd, name, &source);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(r, "Failed to create source for fd:%d (%s): %m",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen fd, name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen free(name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_add_io(s->events, &source->event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen fd, EPOLLIN|EPOLLRDHUP|EPOLLPRI,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen dispatch_raw_source_event, source);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r == 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Add additional source for buffer processing. It will be
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen * enabled later. */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_add_defer(s->events, &source->buffer_event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen dispatch_raw_source_until_block, source);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r == 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_event_source_set_enabled(source->buffer_event, SD_EVENT_OFF);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen } else if (r == -EPERM) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Falling back to sd_event_add_defer for fd:%d (%s)", fd, name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_add_defer(s->events, &source->event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen dispatch_blocking_source_event, source);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r == 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_event_source_set_enabled(source->event, SD_EVENT_ON);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(r, "Failed to register event source for fd:%d: %m",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen fd);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen goto error;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_source_set_description(source->event, name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(r, "Failed to set source name for fd:%d: %m", fd);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen goto error;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 1; /* work to do */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen error:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen remove_source(s, fd);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int add_raw_socket(RemoteServer *s, int fd) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_close_ int fd_ = fd;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen char name[sizeof("raw-socket-")-1 + DECIMAL_STR_MAX(int) + 1];
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(fd >= 0);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_add_io(s->events, &s->listen_event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen fd, EPOLLIN,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen dispatch_raw_connection_event, s);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen xsprintf(name, "raw-socket-%d", fd);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_source_set_description(s->listen_event, name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen fd_ = -1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen s->active ++;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int setup_raw_socket(RemoteServer *s, const char *address) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int fd;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen fd = make_socket_fd(LOG_INFO, address, SOCK_STREAM | SOCK_CLOEXEC);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (fd < 0)
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek return fd;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return add_raw_socket(s, fd);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek/**********************************************************************
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen **********************************************************************
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen **********************************************************************/
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int request_meta(void **connection_cls, int fd, char *hostname) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen RemoteSource *source;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Writer *writer;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(connection_cls);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (*connection_cls)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = get_writer(server, hostname, &writer);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_warning_errno(r, "Failed to get writer for source %s: %m",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen hostname);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen source = source_new(fd, true, hostname, writer);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!source) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen writer_unref(writer);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_oom();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Added RemoteSource as connection metadata %p", source);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen *connection_cls = source;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic void request_meta_free(void *cls,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen struct MHD_Connection *connection,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen void **connection_cls,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen enum MHD_RequestTerminationCode toe) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen RemoteSource *s;
805b573fad06b845502e76f3db3a0efa7583149dLukas Nykryn
805b573fad06b845502e76f3db3a0efa7583149dLukas Nykryn assert(connection_cls);
805b573fad06b845502e76f3db3a0efa7583149dLukas Nykryn s = *connection_cls;
805b573fad06b845502e76f3db3a0efa7583149dLukas Nykryn
805b573fad06b845502e76f3db3a0efa7583149dLukas Nykryn if (s) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Cleaning up connection metadata %p", s);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen source_free(s);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen *connection_cls = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int process_http_upload(
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek struct MHD_Connection *connection,
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek const char *upload_data,
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek size_t *upload_data_size,
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek RemoteSource *source) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bool finished = false;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen size_t remaining;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek assert(source);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_trace("%s: connection %p, %zu bytes",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen __func__, connection, *upload_data_size);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek if (*upload_data_size) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_trace("Received %zu bytes", *upload_data_size);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = push_data(source, upload_data, *upload_data_size);
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respond_oom(connection);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen *upload_data_size = 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen } else
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen finished = true;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen while (true) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = process_source(source, arg_compress, arg_seal);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r == -EAGAIN)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen break;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else if (r < 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_warning("Failed to process data for connection %p", connection);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r == -E2BIG)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respondf(connection,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "Entry is too large, maximum is %u bytes.\n",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen DATA_SIZE_MAX);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respondf(connection,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MHD_HTTP_UNPROCESSABLE_ENTITY,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "Processing failed: %s.", strerror(-r));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!finished)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return MHD_YES;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* The upload is finished */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen remaining = source_non_empty(source);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (remaining > 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_warning("Premature EOFbyte. %zu bytes lost.", remaining);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respondf(connection, MHD_HTTP_EXPECTATION_FAILED,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "Premature EOF. %zu bytes of trailing data not processed.",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen remaining);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respond(connection, MHD_HTTP_ACCEPTED, "OK.\n");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen};
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int request_handler(
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen void *cls,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen struct MHD_Connection *connection,
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek const char *url,
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek const char *method,
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek const char *version,
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek const char *upload_data,
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek size_t *upload_data_size,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen void **connection_cls) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *header;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r, code, fd;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_free_ char *hostname = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(connection);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(connection_cls);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(url);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(method);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_trace("Handling a connection %s %s %s", method, url, version);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (*connection_cls)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return process_http_upload(connection,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen upload_data, upload_data_size,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen *connection_cls);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!streq(method, "POST"))
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respond(connection, MHD_HTTP_METHOD_NOT_ACCEPTABLE,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "Unsupported method.\n");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!streq(url, "/upload"))
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respond(connection, MHD_HTTP_NOT_FOUND,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "Not found.\n");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen header = MHD_lookup_connection_value(connection,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MHD_HEADER_KIND, "Content-Type");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!header || !streq(header, "application/vnd.fdo.journal"))
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respond(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "Content-Type: application/vnd.fdo.journal"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen " is required.\n");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const union MHD_ConnectionInfo *ci;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen ci = MHD_get_connection_info(connection,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MHD_CONNECTION_INFO_CONNECTION_FD);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!ci) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("MHD_get_connection_info failed: cannot get remote fd");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "Cannot check remote address");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen fd = ci->connect_fd;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(fd >= 0);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (server->check_trust) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = check_permissions(connection, &code, &hostname);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return code;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen } else {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = getnameinfo_pretty(fd, &hostname);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "Cannot check remote hostname");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(hostname);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = request_meta(connection_cls, fd, hostname);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r == -ENOMEM)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return respond_oom(connection);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen strerror(-r));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen hostname = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return MHD_YES;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int setup_microhttpd_server(RemoteServer *s,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int fd,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *key,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *cert,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *trust) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen struct MHD_OptionItem opts[] = {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { MHD_OPTION_NOTIFY_COMPLETED, (intptr_t) request_meta_free},
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { MHD_OPTION_EXTERNAL_LOGGER, (intptr_t) microhttpd_logger},
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { MHD_OPTION_LISTEN_SOCKET, fd},
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { MHD_OPTION_END},
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { MHD_OPTION_END},
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { MHD_OPTION_END},
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { MHD_OPTION_END}};
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int opts_pos = 3;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int flags =
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MHD_USE_DEBUG |
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MHD_USE_PEDANTIC_CHECKS |
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MHD_USE_EPOLL_LINUX_ONLY |
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MHD_USE_DUAL_STACK;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const union MHD_DaemonInfo *info;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r, epoll_fd;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MHDDaemonWrapper *d;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(fd >= 0);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = fd_nonblock(fd, true);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_error_errno(r, "Failed to make fd:%d nonblocking: %m", fd);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (key) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(cert);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen opts[opts_pos++] = (struct MHD_OptionItem)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen {MHD_OPTION_HTTPS_MEM_KEY, 0, (char*) key};
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen opts[opts_pos++] = (struct MHD_OptionItem)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen {MHD_OPTION_HTTPS_MEM_CERT, 0, (char*) cert};
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen flags |= MHD_USE_SSL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (trust)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen opts[opts_pos++] = (struct MHD_OptionItem)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen {MHD_OPTION_HTTPS_MEM_TRUST, 0, (char*) trust};
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen d = new(MHDDaemonWrapper, 1);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!d)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_oom();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen d->fd = (uint64_t) fd;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen d->daemon = MHD_start_daemon(flags, 0,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen NULL, NULL,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen request_handler, NULL,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MHD_OPTION_ARRAY, opts,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MHD_OPTION_END);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!d->daemon) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Failed to start µhttp daemon");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = -EINVAL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen goto error;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Started MHD %s daemon on fd:%d (wrapper @ %p)",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen key ? "HTTPS" : "HTTP", fd, d);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen info = MHD_get_daemon_info(d->daemon, MHD_DAEMON_INFO_EPOLL_FD_LINUX_ONLY);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!info) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("µhttp returned NULL daemon info");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = -EOPNOTSUPP;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen goto error;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen epoll_fd = info->listen_fd;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (epoll_fd < 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("µhttp epoll fd is invalid");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = -EUCLEAN;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen goto error;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_add_io(s->events, &d->event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen epoll_fd, EPOLLIN,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen dispatch_http_event, d);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(r, "Failed to add event callback: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen goto error;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_source_set_description(d->event, "epoll-fd");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(r, "Failed to set source name: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen goto error;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = hashmap_ensure_allocated(&s->daemons, &uint64_hash_ops);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_oom();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen goto error;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = hashmap_put(s->daemons, &d->fd, d);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(r, "Failed to add daemon to hashmap: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen goto error;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen s->active ++;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenerror:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MHD_stop_daemon(d->daemon);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen free(d->daemon);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen free(d);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int setup_microhttpd_socket(RemoteServer *s,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *address,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *key,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *cert,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *trust) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int fd;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen fd = make_socket_fd(LOG_DEBUG, address, SOCK_STREAM | SOCK_CLOEXEC);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (fd < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return fd;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return setup_microhttpd_server(s, fd, key, cert, trust);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int dispatch_http_event(sd_event_source *event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int fd,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen uint32_t revents,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen void *userdata) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MHDDaemonWrapper *d = userdata;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(d);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = MHD_run(d->daemon);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r == MHD_NO) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("MHD_run failed!");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen // XXX: unregister daemon
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -EINVAL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 1; /* work to do */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/**********************************************************************
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen **********************************************************************
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen **********************************************************************/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int setup_signals(RemoteServer *s) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sigset_t mask;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(s);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert_se(sigemptyset(&mask) == 0);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sigset_add_many(&mask, SIGINT, SIGTERM, -1);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_add_signal(s->events, &s->sigterm_event, SIGTERM, NULL, s);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_add_signal(s->events, &s->sigint_event, SIGINT, NULL, s);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int negative_fd(const char *spec) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Return a non-positive number as its inverse, -EINVAL otherwise. */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int fd, r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
855d111304114e922b34b6c4bc2a0b08766c2668Colin Ian King r = safe_atoi(spec, &fd);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (fd > 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -EINVAL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -fd;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int remoteserver_init(RemoteServer *s,
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt const char* key,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char* cert,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char* trust) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r, n, fd;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen char **file;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(s);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if ((arg_listen_raw || arg_listen_http) && trust) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Option --trust makes all non-HTTPS connections untrusted.");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -EINVAL;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_default(&s->events);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_error_errno(r, "Failed to allocate event loop: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen setup_signals(s);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(server == NULL);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen server = s;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = init_writer_hashmap(s);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen n = sd_listen_fds(true);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (n < 0)
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen return log_error_errno(n, "Failed to read listening file descriptors from environment: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Received %d descriptors", n);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (MAX(http_socket, https_socket) >= SD_LISTEN_FDS_START + n) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Received fewer sockets than expected");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -EBADFD;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (sd_is_socket(fd, AF_UNSPEC, 0, true)) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Received a listening socket (fd:%d)", fd);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (fd == http_socket)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = setup_microhttpd_server(s, fd, NULL, NULL, NULL);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else if (fd == https_socket)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = setup_microhttpd_server(s, fd, key, cert, trust);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = add_raw_socket(s, fd);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen } else if (sd_is_socket(fd, AF_UNSPEC, 0, false)) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen char *hostname;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = getnameinfo_pretty(fd, &hostname);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_error_errno(r, "Failed to retrieve remote name: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Received a connection socket (fd:%d) from %s", fd, hostname);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = add_source(s, fd, hostname, true);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen } else {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Unknown socket passed on fd:%d", fd);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -EINVAL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_error_errno(r, "Failed to register socket (fd:%d): %m",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen fd);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (arg_url) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *url, *hostname;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen url = strjoina(arg_url, "/entries");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (arg_getter) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_info("Spawning getter %s...", url);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen fd = spawn_getter(arg_getter, url);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen } else {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_info("Spawning curl %s...", url);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen fd = spawn_curl(url);
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (fd < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return fd;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen hostname =
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen startswith(arg_url, "https://") ?:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen startswith(arg_url, "http://") ?:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen arg_url;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = add_source(s, fd, (char*) hostname, false);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (arg_listen_raw) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Listening on a socket...");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = setup_raw_socket(s, arg_listen_raw);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (arg_listen_http) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = setup_microhttpd_socket(s, arg_listen_http, NULL, NULL, NULL);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (arg_listen_https) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = setup_microhttpd_socket(s, arg_listen_https, key, cert, trust);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen STRV_FOREACH(file, arg_files) {
const char *output_name;
if (streq(*file, "-")) {
log_debug("Using standard input as source.");
fd = STDIN_FILENO;
output_name = "stdin";
} else {
log_debug("Reading file %s...", *file);
fd = open(*file, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
if (fd < 0)
return log_error_errno(errno, "Failed to open %s: %m", *file);
output_name = *file;
}
r = add_source(s, fd, (char*) output_name, false);
if (r < 0)
return r;
}
if (s->active == 0) {
log_error("Zarro sources specified");
return -EINVAL;
}
if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE) {
/* In this case we know what the writer will be
called, so we can create it and verify that we can
create output as expected. */
r = get_writer(s, NULL, &s->_single_writer);
if (r < 0)
return r;
}
return 0;
}
static void server_destroy(RemoteServer *s) {
size_t i;
MHDDaemonWrapper *d;
while ((d = hashmap_steal_first(s->daemons))) {
MHD_stop_daemon(d->daemon);
sd_event_source_unref(d->event);
free(d);
}
hashmap_free(s->daemons);
assert(s->sources_size == 0 || s->sources);
for (i = 0; i < s->sources_size; i++)
remove_source(s, i);
free(s->sources);
writer_unref(s->_single_writer);
hashmap_free(s->writers);
sd_event_source_unref(s->sigterm_event);
sd_event_source_unref(s->sigint_event);
sd_event_source_unref(s->listen_event);
sd_event_unref(s->events);
/* fds that we're listening on remain open... */
}
/**********************************************************************
**********************************************************************
**********************************************************************/
static int handle_raw_source(sd_event_source *event,
int fd,
uint32_t revents,
RemoteServer *s) {
RemoteSource *source;
int r;
/* Returns 1 if there might be more data pending,
* 0 if data is currently exhausted, negative on error.
*/
assert(fd >= 0 && fd < (ssize_t) s->sources_size);
source = s->sources[fd];
assert(source->fd == fd);
r = process_source(source, arg_compress, arg_seal);
if (source->state == STATE_EOF) {
size_t remaining;
log_debug("EOF reached with source fd:%d (%s)",
source->fd, source->name);
remaining = source_non_empty(source);
if (remaining > 0)
log_notice("Premature EOF. %zu bytes lost.", remaining);
remove_source(s, source->fd);
log_debug("%zu active sources remaining", s->active);
return 0;
} else if (r == -E2BIG) {
log_notice_errno(E2BIG, "Entry too big, skipped");
return 1;
} else if (r == -EAGAIN) {
return 0;
} else if (r < 0) {
log_debug_errno(r, "Closing connection: %m");
remove_source(server, fd);
return 0;
} else
return 1;
}
static int dispatch_raw_source_until_block(sd_event_source *event,
void *userdata) {
RemoteSource *source = userdata;
int r;
/* Make sure event stays around even if source is destroyed */
sd_event_source_ref(event);
r = handle_raw_source(event, source->fd, EPOLLIN, server);
if (r != 1)
/* No more data for now */
sd_event_source_set_enabled(event, SD_EVENT_OFF);
sd_event_source_unref(event);
return r;
}
static int dispatch_raw_source_event(sd_event_source *event,
int fd,
uint32_t revents,
void *userdata) {
RemoteSource *source = userdata;
int r;
assert(source->event);
assert(source->buffer_event);
r = handle_raw_source(event, fd, EPOLLIN, server);
if (r == 1)
/* Might have more data. We need to rerun the handler
* until we are sure the buffer is exhausted. */
sd_event_source_set_enabled(source->buffer_event, SD_EVENT_ON);
return r;
}
static int dispatch_blocking_source_event(sd_event_source *event,
void *userdata) {
RemoteSource *source = userdata;
return handle_raw_source(event, source->fd, EPOLLIN, server);
}
static int accept_connection(const char* type, int fd,
SocketAddress *addr, char **hostname) {
int fd2, r;
log_debug("Accepting new %s connection on fd:%d", type, fd);
fd2 = accept4(fd, &addr->sockaddr.sa, &addr->size, SOCK_NONBLOCK|SOCK_CLOEXEC);
if (fd2 < 0)
return log_error_errno(errno, "accept() on fd:%d failed: %m", fd);
switch(socket_address_family(addr)) {
case AF_INET:
case AF_INET6: {
_cleanup_free_ char *a = NULL;
char *b;
r = socket_address_print(addr, &a);
if (r < 0) {
log_error_errno(r, "socket_address_print(): %m");
close(fd2);
return r;
}
r = socknameinfo_pretty(&addr->sockaddr, addr->size, &b);
if (r < 0) {
close(fd2);
return r;
}
log_debug("Accepted %s %s connection from %s",
type,
socket_address_family(addr) == AF_INET ? "IP" : "IPv6",
a);
*hostname = b;
return fd2;
};
default:
log_error("Rejected %s connection with unsupported family %d",
type, socket_address_family(addr));
close(fd2);
return -EINVAL;
}
}
static int dispatch_raw_connection_event(sd_event_source *event,
int fd,
uint32_t revents,
void *userdata) {
RemoteServer *s = userdata;
int fd2;
SocketAddress addr = {
.size = sizeof(union sockaddr_union),
.type = SOCK_STREAM,
};
char *hostname = NULL;
fd2 = accept_connection("raw", fd, &addr, &hostname);
if (fd2 < 0)
return fd2;
return add_source(s, fd2, hostname, true);
}
/**********************************************************************
**********************************************************************
**********************************************************************/
static const char* const journal_write_split_mode_table[_JOURNAL_WRITE_SPLIT_MAX] = {
[JOURNAL_WRITE_SPLIT_NONE] = "none",
[JOURNAL_WRITE_SPLIT_HOST] = "host",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP(journal_write_split_mode, JournalWriteSplitMode);
static DEFINE_CONFIG_PARSE_ENUM(config_parse_write_split_mode,
journal_write_split_mode,
JournalWriteSplitMode,
"Failed to parse split mode setting");
static int parse_config(void) {
const ConfigTableItem items[] = {
{ "Remote", "SplitMode", config_parse_write_split_mode, 0, &arg_split_mode },
{ "Remote", "ServerKeyFile", config_parse_path, 0, &arg_key },
{ "Remote", "ServerCertificateFile", config_parse_path, 0, &arg_cert },
{ "Remote", "TrustedCertificateFile", config_parse_path, 0, &arg_trust },
{}};
return config_parse_many(PKGSYSCONFDIR "/journal-remote.conf",
CONF_DIRS_NULSTR("systemd/journal-remote.conf"),
"Remote\0", config_item_table_lookup, items,
false, NULL);
}
static void help(void) {
printf("%s [OPTIONS...] {FILE|-}...\n\n"
"Write external journal events to journal file(s).\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --url=URL Read events from systemd-journal-gatewayd at URL\n"
" --getter=COMMAND Read events from the output of COMMAND\n"
" --listen-raw=ADDR Listen for connections at ADDR\n"
" --listen-http=ADDR Listen for HTTP connections at ADDR\n"
" --listen-https=ADDR Listen for HTTPS connections at ADDR\n"
" -o --output=FILE|DIR Write output to FILE or DIR/external-*.journal\n"
" --compress[=BOOL] XZ-compress the output journal (default: yes)\n"
" --seal[=BOOL] Use event sealing (default: no)\n"
" --key=FILENAME SSL key in PEM format (default:\n"
" \"" PRIV_KEY_FILE "\")\n"
" --cert=FILENAME SSL certificate in PEM format (default:\n"
" \"" CERT_FILE "\")\n"
" --trust=FILENAME|all SSL CA certificate or disable checking (default:\n"
" \"" TRUST_FILE "\")\n"
" --gnutls-log=CATEGORY...\n"
" Specify a list of gnutls logging categories\n"
" --split-mode=none|host How many output files to create\n"
"\n"
"Note: file descriptors from sd_listen_fds() will be consumed, too.\n"
, program_invocation_short_name);
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
ARG_URL,
ARG_LISTEN_RAW,
ARG_LISTEN_HTTP,
ARG_LISTEN_HTTPS,
ARG_GETTER,
ARG_SPLIT_MODE,
ARG_COMPRESS,
ARG_SEAL,
ARG_KEY,
ARG_CERT,
ARG_TRUST,
ARG_GNUTLS_LOG,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "url", required_argument, NULL, ARG_URL },
{ "getter", required_argument, NULL, ARG_GETTER },
{ "listen-raw", required_argument, NULL, ARG_LISTEN_RAW },
{ "listen-http", required_argument, NULL, ARG_LISTEN_HTTP },
{ "listen-https", required_argument, NULL, ARG_LISTEN_HTTPS },
{ "output", required_argument, NULL, 'o' },
{ "split-mode", required_argument, NULL, ARG_SPLIT_MODE },
{ "compress", optional_argument, NULL, ARG_COMPRESS },
{ "seal", optional_argument, NULL, ARG_SEAL },
{ "key", required_argument, NULL, ARG_KEY },
{ "cert", required_argument, NULL, ARG_CERT },
{ "trust", required_argument, NULL, ARG_TRUST },
{ "gnutls-log", required_argument, NULL, ARG_GNUTLS_LOG },
{}
};
int c, r;
bool type_a, type_b;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "ho:", options, NULL)) >= 0)
switch(c) {
case 'h':
help();
return 0 /* done */;
case ARG_VERSION:
puts(PACKAGE_STRING);
puts(SYSTEMD_FEATURES);
return 0 /* done */;
case ARG_URL:
if (arg_url) {
log_error("cannot currently set more than one --url");
return -EINVAL;
}
arg_url = optarg;
break;
case ARG_GETTER:
if (arg_getter) {
log_error("cannot currently use --getter more than once");
return -EINVAL;
}
arg_getter = optarg;
break;
case ARG_LISTEN_RAW:
if (arg_listen_raw) {
log_error("cannot currently use --listen-raw more than once");
return -EINVAL;
}
arg_listen_raw = optarg;
break;
case ARG_LISTEN_HTTP:
if (arg_listen_http || http_socket >= 0) {
log_error("cannot currently use --listen-http more than once");
return -EINVAL;
}
r = negative_fd(optarg);
if (r >= 0)
http_socket = r;
else
arg_listen_http = optarg;
break;
case ARG_LISTEN_HTTPS:
if (arg_listen_https || https_socket >= 0) {
log_error("cannot currently use --listen-https more than once");
return -EINVAL;
}
r = negative_fd(optarg);
if (r >= 0)
https_socket = r;
else
arg_listen_https = optarg;
break;
case ARG_KEY:
if (arg_key) {
log_error("Key file specified twice");
return -EINVAL;
}
arg_key = strdup(optarg);
if (!arg_key)
return log_oom();
break;
case ARG_CERT:
if (arg_cert) {
log_error("Certificate file specified twice");
return -EINVAL;
}
arg_cert = strdup(optarg);
if (!arg_cert)
return log_oom();
break;
case ARG_TRUST:
if (arg_trust || arg_trust_all) {
log_error("Confusing trusted CA configuration");
return -EINVAL;
}
if (streq(optarg, "all"))
arg_trust_all = true;
else {
#ifdef HAVE_GNUTLS
arg_trust = strdup(optarg);
if (!arg_trust)
return log_oom();
#else
log_error("Option --trust is not available.");
return -EINVAL;
#endif
}
break;
case 'o':
if (arg_output) {
log_error("cannot use --output/-o more than once");
return -EINVAL;
}
arg_output = optarg;
break;
case ARG_SPLIT_MODE:
arg_split_mode = journal_write_split_mode_from_string(optarg);
if (arg_split_mode == _JOURNAL_WRITE_SPLIT_INVALID) {
log_error("Invalid split mode: %s", optarg);
return -EINVAL;
}
break;
case ARG_COMPRESS:
if (optarg) {
r = parse_boolean(optarg);
if (r < 0) {
log_error("Failed to parse --compress= parameter.");
return -EINVAL;
}
arg_compress = !!r;
} else
arg_compress = true;
break;
case ARG_SEAL:
if (optarg) {
r = parse_boolean(optarg);
if (r < 0) {
log_error("Failed to parse --seal= parameter.");
return -EINVAL;
}
arg_seal = !!r;
} else
arg_seal = true;
break;
case ARG_GNUTLS_LOG: {
#ifdef HAVE_GNUTLS
const char *word, *state;
size_t size;
FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
char *cat;
cat = strndup(word, size);
if (!cat)
return log_oom();
if (strv_consume(&arg_gnutls_log, cat) < 0)
return log_oom();
}
break;
#else
log_error("Option --gnutls-log is not available.");
return -EINVAL;
#endif
}
case '?':
return -EINVAL;
default:
assert_not_reached("Unknown option code.");
}
if (optind < argc)
arg_files = argv + optind;
type_a = arg_getter || !strv_isempty(arg_files);
type_b = arg_url
|| arg_listen_raw
|| arg_listen_http || arg_listen_https
|| sd_listen_fds(false) > 0;
if (type_a && type_b) {
log_error("Cannot use file input or --getter with "
"--arg-listen-... or socket activation.");
return -EINVAL;
}
if (type_a) {
if (!arg_output) {
log_error("Option --output must be specified with file input or --getter.");
return -EINVAL;
}
arg_split_mode = JOURNAL_WRITE_SPLIT_NONE;
}
if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE
&& arg_output && is_dir(arg_output, true) > 0) {
log_error("For SplitMode=none, output must be a file.");
return -EINVAL;
}
if (arg_split_mode == JOURNAL_WRITE_SPLIT_HOST
&& arg_output && is_dir(arg_output, true) <= 0) {
log_error("For SplitMode=host, output must be a directory.");
return -EINVAL;
}
log_debug("Full config: SplitMode=%s Key=%s Cert=%s Trust=%s",
journal_write_split_mode_to_string(arg_split_mode),
strna(arg_key),
strna(arg_cert),
strna(arg_trust));
return 1 /* work to do */;
}
static int load_certificates(char **key, char **cert, char **trust) {
int r;
r = read_full_file(arg_key ?: PRIV_KEY_FILE, key, NULL);
if (r < 0)
return log_error_errno(r, "Failed to read key from file '%s': %m",
arg_key ?: PRIV_KEY_FILE);
r = read_full_file(arg_cert ?: CERT_FILE, cert, NULL);
if (r < 0)
return log_error_errno(r, "Failed to read certificate from file '%s': %m",
arg_cert ?: CERT_FILE);
if (arg_trust_all)
log_info("Certificate checking disabled.");
else {
r = read_full_file(arg_trust ?: TRUST_FILE, trust, NULL);
if (r < 0)
return log_error_errno(r, "Failed to read CA certificate file '%s': %m",
arg_trust ?: TRUST_FILE);
}
return 0;
}
int main(int argc, char **argv) {
RemoteServer s = {};
int r;
_cleanup_free_ char *key = NULL, *cert = NULL, *trust = NULL;
log_show_color(true);
log_parse_environment();
r = parse_config();
if (r < 0)
return EXIT_FAILURE;
r = parse_argv(argc, argv);
if (r <= 0)
return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
if (arg_listen_http || arg_listen_https) {
r = setup_gnutls_logger(arg_gnutls_log);
if (r < 0)
return EXIT_FAILURE;
}
if (arg_listen_https || https_socket >= 0)
if (load_certificates(&key, &cert, &trust) < 0)
return EXIT_FAILURE;
if (remoteserver_init(&s, key, cert, trust) < 0)
return EXIT_FAILURE;
r = sd_event_set_watchdog(s.events, true);
if (r < 0)
log_error_errno(r, "Failed to enable watchdog: %m");
else
log_debug("Watchdog is %s.", r > 0 ? "enabled" : "disabled");
log_debug("%s running as pid "PID_FMT,
program_invocation_short_name, getpid());
sd_notify(false,
"READY=1\n"
"STATUS=Processing requests...");
while (s.active) {
r = sd_event_get_state(s.events);
if (r < 0)
break;
if (r == SD_EVENT_FINISHED)
break;
r = sd_event_run(s.events, -1);
if (r < 0) {
log_error_errno(r, "Failed to run event loop: %m");
break;
}
}
sd_notifyf(false,
"STOPPING=1\n"
"STATUS=Shutting down after writing %" PRIu64 " entries...", s.event_count);
log_info("Finishing after writing %" PRIu64 " entries", s.event_count);
server_destroy(&s);
free(arg_key);
free(arg_cert);
free(arg_trust);
return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}