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