journal-remote.c revision 5c879495eab608bf9b6e7bec1020d916a0503b6e
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/***
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright 2012 Zbigniew Jędrzejewski-Szmek
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering***/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <errno.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <fcntl.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <inttypes.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <stdio.h>
39d8db043b599a7382f94bfc904d5e108af438bdLennart Poettering#include <stdlib.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <string.h>
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering#include <sys/prctl.h>
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering#include <sys/socket.h>
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering#include <sys/stat.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <sys/types.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <unistd.h>
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering#include <getopt.h>
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering#include "sd-daemon.h"
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering#include "sd-event.h"
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering#include "journal-file.h"
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering#include "journald-native.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "socket-util.h"
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering#include "mkdir.h"
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering#include "build.h"
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering#include "macro.h"
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering#include "strv.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "fileio.h"
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering#include "microhttpd-util.h"
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#ifdef HAVE_GNUTLS
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering#include <gnutls/gnutls.h>
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering#endif
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering#include "journal-remote-parse.h"
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering#include "journal-remote-write.h"
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
818f766b12e025683cf4fed12b3da2a025bb0b31Lennart Poettering#define REMOTE_JOURNAL_PATH "/var/log/journal/" SD_ID128_FORMAT_STR "/remote-%s.journal"
818f766b12e025683cf4fed12b3da2a025bb0b31Lennart Poettering
818f766b12e025683cf4fed12b3da2a025bb0b31Lennart Poetteringstatic char* arg_output = NULL;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poetteringstatic char* arg_url = NULL;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poetteringstatic char* arg_getter = NULL;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poetteringstatic char* arg_listen_raw = NULL;
818f766b12e025683cf4fed12b3da2a025bb0b31Lennart Poetteringstatic char* arg_listen_http = NULL;
818f766b12e025683cf4fed12b3da2a025bb0b31Lennart Poetteringstatic char* arg_listen_https = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic char** arg_files = NULL;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poetteringstatic int arg_compress = true;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int arg_seal = false;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int http_socket = -1, https_socket = -1;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic char** arg_gnutls_log = NULL;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic char *key_pem = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic char *cert_pem = NULL;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poetteringstatic char *trust_pem = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering/**********************************************************************
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering **********************************************************************
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering **********************************************************************/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int spawn_child(const char* child, char** argv) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int fd[2];
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pid_t parent_pid, child_pid;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (pipe(fd) < 0) {
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering log_error("Failed to create pager pipe: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -errno;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering parent_pid = getpid();
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering child_pid = fork();
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering if (child_pid < 0) {
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering r = -errno;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering log_error("Failed to fork: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering safe_close_pair(fd);
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering return r;
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering }
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering /* In the child */
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering if (child_pid == 0) {
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering r = dup2(fd[1], STDOUT_FILENO);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering if (r < 0) {
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering log_error("Failed to dup pipe to stdout: %m");
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering _exit(EXIT_FAILURE);
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering safe_close_pair(fd);
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering /* Make sure the child goes away when the parent dies */
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering _exit(EXIT_FAILURE);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering /* Check whether our parent died before we were able
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering * to set the death signal */
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering if (getppid() != parent_pid)
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering _exit(EXIT_SUCCESS);
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering execvp(child, argv);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering log_error("Failed to exec child %s: %m", child);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering _exit(EXIT_FAILURE);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering r = close(fd[1]);
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering if (r < 0)
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering log_warning("Failed to close write end of pipe: %m");
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering return fd[0];
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering}
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poetteringstatic int spawn_curl(char* url) {
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering char **argv = STRV_MAKE("curl",
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering "-HAccept: application/vnd.fdo.journal",
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering "--silent",
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering "--show-error",
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering url);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering int r;
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering r = spawn_child("curl", argv);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering log_error("Failed to spawn curl: %m");
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int spawn_getter(char *getter, char *url) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering int r;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering _cleanup_strv_free_ char **words = NULL;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering assert(getter);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering words = strv_split_quoted(getter);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering if (!words)
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering return log_oom();
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = spawn_child(words[0], words);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering if (r < 0)
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering log_error("Failed to spawn getter %s: %m", getter);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poetteringstatic int open_output(Writer *s, const char* url) {
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering _cleanup_free_ char *name, *output = NULL;
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering char *c;
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering int r;
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering assert(url);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering name = strdup(url);
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering if (!name)
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering return log_oom();
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering for(c = name; *c; c++) {
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering if (*c == '/' || *c == ':' || *c == ' ')
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering *c = '~';
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering else if (*c == '?') {
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering *c = '\0';
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering }
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering if (!arg_output) {
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering sd_id128_t machine;
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering r = sd_id128_get_machine(&machine);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering log_error("failed to determine machine ID128: %s", strerror(-r));
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering return r;
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering }
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering r = asprintf(&output, REMOTE_JOURNAL_PATH,
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering SD_ID128_FORMAT_VAL(machine), name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering return log_oom();
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering } else {
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering r = is_dir(arg_output, true);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering if (r > 0) {
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering r = asprintf(&output,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "%s/remote-%s.journal", arg_output, name);
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering if (r < 0)
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering return log_oom();
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering } else {
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering output = strdup(arg_output);
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering if (!output)
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering return log_oom();
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering }
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = journal_file_open_reliably(output,
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering O_RDWR|O_CREAT, 0640,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering arg_compress, arg_seal,
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering &s->metrics,
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering s->mmap,
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering NULL, &s->journal);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r < 0)
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering log_error("Failed to open output journal %s: %s",
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering arg_output, strerror(-r));
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering else
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering log_info("Opened output file %s", s->journal->path);
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering return r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering/**********************************************************************
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering **********************************************************************
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering **********************************************************************/
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poetteringtypedef struct MHDDaemonWrapper {
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering uint64_t fd;
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering struct MHD_Daemon *daemon;
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering sd_event_source *event;
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering} MHDDaemonWrapper;
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poetteringtypedef struct RemoteServer {
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering RemoteSource **sources;
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering size_t sources_size;
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering size_t active;
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering sd_event *events;
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering sd_event_source *sigterm_event, *sigint_event, *listen_event;
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering Writer writer;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering Hashmap *daemons;
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering} RemoteServer;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/* This should go away as soon as µhttpd allows state to be passed around. */
ad867662936a4c7ab2c7116d804c272338801231Lennart Poetteringstatic RemoteServer *server;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poetteringstatic int dispatch_raw_source_event(sd_event_source *event,
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering int fd,
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering uint32_t revents,
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering void *userdata);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic int dispatch_raw_connection_event(sd_event_source *event,
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering int fd,
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering uint32_t revents,
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering void *userdata);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poetteringstatic int dispatch_http_event(sd_event_source *event,
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering int fd,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering uint32_t revents,
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering void *userdata);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poetteringstatic int get_source_for_fd(RemoteServer *s, int fd, RemoteSource **source) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering assert(fd >= 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(source);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!GREEDY_REALLOC0(s->sources, s->sources_size, fd + 1))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return log_oom();
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (s->sources[fd] == NULL) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering s->sources[fd] = new0(RemoteSource, 1);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!s->sources[fd])
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering return log_oom();
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering s->sources[fd]->fd = -1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering s->active++;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *source = s->sources[fd];
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int remove_source(RemoteServer *s, int fd) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering RemoteSource *source;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(s);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering assert(fd >= 0 && fd < (ssize_t) s->sources_size);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
7b9f7afcc04e80b77a2567b0750aa2cd03c1a1cdLennart Poettering source = s->sources[fd];
7b9f7afcc04e80b77a2567b0750aa2cd03c1a1cdLennart Poettering if (source) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering source_free(source);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering s->sources[fd] = NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering s->active--;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering close(fd);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return 0;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic int add_source(RemoteServer *s, int fd, const char* name) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering RemoteSource *source = NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering _cleanup_free_ char *realname = NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering int r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(s);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(fd >= 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (name) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering realname = strdup(name);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (!realname)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return log_oom();
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering } else {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = asprintf(&realname, "fd:%d", fd);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return log_oom();
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_debug("Creating source for fd:%d (%s)", fd, realname);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = get_source_for_fd(s, fd, &source);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to create source for fd:%d (%s)", fd, realname);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(source);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(source->fd < 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering source->fd = fd;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
82bd6dddc4a363a9c3c6f41eb46eb171a80dca27Lennart Poettering r = sd_event_add_io(s->events, &source->event,
82bd6dddc4a363a9c3c6f41eb46eb171a80dca27Lennart Poettering fd, EPOLLIN, dispatch_raw_source_event, s);
82bd6dddc4a363a9c3c6f41eb46eb171a80dca27Lennart Poettering if (r < 0) {
82bd6dddc4a363a9c3c6f41eb46eb171a80dca27Lennart Poettering log_error("Failed to register event source for fd:%d: %s",
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering fd, strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto error;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering return 1; /* work to do */
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering error:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering remove_source(s, fd);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int add_raw_socket(RemoteServer *s, int fd) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering r = sd_event_add_io(s->events, &s->listen_event, fd, EPOLLIN,
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering dispatch_raw_connection_event, s);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r < 0) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering close(fd);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering s->active ++;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering return 0;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering}
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int setup_raw_socket(RemoteServer *s, const char *address) {
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering int fd;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering fd = make_socket_fd(LOG_INFO, address, SOCK_STREAM | SOCK_CLOEXEC);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (fd < 0)
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering return fd;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering return add_raw_socket(s, fd);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering/**********************************************************************
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering **********************************************************************
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering **********************************************************************/
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poetteringstatic RemoteSource *request_meta(void **connection_cls) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering RemoteSource *source;
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering assert(connection_cls);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (*connection_cls)
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering return *connection_cls;
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering source = new0(RemoteSource, 1);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!source)
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering return NULL;
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering source->fd = -1;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_debug("Added RemoteSource as connection metadata %p", source);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering *connection_cls = source;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return source;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poetteringstatic void request_meta_free(void *cls,
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering struct MHD_Connection *connection,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering void **connection_cls,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering enum MHD_RequestTerminationCode toe) {
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering RemoteSource *s;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering assert(connection_cls);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering s = *connection_cls;
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_debug("Cleaning up connection metadata %p", s);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering source_free(s);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering *connection_cls = NULL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering}
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poetteringstatic int process_http_upload(
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct MHD_Connection *connection,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *upload_data,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering size_t *upload_data_size,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering RemoteSource *source) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering bool finished = false;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering int r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(source);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_debug("request_handler_upload: connection %p, %zu bytes",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering connection, *upload_data_size);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (*upload_data_size) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_info("Received %zu bytes", *upload_data_size);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = push_data(source, upload_data, *upload_data_size);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to store received data of size %zu: %s",
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering *upload_data_size, strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return mhd_respond_oom(connection);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *upload_data_size = 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering finished = true;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering while (true) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = process_source(source, &server->writer, arg_compress, arg_seal);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r == -E2BIG)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Entry too big, skipped");
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering else if (r == -EAGAIN || r == -EWOULDBLOCK)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else if (r < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Failed to process data for connection %p", connection);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return mhd_respondf(connection, MHD_HTTP_UNPROCESSABLE_ENTITY,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "Processing failed: %s", strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (!finished)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return MHD_YES;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering /* The upload is finished */
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (source_non_empty(source)) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering log_warning("EOF reached with incomplete data");
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return mhd_respond(connection, MHD_HTTP_EXPECTATION_FAILED,
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering "Trailing data not processed.");
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return mhd_respond(connection, MHD_HTTP_ACCEPTED, "OK.\n");
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering};
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic int request_handler(
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering void *cls,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct MHD_Connection *connection,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *url,
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering const char *method,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *version,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *upload_data,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering size_t *upload_data_size,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering void **connection_cls) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *header;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r ,code;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
82bd6dddc4a363a9c3c6f41eb46eb171a80dca27Lennart Poettering assert(connection);
82bd6dddc4a363a9c3c6f41eb46eb171a80dca27Lennart Poettering assert(connection_cls);
82bd6dddc4a363a9c3c6f41eb46eb171a80dca27Lennart Poettering assert(url);
82bd6dddc4a363a9c3c6f41eb46eb171a80dca27Lennart Poettering assert(method);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_debug("Handling a connection %s %s %s", method, url, version);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (*connection_cls)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return process_http_upload(connection,
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering upload_data, upload_data_size,
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering *connection_cls);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!streq(method, "POST"))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return mhd_respond(connection, MHD_HTTP_METHOD_NOT_ACCEPTABLE,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "Unsupported method.\n");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!streq(url, "/upload"))
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return mhd_respond(connection, MHD_HTTP_NOT_FOUND,
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering "Not found.\n");
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering header = MHD_lookup_connection_value(connection,
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering MHD_HEADER_KIND, "Content-Type");
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!header || !streq(header, "application/vnd.fdo.journal"))
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return mhd_respond(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE,
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering "Content-Type: application/vnd.fdo.journal"
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering " is required.\n");
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (trust_pem) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = check_permissions(connection, &code);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return code;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!request_meta(connection_cls))
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return respond_oom(connection);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return MHD_YES;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering}
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poetteringstatic int setup_microhttpd_server(RemoteServer *s, int fd, bool https) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering struct MHD_OptionItem opts[] = {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering { MHD_OPTION_NOTIFY_COMPLETED, (intptr_t) request_meta_free},
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering { MHD_OPTION_EXTERNAL_LOGGER, (intptr_t) microhttpd_logger},
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering { MHD_OPTION_LISTEN_SOCKET, fd},
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering { MHD_OPTION_END},
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering { MHD_OPTION_END},
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering { MHD_OPTION_END},
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering { MHD_OPTION_END}};
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering int opts_pos = 3;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering int flags =
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering MHD_USE_DEBUG |
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering MHD_USE_PEDANTIC_CHECKS |
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering MHD_USE_EPOLL_LINUX_ONLY |
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering MHD_USE_DUAL_STACK;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering const union MHD_DaemonInfo *info;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering int r, epoll_fd;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering MHDDaemonWrapper *d;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering assert(fd >= 0);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = fd_nonblock(fd, true);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering log_error("Failed to make fd:%d nonblocking: %s", fd, strerror(-r));
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return r;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (https) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering opts[opts_pos++] = (struct MHD_OptionItem)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering {MHD_OPTION_HTTPS_MEM_KEY, 0, key_pem};
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering opts[opts_pos++] = (struct MHD_OptionItem)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering {MHD_OPTION_HTTPS_MEM_CERT, 0, cert_pem};
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering flags |= MHD_USE_SSL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (trust_pem)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering opts[opts_pos++] = (struct MHD_OptionItem)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering {MHD_OPTION_HTTPS_MEM_TRUST, 0, trust_pem};
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering d = new(MHDDaemonWrapper, 1);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!d)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return log_oom();
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering d->fd = (uint64_t) fd;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering d->daemon = MHD_start_daemon(flags, 0,
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering NULL, NULL,
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering request_handler, NULL,
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering MHD_OPTION_ARRAY, opts,
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering MHD_OPTION_END);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!d->daemon) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering log_error("Failed to start µhttp daemon");
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = -EINVAL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering goto error;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering log_debug("Started MHD %s daemon on fd:%d (wrapper @ %p)",
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering https ? "HTTPS" : "HTTP", fd, d);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering info = MHD_get_daemon_info(d->daemon, MHD_DAEMON_INFO_EPOLL_FD_LINUX_ONLY);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!info) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering log_error("µhttp returned NULL daemon info");
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = -ENOTSUP;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering goto error;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering epoll_fd = info->listen_fd;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (epoll_fd < 0) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering log_error("µhttp epoll fd is invalid");
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = -EUCLEAN;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering goto error;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = sd_event_add_io(s->events, &d->event,
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering epoll_fd, EPOLLIN, dispatch_http_event, d);
7b9f7afcc04e80b77a2567b0750aa2cd03c1a1cdLennart Poettering if (r < 0) {
7b9f7afcc04e80b77a2567b0750aa2cd03c1a1cdLennart Poettering log_error("Failed to add event callback: %s", strerror(-r));
7b9f7afcc04e80b77a2567b0750aa2cd03c1a1cdLennart Poettering goto error;
7b9f7afcc04e80b77a2567b0750aa2cd03c1a1cdLennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = hashmap_ensure_allocated(&s->daemons, uint64_hash_func, uint64_compare_func);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering log_oom();
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering goto error;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = hashmap_put(s->daemons, &d->fd, d);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering log_error("Failed to add daemon to hashmap: %s", strerror(-r));
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering goto error;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering s->active ++;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return 0;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poetteringerror:
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering MHD_stop_daemon(d->daemon);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering free(d->daemon);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering free(d);
82bd6dddc4a363a9c3c6f41eb46eb171a80dca27Lennart Poettering return r;
82bd6dddc4a363a9c3c6f41eb46eb171a80dca27Lennart Poettering}
82bd6dddc4a363a9c3c6f41eb46eb171a80dca27Lennart Poettering
82bd6dddc4a363a9c3c6f41eb46eb171a80dca27Lennart Poetteringstatic int setup_microhttpd_socket(RemoteServer *s,
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering const char *address,
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering bool https) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering int fd;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering fd = make_socket_fd(LOG_INFO, address, SOCK_STREAM | SOCK_CLOEXEC);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (fd < 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return fd;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return setup_microhttpd_server(s, fd, https);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering}
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poetteringstatic int dispatch_http_event(sd_event_source *event,
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering int fd,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering uint32_t revents,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering void *userdata) {
878cd63db2d6cfc00ae4d68355a2d5402cd9f24fLennart Poettering MHDDaemonWrapper *d = userdata;
878cd63db2d6cfc00ae4d68355a2d5402cd9f24fLennart Poettering int r;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(d);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_info("%s", __func__);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = MHD_run(d->daemon);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r == MHD_NO) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("MHD_run failed!");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering // XXX: unregister daemon
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -EINVAL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 1; /* work to do */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/**********************************************************************
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering **********************************************************************
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering **********************************************************************/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int dispatch_sigterm(sd_event_source *event,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const struct signalfd_siginfo *si,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering RemoteServer *s = userdata;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(s);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_received_signal(LOG_INFO, si);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_event_exit(s->events, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int setup_signals(RemoteServer *s) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sigset_t mask;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(s);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert_se(sigemptyset(&mask) == 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sigset_add_many(&mask, SIGINT, SIGTERM, -1);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
4d1cf1e229c9bdbc44778c0863eaad918f5724e7Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_event_add_signal(s->events, &s->sigterm_event, SIGTERM, dispatch_sigterm, s);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_event_add_signal(s->events, &s->sigint_event, SIGINT, dispatch_sigterm, s);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int fd_fd(const char *spec) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int fd, r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = safe_atoi(spec, &fd);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (fd >= 0)
return -ENOENT;
return -fd;
}
static int remoteserver_init(RemoteServer *s) {
int r, n, fd;
const char *output_name = NULL;
char **file;
assert(s);
sd_event_default(&s->events);
setup_signals(s);
assert(server == NULL);
server = s;
n = sd_listen_fds(true);
if (n < 0) {
log_error("Failed to read listening file descriptors from environment: %s",
strerror(-n));
return n;
} else
log_info("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, false)) {
log_info("Received a listening socket (fd:%d)", fd);
if (fd == http_socket)
r = setup_microhttpd_server(s, fd, false);
else if (fd == https_socket)
r = setup_microhttpd_server(s, fd, true);
else
r = add_raw_socket(s, fd);
} else if (sd_is_socket(fd, AF_UNSPEC, 0, true)) {
log_info("Received a connection socket (fd:%d)", fd);
r = add_source(s, fd, NULL);
} else {
log_error("Unknown socket passed on fd:%d", fd);
return -EINVAL;
}
if(r < 0) {
log_error("Failed to register socket (fd:%d): %s",
fd, strerror(-r));
return r;
}
output_name = "socket";
}
if (arg_url) {
_cleanup_free_ char *url = NULL;
_cleanup_strv_free_ char **urlv = strv_new(arg_url, "/entries", NULL);
if (!urlv)
return log_oom();
url = strv_join(urlv, "");
if (!url)
return log_oom();
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;
r = add_source(s, fd, arg_url);
if (r < 0)
return r;
output_name = arg_url;
}
if (arg_listen_raw) {
log_info("Listening on a socket...");
r = setup_raw_socket(s, arg_listen_raw);
if (r < 0)
return r;
output_name = arg_listen_raw;
}
if (arg_listen_http) {
r = setup_microhttpd_socket(s, arg_listen_http, false);
if (r < 0)
return r;
output_name = arg_listen_http;
}
if (arg_listen_https) {
r = setup_microhttpd_socket(s, arg_listen_https, true);
if (r < 0)
return r;
output_name = arg_listen_https;
}
STRV_FOREACH(file, arg_files) {
if (streq(*file, "-")) {
log_info("Reading standard input...");
fd = STDIN_FILENO;
output_name = "stdin";
} else {
log_info("Reading file %s...", *file);
fd = open(*file, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
if (fd < 0) {
log_error("Failed to open %s: %m", *file);
return -errno;
}
output_name = *file;
}
r = add_source(s, fd, output_name);
if (r < 0)
return r;
}
if (s->active == 0) {
log_error("Zarro sources specified");
return -EINVAL;
}
if (!!n + !!arg_url + !!arg_listen_raw + !!arg_files)
output_name = "multiple";
r = writer_init(&s->writer);
if (r < 0)
return r;
r = open_output(&s->writer, output_name);
return r;
}
static int server_destroy(RemoteServer *s) {
int r;
size_t i;
MHDDaemonWrapper *d;
r = writer_close(&s->writer);
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);
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... */
return r;
}
/**********************************************************************
**********************************************************************
**********************************************************************/
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, &s->writer, arg_compress, arg_seal);
if (source->state == STATE_EOF) {
log_info("EOF reached with source fd:%d (%s)",
source->fd, source->name);
if (source_non_empty(source))
log_warning("EOF reached with incomplete data");
remove_source(s, source->fd);
log_info("%zd active source remaining", s->active);
} else if (r == -E2BIG) {
log_error("Entry too big, skipped");
r = 1;
}
return r;
}
static int accept_connection(const char* type, int fd, SocketAddress *addr) {
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) {
log_error("accept() on fd:%d failed: %m", fd);
return -errno;
}
switch(socket_address_family(addr)) {
case AF_INET:
case AF_INET6: {
char* _cleanup_free_ a = NULL;
r = socket_address_print(addr, &a);
if (r < 0) {
log_error("socket_address_print(): %s", strerror(-r));
close(fd2);
return r;
}
log_info("Accepted %s %s connection from %s",
type,
socket_address_family(addr) == AF_INET ? "IP" : "IPv6",
a);
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,
};
fd2 = accept_connection("raw", fd, &addr);
if (fd2 < 0)
return fd2;
return add_source(s, fd2, NULL);
}
/**********************************************************************
**********************************************************************
**********************************************************************/
static void help(void) {
printf("%s [OPTIONS...] {FILE|-}...\n\n"
"Write external journal events to a journal file.\n\n"
"Options:\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"
" --[no-]compress Use XZ-compression in the output journal (default: yes)\n"
" --[no-]seal Use Event sealing in the output journal (default: no)\n"
" --key=FILENAME Specify key in PEM format\n"
" --cert=FILENAME Specify certificate in PEM format\n"
" --trust=FILENAME Specify CA certificate in PEM format\n"
" --gnutls-log=CATEGORY...\n"
" Specify a list of gnutls logging categories\n"
" -h --help Show this help and exit\n"
" --version Print version string and exit\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_COMPRESS,
ARG_NO_COMPRESS,
ARG_SEAL,
ARG_NO_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' },
{ "compress", no_argument, NULL, ARG_COMPRESS },
{ "no-compress", no_argument, NULL, ARG_NO_COMPRESS },
{ "seal", no_argument, NULL, ARG_SEAL },
{ "no-seal", no_argument, NULL, ARG_NO_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;
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 = fd_fd(optarg);
if (r >= 0)
http_socket = r;
else if (r == -ENOENT)
arg_listen_http = optarg;
else {
log_error("Invalid port/fd specification %s: %s",
optarg, strerror(-r));
return -EINVAL;
}
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 = fd_fd(optarg);
if (r >= 0)
https_socket = r;
else if (r == -ENOENT)
arg_listen_https = optarg;
else {
log_error("Invalid port/fd specification %s: %s",
optarg, strerror(-r));
return -EINVAL;
}
break;
case ARG_KEY:
if (key_pem) {
log_error("Key file specified twice");
return -EINVAL;
}
r = read_full_file(optarg, &key_pem, NULL);
if (r < 0) {
log_error("Failed to read key file: %s", strerror(-r));
return r;
}
assert(key_pem);
break;
case ARG_CERT:
if (cert_pem) {
log_error("Certificate file specified twice");
return -EINVAL;
}
r = read_full_file(optarg, &cert_pem, NULL);
if (r < 0) {
log_error("Failed to read certificate file: %s", strerror(-r));
return r;
}
assert(cert_pem);
break;
case ARG_TRUST:
#ifdef HAVE_GNUTLS
if (trust_pem) {
log_error("CA certificate file specified twice");
return -EINVAL;
}
r = read_full_file(optarg, &trust_pem, NULL);
if (r < 0) {
log_error("Failed to read CA certificate file: %s", strerror(-r));
return r;
}
assert(trust_pem);
break;
#else
log_error("Option --trust is not available.");
return -EINVAL;
#endif
case 'o':
if (arg_output) {
log_error("cannot use --output/-o more than once");
return -EINVAL;
}
arg_output = optarg;
break;
case ARG_COMPRESS:
arg_compress = true;
break;
case ARG_NO_COMPRESS:
arg_compress = false;
break;
case ARG_SEAL:
arg_seal = true;
break;
case ARG_NO_SEAL:
arg_seal = false;
break;
case ARG_GNUTLS_LOG: {
#ifdef HAVE_GNUTLS
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:
log_error("Unknown option code %c", c);
return -EINVAL;
}
if (arg_listen_https && !(key_pem && cert_pem)) {
log_error("Options --key and --cert must be used when https sources are specified");
return -EINVAL;
}
if (optind < argc)
arg_files = argv + optind;
return 1 /* work to do */;
}
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, r2;
log_show_color(true);
log_parse_environment();
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 (remoteserver_init(&s) < 0)
return EXIT_FAILURE;
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("Failed to run event loop: %s", strerror(-r));
break;
}
}
log_info("Finishing after writing %" PRIu64 " entries", s.writer.seqnum);
r2 = server_destroy(&s);
sd_notify(false, "STATUS=Shutting down...");
return r >= 0 && r2 >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}