diff options
author | Samuel BF <8824801-samuelbf@users.noreply.gitlab.com> | 2023-10-05 21:39:45 +0200 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2023-12-06 22:22:27 +0100 |
commit | 435c372ce5059082212d37ac7039844f14f34a80 (patch) | |
tree | 3e8eeb0b5f4eb16e48405efede2c944c4555a208 /src/journal-remote | |
parent | udev: generate system-unique storage symlinks using device path (diff) | |
download | systemd-435c372ce5059082212d37ac7039844f14f34a80.tar.xz systemd-435c372ce5059082212d37ac7039844f14f34a80.zip |
journal-gatewayd: add since/until parameters for /entries
Request with Range header like 'entries=<cursor>:' (with a colon at the end,
invalid syntax per the doc), is now rejected with error 400 Bad Request.
fix #4883
Diffstat (limited to 'src/journal-remote')
-rw-r--r-- | src/journal-remote/journal-gatewayd.c | 176 |
1 files changed, 136 insertions, 40 deletions
diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c index 09194710cb..9f0d0ec34a 100644 --- a/src/journal-remote/journal-gatewayd.c +++ b/src/journal-remote/journal-gatewayd.c @@ -32,6 +32,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) @@ -54,9 +55,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; @@ -211,6 +213,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; @@ -292,60 +305,56 @@ 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; - - range += 8; - range += strspn(range, WHITESPACE); + r = safe_atoi64(t, &m->n_skip); + if (r < 0) + return r; + } - colon = strchr(range, ':'); - if (!colon) - m->cursor = strdup(range); - else { - const char *p; + p = (colon2 ?: colon) + 1; + r = safe_atou64(p, &m->n_entries); + if (r < 0) + return r; - colon2 = strchr(colon + 1, ':'); - if (colon2) { - _cleanup_free_ char *t = NULL; + if (m->n_entries <= 0) + return -EINVAL; - t = strndup(colon + 1, colon2 - colon - 1); - if (!t) - return -ENOMEM; + m->n_entries_set = true; - r = safe_atoi64(t, &m->n_skip); - if (r < 0) - return r; - } + return 0; +} - p = (colon2 ?: colon) + 1; - if (*p) { - r = safe_atou64(p, &m->n_entries); - if (r < 0) - return r; +static int request_parse_range_entries( + RequestMeta *m, + const char *entries_request) { - if (m->n_entries <= 0) - return -EINVAL; + const char *colon; + int r; - 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; @@ -356,6 +365,88 @@ 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; + + 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; + + m->n_skip = 0; + range_after_eq = startswith(range, "entries="); + if (range_after_eq) { + range_after_eq += strspn(range_after_eq, WHITESPACE); + return request_parse_range_entries(m, range_after_eq); + } + + range_after_eq = startswith(range, "realtime="); + if (startswith(range, "realtime=")) { + range_after_eq += strspn(range_after_eq, WHITESPACE); + return request_parse_range_time(m, range_after_eq); + } + + return 0; +} + static mhd_result request_parse_arguments_iterator( void *cls, enum MHD_ValueKind kind, @@ -496,10 +587,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."); |