summaryrefslogtreecommitdiffstats
path: root/src/journal-remote
diff options
context:
space:
mode:
Diffstat (limited to 'src/journal-remote')
-rw-r--r--src/journal-remote/fuzz-journal-remote.c2
-rw-r--r--src/journal-remote/journal-gatewayd.c207
-rw-r--r--src/journal-remote/journal-remote-main.c28
-rw-r--r--src/journal-remote/journal-remote.c15
-rw-r--r--src/journal-remote/journal-remote.h5
-rw-r--r--src/journal-remote/journal-upload-journal.c2
-rw-r--r--src/journal-remote/journal-upload.c28
-rw-r--r--src/journal-remote/journal-upload.h2
-rw-r--r--src/journal-remote/meson.build10
9 files changed, 197 insertions, 102 deletions
diff --git a/src/journal-remote/fuzz-journal-remote.c b/src/journal-remote/fuzz-journal-remote.c
index 557100b..774389d 100644
--- a/src/journal-remote/fuzz-journal-remote.c
+++ b/src/journal-remote/fuzz-journal-remote.c
@@ -67,7 +67,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
/* Out */
- r = sd_journal_open_files(&j, (const char**) STRV_MAKE(name), 0);
+ r = sd_journal_open_files(&j, (const char**) STRV_MAKE(name), SD_JOURNAL_ASSUME_IMMUTABLE);
if (r < 0) {
log_error_errno(r, "sd_journal_open_files([\"%s\"]) failed: %m", name);
assert_se(IN_SET(r, -ENOMEM, -EMFILE, -ENFILE, -ENODATA));
diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c
index aaa52c0..dd91f22 100644
--- a/src/journal-remote/journal-gatewayd.c
+++ b/src/journal-remote/journal-gatewayd.c
@@ -22,6 +22,8 @@
#include "fileio.h"
#include "glob-util.h"
#include "hostname-util.h"
+#include "journal-internal.h"
+#include "journal-remote.h"
#include "log.h"
#include "logs-show.h"
#include "main-func.h"
@@ -32,6 +34,7 @@
#include "pretty-print.h"
#include "sigbus.h"
#include "signal-util.h"
+#include "time-util.h"
#include "tmpfile-util.h"
#define JOURNAL_WAIT_TIMEOUT (10*USEC_PER_SEC)
@@ -55,9 +58,10 @@ typedef struct RequestMeta {
OutputMode mode;
char *cursor;
+ usec_t since, until;
int64_t n_skip;
uint64_t n_entries;
- bool n_entries_set;
+ bool n_entries_set, since_set, until_set;
FILE *tmp;
uint64_t delta, size;
@@ -212,6 +216,17 @@ static ssize_t request_reader_entries(
return MHD_CONTENT_READER_END_OF_STREAM;
}
+ if (m->until_set) {
+ usec_t usec;
+
+ r = sd_journal_get_realtime_usec(m->journal, &usec);
+ if (r < 0) {
+ log_error_errno(r, "Failed to determine timestamp: %m");
+ return MHD_CONTENT_READER_END_WITH_ERROR;
+ }
+ if (usec > m->until)
+ return MHD_CONTENT_READER_END_OF_STREAM;
+ }
pos -= m->size;
m->delta += m->size;
@@ -293,60 +308,59 @@ static int request_parse_accept(
return 0;
}
-static int request_parse_range(
+static int request_parse_range_skip_and_n_entries(
RequestMeta *m,
- struct MHD_Connection *connection) {
+ const char *colon) {
- const char *range, *colon, *colon2;
+ const char *p, *colon2;
int r;
- assert(m);
- assert(connection);
+ colon2 = strchr(colon + 1, ':');
+ if (colon2) {
+ _cleanup_free_ char *t = NULL;
- range = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Range");
- if (!range)
- return 0;
+ t = strndup(colon + 1, colon2 - colon - 1);
+ if (!t)
+ return -ENOMEM;
- if (!startswith(range, "entries="))
- return 0;
+ r = safe_atoi64(t, &m->n_skip);
+ if (r < 0)
+ return r;
+ }
- range += 8;
- range += strspn(range, WHITESPACE);
+ p = (colon2 ?: colon) + 1;
+ r = safe_atou64(p, &m->n_entries);
+ if (r < 0)
+ return r;
- colon = strchr(range, ':');
- if (!colon)
- m->cursor = strdup(range);
- else {
- const char *p;
+ if (m->n_entries <= 0)
+ return -EINVAL;
- colon2 = strchr(colon + 1, ':');
- if (colon2) {
- _cleanup_free_ char *t = NULL;
+ m->n_entries_set = true;
- t = strndup(colon + 1, colon2 - colon - 1);
- if (!t)
- return -ENOMEM;
+ return 0;
+}
- r = safe_atoi64(t, &m->n_skip);
- if (r < 0)
- return r;
- }
+static int request_parse_range_entries(
+ RequestMeta *m,
+ const char *entries_request) {
- p = (colon2 ?: colon) + 1;
- if (*p) {
- r = safe_atou64(p, &m->n_entries);
- if (r < 0)
- return r;
+ const char *colon;
+ int r;
- if (m->n_entries <= 0)
- return -EINVAL;
+ assert(m);
+ assert(entries_request);
- m->n_entries_set = true;
- }
+ colon = strchr(entries_request, ':');
+ if (!colon)
+ m->cursor = strdup(entries_request);
+ else {
+ r = request_parse_range_skip_and_n_entries(m, colon);
+ if (r < 0)
+ return r;
- m->cursor = strndup(range, colon - range);
+ m->cursor = strndup(entries_request, colon - entries_request);
}
-
if (!m->cursor)
return -ENOMEM;
@@ -357,6 +371,93 @@ static int request_parse_range(
return 0;
}
+static int request_parse_range_time(
+ RequestMeta *m,
+ const char *time_request) {
+
+ _cleanup_free_ char *until = NULL;
+ const char *colon;
+ int r;
+
+ assert(m);
+ assert(time_request);
+
+ colon = strchr(time_request, ':');
+ if (!colon)
+ return -EINVAL;
+
+ if (colon - time_request > 0) {
+ _cleanup_free_ char *t = NULL;
+
+ t = strndup(time_request, colon - time_request);
+ if (!t)
+ return -ENOMEM;
+
+ r = parse_sec(t, &m->since);
+ if (r < 0)
+ return r;
+
+ m->since_set = true;
+ }
+
+ time_request = colon + 1;
+ colon = strchr(time_request, ':');
+ if (!colon)
+ until = strdup(time_request);
+ else {
+ r = request_parse_range_skip_and_n_entries(m, colon);
+ if (r < 0)
+ return r;
+
+ until = strndup(time_request, colon - time_request);
+ }
+ if (!until)
+ return -ENOMEM;
+
+ if (!isempty(until)) {
+ r = parse_sec(until, &m->until);
+ if (r < 0)
+ return r;
+
+ m->until_set = true;
+ if (m->until < m->since)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int request_parse_range(
+ RequestMeta *m,
+ struct MHD_Connection *connection) {
+
+ const char *range, *range_after_eq;
+
+ assert(m);
+ assert(connection);
+
+ range = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Range");
+ if (!range)
+ return 0;
+
+ /* Safety upper bound to make Coverity happy. Apache2 has a default limit of 8KB:
+ * https://httpd.apache.org/docs/2.2/mod/core.html#limitrequestfieldsize */
+ if (strlen(range) > JOURNAL_SERVER_MEMORY_MAX)
+ return -EINVAL;
+
+ m->n_skip = 0;
+
+ range_after_eq = startswith(range, "entries=");
+ if (range_after_eq)
+ return request_parse_range_entries(m, skip_leading_chars(range_after_eq, /* bad = */ NULL));
+
+ range_after_eq = startswith(range, "realtime=");
+ if (range_after_eq)
+ return request_parse_range_time(m, skip_leading_chars(range_after_eq, /* bad = */ NULL));
+
+ return 0;
+}
+
static mhd_result request_parse_arguments_iterator(
void *cls,
enum MHD_ValueKind kind,
@@ -364,7 +465,6 @@ static mhd_result request_parse_arguments_iterator(
const char *value) {
RequestMeta *m = ASSERT_PTR(cls);
- _cleanup_free_ char *p = NULL;
int r;
if (isempty(key)) {
@@ -416,17 +516,7 @@ static mhd_result request_parse_arguments_iterator(
}
if (r) {
- char match[9 + 32 + 1] = "_BOOT_ID=";
- sd_id128_t bid;
-
- r = sd_id128_get_boot(&bid);
- if (r < 0) {
- log_error_errno(r, "Failed to get boot ID: %m");
- return MHD_NO;
- }
-
- sd_id128_to_string(bid, match + 9);
- r = sd_journal_add_match(m->journal, match, sizeof(match)-1);
+ r = add_match_boot_id(m->journal, SD_ID128_NULL);
if (r < 0) {
m->argument_parse_error = r;
return MHD_NO;
@@ -436,13 +526,7 @@ static mhd_result request_parse_arguments_iterator(
return MHD_YES;
}
- p = strjoin(key, "=", strempty(value));
- if (!p) {
- m->argument_parse_error = log_oom();
- return MHD_NO;
- }
-
- r = sd_journal_add_match(m->journal, p, 0);
+ r = journal_add_match_pair(m->journal, key, strempty(value));
if (r < 0) {
m->argument_parse_error = r;
return MHD_NO;
@@ -497,10 +581,15 @@ static int request_handler_entries(
if (m->cursor)
r = sd_journal_seek_cursor(m->journal, m->cursor);
+ else if (m->since_set)
+ r = sd_journal_seek_realtime_usec(m->journal, m->since);
else if (m->n_skip >= 0)
r = sd_journal_seek_head(m->journal);
+ else if (m->until_set && m->n_skip < 0)
+ r = sd_journal_seek_realtime_usec(m->journal, m->until);
else if (m->n_skip < 0)
r = sd_journal_seek_tail(m->journal);
+
if (r < 0)
return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to seek in journal.");
@@ -778,7 +867,7 @@ static int request_handler_machine(
SD_ID128_FORMAT_VAL(bid),
hostname_cleanup(hostname),
os_release_pretty_name(pretty_name, os_name),
- v ? v : "bare",
+ v ?: "bare",
usage,
cutoff_from,
cutoff_to);
diff --git a/src/journal-remote/journal-remote-main.c b/src/journal-remote/journal-remote-main.c
index 294719b..34d4062 100644
--- a/src/journal-remote/journal-remote-main.c
+++ b/src/journal-remote/journal-remote-main.c
@@ -108,7 +108,7 @@ static int spawn_child(const char* child, char** argv) {
r = fd_nonblock(fd[0], true);
if (r < 0)
- log_warning_errno(errno, "Failed to set child pipe to non-blocking: %m");
+ log_warning_errno(r, "Failed to set child pipe to non-blocking: %m");
return fd[0];
}
@@ -374,7 +374,7 @@ static int setup_microhttpd_server(RemoteServer *s,
{ MHD_OPTION_EXTERNAL_LOGGER, (intptr_t) microhttpd_logger},
{ MHD_OPTION_NOTIFY_COMPLETED, (intptr_t) request_meta_free},
{ MHD_OPTION_LISTEN_SOCKET, fd},
- { MHD_OPTION_CONNECTION_MEMORY_LIMIT, 128*1024},
+ { MHD_OPTION_CONNECTION_MEMORY_LIMIT, JOURNAL_SERVER_MEMORY_MAX},
{ MHD_OPTION_END},
{ MHD_OPTION_END},
{ MHD_OPTION_END},
@@ -451,7 +451,7 @@ static int setup_microhttpd_server(RemoteServer *s,
if (epoll_fd < 0)
return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN), "μhttp epoll fd is invalid");
- r = sd_event_add_io(s->events, &d->io_event,
+ r = sd_event_add_io(s->event, &d->io_event,
epoll_fd, EPOLLIN,
dispatch_http_event, d);
if (r < 0)
@@ -461,7 +461,7 @@ static int setup_microhttpd_server(RemoteServer *s,
if (r < 0)
return log_error_errno(r, "Failed to set source name: %m");
- r = sd_event_add_time(s->events, &d->timer_event,
+ r = sd_event_add_time(s->event, &d->timer_event,
CLOCK_MONOTONIC, UINT64_MAX, 0,
null_timer_event_handler, d);
if (r < 0)
@@ -562,7 +562,7 @@ static int create_remoteserver(
if (r < 0)
return r;
- r = sd_event_set_signal_exit(s->events, true);
+ r = sd_event_set_signal_exit(s->event, true);
if (r < 0)
return log_error_errno(r, "Failed to install SIGINT/SIGTERM handlers: %m");
@@ -728,9 +728,12 @@ static int parse_config(void) {
{}
};
- return config_parse_config_file("journal-remote.conf", "Remote\0",
- config_item_table_lookup, items,
- CONFIG_PARSE_WARN, NULL);
+ return config_parse_standard_file_with_dropins(
+ "systemd/journal-remote.conf",
+ "Remote\0",
+ config_item_table_lookup, items,
+ CONFIG_PARSE_WARN,
+ /* userdata= */ NULL);
}
static int help(void) {
@@ -1067,8 +1070,7 @@ static int run(int argc, char **argv) {
_cleanup_free_ char *cert = NULL, *trust = NULL;
int r;
- log_show_color(true);
- log_parse_environment();
+ log_setup();
/* The journal merging logic potentially needs a lot of fds. */
(void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
@@ -1107,7 +1109,7 @@ static int run(int argc, char **argv) {
if (r < 0)
return r;
- r = sd_event_set_watchdog(s.events, true);
+ r = sd_event_set_watchdog(s.event, true);
if (r < 0)
return log_error_errno(r, "Failed to enable watchdog: %m");
@@ -1119,13 +1121,13 @@ static int run(int argc, char **argv) {
notify_message = notify_start(NOTIFY_READY, NOTIFY_STOPPING);
while (s.active) {
- r = sd_event_get_state(s.events);
+ r = sd_event_get_state(s.event);
if (r < 0)
return r;
if (r == SD_EVENT_FINISHED)
break;
- r = sd_event_run(s.events, -1);
+ r = sd_event_run(s.event, -1);
if (r < 0)
return log_error_errno(r, "Failed to run event loop: %m");
}
diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c
index 9db686d..92187b7 100644
--- a/src/journal-remote/journal-remote.c
+++ b/src/journal-remote/journal-remote.c
@@ -86,7 +86,6 @@ static int open_output(RemoteServer *s, Writer *w, const char* host) {
UINT64_MAX,
&w->metrics,
w->mmap,
- NULL,
&w->journal);
if (r < 0)
return log_error_errno(r, "Failed to open output journal %s: %m", filename);
@@ -258,19 +257,19 @@ int journal_remote_add_source(RemoteServer *s, int fd, char* name, bool own_name
return r;
}
- r = sd_event_add_io(s->events, &source->event,
+ r = sd_event_add_io(s->event, &source->event,
fd, EPOLLIN|EPOLLRDHUP|EPOLLPRI,
dispatch_raw_source_event, source);
if (r == 0) {
/* Add additional source for buffer processing. It will be
* enabled later. */
- r = sd_event_add_defer(s->events, &source->buffer_event,
+ r = sd_event_add_defer(s->event, &source->buffer_event,
dispatch_raw_source_until_block, source);
if (r == 0)
r = sd_event_source_set_enabled(source->buffer_event, SD_EVENT_OFF);
} else if (r == -EPERM) {
log_debug("Falling back to sd_event_add_defer for fd:%d (%s)", fd, name);
- r = sd_event_add_defer(s->events, &source->event,
+ r = sd_event_add_defer(s->event, &source->event,
dispatch_blocking_source_event, source);
if (r == 0)
r = sd_event_source_set_enabled(source->event, SD_EVENT_ON);
@@ -302,7 +301,7 @@ int journal_remote_add_raw_socket(RemoteServer *s, int fd) {
assert(s);
assert(fd >= 0);
- r = sd_event_add_io(s->events, &s->listen_event,
+ r = sd_event_add_io(s->event, &s->listen_event,
fd, EPOLLIN,
dispatch_raw_connection_event, s);
if (r < 0)
@@ -348,7 +347,7 @@ int journal_remote_server_init(
else
assert_not_reached();
- r = sd_event_default(&s->events);
+ r = sd_event_default(&s->event);
if (r < 0)
return log_error_errno(r, "Failed to allocate event loop: %m");
@@ -377,7 +376,7 @@ void journal_remote_server_destroy(RemoteServer *s) {
hashmap_free(s->writers);
sd_event_source_unref(s->listen_event);
- sd_event_unref(s->events);
+ sd_event_unref(s->event);
if (s == journal_remote_server_global)
journal_remote_server_global = NULL;
@@ -525,7 +524,7 @@ static int accept_connection(
if (r < 0)
return log_error_errno(r, "socket_address_print(): %m");
- r = socknameinfo_pretty(&addr->sockaddr, addr->size, &b);
+ r = socknameinfo_pretty(&addr->sockaddr.sa, addr->size, &b);
if (r < 0)
return log_error_errno(r, "Resolving hostname failed: %m");
diff --git a/src/journal-remote/journal-remote.h b/src/journal-remote/journal-remote.h
index 3d64db0..f1ec5d9 100644
--- a/src/journal-remote/journal-remote.h
+++ b/src/journal-remote/journal-remote.h
@@ -29,7 +29,7 @@ struct RemoteServer {
RemoteSource **sources;
size_t active;
- sd_event *events;
+ sd_event *event;
sd_event_source *listen_event;
Hashmap *writers;
@@ -48,6 +48,9 @@ struct RemoteServer {
};
extern RemoteServer *journal_remote_server_global;
+/* Used for MHD_OPTION_CONNECTION_MEMORY_LIMIT and header parsing cap */
+#define JOURNAL_SERVER_MEMORY_MAX 128U * 1024U
+
int journal_remote_server_init(
RemoteServer *s,
const char *output,
diff --git a/src/journal-remote/journal-upload-journal.c b/src/journal-remote/journal-upload-journal.c
index 8206ca8..23ad3b2 100644
--- a/src/journal-remote/journal-upload-journal.c
+++ b/src/journal-remote/journal-upload-journal.c
@@ -388,7 +388,7 @@ int open_journal_for_upload(Uploader *u,
else
u->timeout = JOURNAL_UPLOAD_POLL_TIMEOUT;
- r = sd_event_add_io(u->events, &u->input_event,
+ r = sd_event_add_io(u->event, &u->input_event,
fd, events, dispatch_journal_input, u);
if (r < 0)
return log_error_errno(r, "Failed to register input event: %m");
diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c
index d70a049..f6b9351 100644
--- a/src/journal-remote/journal-upload.c
+++ b/src/journal-remote/journal-upload.c
@@ -366,7 +366,7 @@ static int open_file_for_upload(Uploader *u, const char *filename) {
u->input = fd;
if (arg_follow != 0) {
- r = sd_event_add_io(u->events, &u->input_event,
+ r = sd_event_add_io(u->event, &u->input_event,
fd, EPOLLIN, dispatch_fd_input, u);
if (r < 0) {
if (r != -EPERM || arg_follow > 0)
@@ -415,11 +415,11 @@ static int setup_uploader(Uploader *u, const char *url, const char *state_file)
u->state_file = state_file;
- r = sd_event_default(&u->events);
+ r = sd_event_default(&u->event);
if (r < 0)
return log_error_errno(r, "sd_event_default failed: %m");
- r = sd_event_set_signal_exit(u->events, true);
+ r = sd_event_set_signal_exit(u->event, true);
if (r < 0)
return log_error_errno(r, "Failed to install SIGINT/SIGTERM handlers: %m");
@@ -445,7 +445,7 @@ static void destroy_uploader(Uploader *u) {
close_fd_input(u);
close_journal_input(u);
- sd_event_unref(u->events);
+ sd_event_unref(u->event);
}
static int perform_upload(Uploader *u) {
@@ -499,9 +499,12 @@ static int parse_config(void) {
{}
};
- return config_parse_config_file("journal-upload.conf", "Upload\0",
- config_item_table_lookup, items,
- CONFIG_PARSE_WARN, NULL);
+ return config_parse_standard_file_with_dropins(
+ "systemd/journal-upload.conf",
+ "Upload\0",
+ config_item_table_lookup, items,
+ CONFIG_PARSE_WARN,
+ /* userdata= */ NULL);
}
static int help(void) {
@@ -745,7 +748,7 @@ static int open_journal(sd_journal **j) {
else if (arg_file)
r = sd_journal_open_files(j, (const char**) arg_file, 0);
else if (arg_machine)
- r = journal_open_machine(j, arg_machine);
+ r = journal_open_machine(j, arg_machine, 0);
else
r = sd_journal_open_namespace(j, arg_namespace,
(arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY) | arg_namespace_flags | arg_journal_type);
@@ -761,8 +764,7 @@ static int run(int argc, char **argv) {
bool use_journal;
int r;
- log_show_color(true);
- log_parse_environment();
+ log_setup();
/* The journal merging logic potentially needs a lot of fds. */
(void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
@@ -781,7 +783,7 @@ static int run(int argc, char **argv) {
if (r < 0)
return r;
- sd_event_set_watchdog(u.events, true);
+ sd_event_set_watchdog(u.event, true);
r = check_cursor_updating(&u);
if (r < 0)
@@ -809,7 +811,7 @@ static int run(int argc, char **argv) {
NOTIFY_STOPPING);
for (;;) {
- r = sd_event_get_state(u.events);
+ r = sd_event_get_state(u.event);
if (r < 0)
return r;
if (r == SD_EVENT_FINISHED)
@@ -836,7 +838,7 @@ static int run(int argc, char **argv) {
return r;
}
- r = sd_event_run(u.events, u.timeout);
+ r = sd_event_run(u.event, u.timeout);
if (r < 0)
return log_error_errno(r, "Failed to run event loop: %m");
}
diff --git a/src/journal-remote/journal-upload.h b/src/journal-remote/journal-upload.h
index 2007864..5ba3c4f 100644
--- a/src/journal-remote/journal-upload.h
+++ b/src/journal-remote/journal-upload.h
@@ -24,7 +24,7 @@ typedef enum {
} entry_state;
typedef struct Uploader {
- sd_event *events;
+ sd_event *event;
char *url;
CURL *easy;
diff --git a/src/journal-remote/meson.build b/src/journal-remote/meson.build
index 964a251..10a8275 100644
--- a/src/journal-remote/meson.build
+++ b/src/journal-remote/meson.build
@@ -22,9 +22,9 @@ libsystemd_journal_remote = static_library(
libsystemd_journal_remote_sources,
include_directories : includes,
dependencies : [libgnutls,
- liblz4,
+ liblz4_cflags,
libmicrohttpd,
- libxz,
+ libxz_cflags,
threads,
userspace],
build_by_default : false)
@@ -38,9 +38,9 @@ systemd_journal_gatewayd_sources = files(
common_deps = [
libgnutls,
- liblz4,
- libxz,
- libzstd,
+ liblz4_cflags,
+ libxz_cflags,
+ libzstd_cflags,
threads,
]