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