2020-11-09 05:23:58 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
2012-11-01 23:08:03 +01:00
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <sys/prctl.h>
|
2017-10-26 10:54:30 +02:00
|
|
|
#include <stdint.h>
|
2015-09-23 03:01:06 +02:00
|
|
|
|
2012-11-01 23:08:03 +01:00
|
|
|
#include "sd-daemon.h"
|
2015-09-23 03:01:06 +02:00
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
#include "alloc-util.h"
|
2015-11-03 12:26:12 +01:00
|
|
|
#include "def.h"
|
2019-04-10 19:50:53 +02:00
|
|
|
#include "errno-util.h"
|
2015-10-23 18:52:53 +02:00
|
|
|
#include "escape.h"
|
2015-10-25 13:14:12 +01:00
|
|
|
#include "fd-util.h"
|
2012-11-01 23:08:03 +01:00
|
|
|
#include "journal-file.h"
|
2015-10-23 18:52:53 +02:00
|
|
|
#include "journal-remote-write.h"
|
2015-10-25 13:14:12 +01:00
|
|
|
#include "journal-remote.h"
|
2012-11-01 23:08:03 +01:00
|
|
|
#include "journald-native.h"
|
|
|
|
#include "macro.h"
|
2015-10-26 16:18:16 +01:00
|
|
|
#include "parse-util.h"
|
2018-01-11 00:39:12 +01:00
|
|
|
#include "process-util.h"
|
2015-09-23 03:01:06 +02:00
|
|
|
#include "socket-util.h"
|
2015-10-27 01:26:31 +01:00
|
|
|
#include "stdio-util.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "string-util.h"
|
2012-11-01 23:08:03 +01:00
|
|
|
#include "strv.h"
|
|
|
|
|
2014-06-22 19:36:31 +02:00
|
|
|
#define REMOTE_JOURNAL_PATH "/var/log/journal/remote"
|
2012-11-01 23:08:03 +01:00
|
|
|
|
2014-07-02 06:15:37 +02:00
|
|
|
#define filename_escape(s) xescape((s), "/ ")
|
2014-06-22 19:36:31 +02:00
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
static int open_output(RemoteServer *s, Writer *w, const char* host) {
|
|
|
|
_cleanup_free_ char *_filename = NULL;
|
|
|
|
const char *filename;
|
2012-11-01 23:08:03 +01:00
|
|
|
int r;
|
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
switch (s->split_mode) {
|
2014-06-22 19:36:31 +02:00
|
|
|
case JOURNAL_WRITE_SPLIT_NONE:
|
2018-05-16 10:21:58 +02:00
|
|
|
filename = s->output;
|
2014-06-22 19:36:31 +02:00
|
|
|
break;
|
2012-11-01 23:08:03 +01:00
|
|
|
|
2014-06-22 19:36:31 +02:00
|
|
|
case JOURNAL_WRITE_SPLIT_HOST: {
|
|
|
|
_cleanup_free_ char *name;
|
2012-11-01 23:08:03 +01:00
|
|
|
|
2014-06-22 19:36:31 +02:00
|
|
|
assert(host);
|
2012-11-01 23:08:03 +01:00
|
|
|
|
2014-06-22 19:36:31 +02:00
|
|
|
name = filename_escape(host);
|
|
|
|
if (!name)
|
|
|
|
return log_oom();
|
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
r = asprintf(&_filename, "%s/remote-%s.journal", s->output, name);
|
2012-11-01 23:08:03 +01:00
|
|
|
if (r < 0)
|
|
|
|
return log_oom();
|
2014-06-22 19:36:31 +02:00
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
filename = _filename;
|
2014-06-22 19:36:31 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
assert_not_reached("what?");
|
2012-11-01 23:08:03 +01:00
|
|
|
}
|
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
r = journal_file_open_reliably(filename,
|
2012-11-01 23:08:03 +01:00
|
|
|
O_RDWR|O_CREAT, 0640,
|
2018-05-16 10:21:58 +02:00
|
|
|
s->compress, (uint64_t) -1, s->seal,
|
2014-06-22 19:36:31 +02:00
|
|
|
&w->metrics,
|
2016-02-18 02:37:10 +01:00
|
|
|
w->mmap, NULL,
|
2014-06-22 19:36:31 +02:00
|
|
|
NULL, &w->journal);
|
2012-11-01 23:08:03 +01:00
|
|
|
if (r < 0)
|
2018-05-16 10:21:58 +02:00
|
|
|
return log_error_errno(r, "Failed to open output journal %s: %m", filename);
|
|
|
|
|
|
|
|
log_debug("Opened output file %s", w->journal->path);
|
|
|
|
return 0;
|
2012-11-01 23:08:03 +01:00
|
|
|
}
|
|
|
|
|
2014-03-15 20:58:03 +01:00
|
|
|
/**********************************************************************
|
|
|
|
**********************************************************************
|
|
|
|
**********************************************************************/
|
|
|
|
|
2014-07-02 06:15:37 +02:00
|
|
|
static int init_writer_hashmap(RemoteServer *s) {
|
2018-05-16 10:21:58 +02:00
|
|
|
static const struct hash_ops* const hash_ops[] = {
|
2014-08-13 01:00:18 +02:00
|
|
|
[JOURNAL_WRITE_SPLIT_NONE] = NULL,
|
|
|
|
[JOURNAL_WRITE_SPLIT_HOST] = &string_hash_ops,
|
2014-07-02 06:15:37 +02:00
|
|
|
};
|
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
assert(s);
|
|
|
|
assert(s->split_mode >= 0 && s->split_mode < (int) ELEMENTSOF(hash_ops));
|
2014-03-15 20:58:03 +01:00
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
s->writers = hashmap_new(hash_ops[s->split_mode]);
|
2014-07-02 06:15:37 +02:00
|
|
|
if (!s->writers)
|
|
|
|
return log_oom();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
int journal_remote_get_writer(RemoteServer *s, const char *host, Writer **writer) {
|
tree-wide: drop redundant _cleanup_ macros (#8810)
This drops a good number of type-specific _cleanup_ macros, and patches
all users to just use the generic ones.
In most recent code we abstained from defining type-specific macros, and
this basically removes all those added already, with the exception of
the really low-level ones.
Having explicit macros for this is not too useful, as the expression
without the extra macro is generally just 2ch wider. We should generally
emphesize generic code, unless there are really good reasons for
specific code, hence let's follow this in this case too.
Note that _cleanup_free_ and similar really low-level, libc'ish, Linux
API'ish macros continue to be defined, only the really high-level OO
ones are dropped. From now on this should really be the rule: for really
low-level stuff, such as memory allocation, fd handling and so one, go
ahead and define explicit per-type macros, but for high-level, specific
program code, just use the generic _cleanup_() macro directly, in order
to keep things simple and as readable as possible for the uninitiated.
Note that before this patch some of the APIs (notable libudev ones) were
already used with the high-level macros at some places and with the
generic _cleanup_ macro at others. With this patch we hence unify on the
latter.
2018-04-25 12:31:45 +02:00
|
|
|
_cleanup_(writer_unrefp) Writer *w = NULL;
|
2014-07-02 06:15:37 +02:00
|
|
|
const void *key;
|
|
|
|
int r;
|
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
switch(s->split_mode) {
|
2014-07-02 06:15:37 +02:00
|
|
|
case JOURNAL_WRITE_SPLIT_NONE:
|
|
|
|
key = "one and only";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case JOURNAL_WRITE_SPLIT_HOST:
|
|
|
|
assert(host);
|
|
|
|
key = host;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
assert_not_reached("what split mode?");
|
|
|
|
}
|
|
|
|
|
|
|
|
w = hashmap_get(s->writers, key);
|
|
|
|
if (w)
|
|
|
|
writer_ref(w);
|
|
|
|
else {
|
|
|
|
w = writer_new(s);
|
|
|
|
if (!w)
|
|
|
|
return log_oom();
|
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
if (s->split_mode == JOURNAL_WRITE_SPLIT_HOST) {
|
2014-07-02 06:15:37 +02:00
|
|
|
w->hashmap_key = strdup(key);
|
|
|
|
if (!w->hashmap_key)
|
|
|
|
return log_oom();
|
|
|
|
}
|
2014-03-15 20:58:03 +01:00
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
r = open_output(s, w, host);
|
2014-07-02 06:15:37 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2012-11-01 23:08:03 +01:00
|
|
|
|
2014-07-02 06:15:37 +02:00
|
|
|
r = hashmap_put(s->writers, w->hashmap_key ?: key, w);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
}
|
2012-11-01 23:08:03 +01:00
|
|
|
|
2018-04-05 07:26:26 +02:00
|
|
|
*writer = TAKE_PTR(w);
|
|
|
|
|
2014-07-02 06:15:37 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2014-03-15 20:58:03 +01:00
|
|
|
|
2014-07-02 06:15:37 +02:00
|
|
|
/**********************************************************************
|
|
|
|
**********************************************************************
|
|
|
|
**********************************************************************/
|
2012-11-01 23:08:03 +01:00
|
|
|
|
2014-03-15 20:58:03 +01:00
|
|
|
/* This should go away as soon as µhttpd allows state to be passed around. */
|
2018-05-16 10:21:58 +02:00
|
|
|
RemoteServer *journal_remote_server_global;
|
2014-03-15 20:58:03 +01:00
|
|
|
|
2012-11-01 23:08:03 +01:00
|
|
|
static int dispatch_raw_source_event(sd_event_source *event,
|
|
|
|
int fd,
|
|
|
|
uint32_t revents,
|
|
|
|
void *userdata);
|
2015-03-13 05:02:28 +01:00
|
|
|
static int dispatch_raw_source_until_block(sd_event_source *event,
|
|
|
|
void *userdata);
|
2014-09-28 02:00:00 +02:00
|
|
|
static int dispatch_blocking_source_event(sd_event_source *event,
|
|
|
|
void *userdata);
|
2012-11-01 23:08:03 +01:00
|
|
|
static int dispatch_raw_connection_event(sd_event_source *event,
|
|
|
|
int fd,
|
|
|
|
uint32_t revents,
|
|
|
|
void *userdata);
|
|
|
|
|
2014-07-02 06:15:37 +02:00
|
|
|
static int get_source_for_fd(RemoteServer *s,
|
|
|
|
int fd, char *name, RemoteSource **source) {
|
|
|
|
Writer *writer;
|
|
|
|
int r;
|
|
|
|
|
2014-10-13 04:27:20 +02:00
|
|
|
/* This takes ownership of name, but only on success. */
|
|
|
|
|
2012-11-01 23:08:03 +01:00
|
|
|
assert(fd >= 0);
|
|
|
|
assert(source);
|
|
|
|
|
2014-04-10 15:48:59 +02:00
|
|
|
if (!GREEDY_REALLOC0(s->sources, s->sources_size, fd + 1))
|
2012-11-01 23:08:03 +01:00
|
|
|
return log_oom();
|
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
r = journal_remote_get_writer(s, name, &writer);
|
2014-11-28 17:34:26 +01:00
|
|
|
if (r < 0)
|
|
|
|
return log_warning_errno(r, "Failed to get writer for source %s: %m",
|
|
|
|
name);
|
2014-07-02 06:15:37 +02:00
|
|
|
|
2019-04-28 14:28:49 +02:00
|
|
|
if (!s->sources[fd]) {
|
2014-07-02 06:15:37 +02:00
|
|
|
s->sources[fd] = source_new(fd, false, name, writer);
|
|
|
|
if (!s->sources[fd]) {
|
|
|
|
writer_unref(writer);
|
2012-11-01 23:08:03 +01:00
|
|
|
return log_oom();
|
2014-07-02 06:15:37 +02:00
|
|
|
}
|
|
|
|
|
2012-11-01 23:08:03 +01:00
|
|
|
s->active++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*source = s->sources[fd];
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int remove_source(RemoteServer *s, int fd) {
|
|
|
|
RemoteSource *source;
|
|
|
|
|
|
|
|
assert(s);
|
2014-04-10 15:48:59 +02:00
|
|
|
assert(fd >= 0 && fd < (ssize_t) s->sources_size);
|
2012-11-01 23:08:03 +01:00
|
|
|
|
|
|
|
source = s->sources[fd];
|
|
|
|
if (source) {
|
2014-06-22 19:36:31 +02:00
|
|
|
/* this closes fd too */
|
2012-11-01 23:08:03 +01:00
|
|
|
source_free(source);
|
|
|
|
s->sources[fd] = NULL;
|
|
|
|
s->active--;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
int journal_remote_add_source(RemoteServer *s, int fd, char* name, bool own_name) {
|
2015-03-27 12:02:49 +01:00
|
|
|
RemoteSource *source = NULL;
|
2012-11-01 23:08:03 +01:00
|
|
|
int r;
|
|
|
|
|
2014-10-13 04:27:20 +02:00
|
|
|
/* This takes ownership of name, even on failure, if own_name is true. */
|
|
|
|
|
2012-11-01 23:08:03 +01:00
|
|
|
assert(s);
|
|
|
|
assert(fd >= 0);
|
2014-07-02 06:15:37 +02:00
|
|
|
assert(name);
|
2012-11-01 23:08:03 +01:00
|
|
|
|
2014-07-02 06:15:37 +02:00
|
|
|
if (!own_name) {
|
|
|
|
name = strdup(name);
|
|
|
|
if (!name)
|
|
|
|
return log_oom();
|
|
|
|
}
|
2012-11-01 23:08:03 +01:00
|
|
|
|
2014-07-02 06:15:37 +02:00
|
|
|
r = get_source_for_fd(s, fd, name, &source);
|
2012-11-01 23:08:03 +01:00
|
|
|
if (r < 0) {
|
2014-11-28 17:09:20 +01:00
|
|
|
log_error_errno(r, "Failed to create source for fd:%d (%s): %m",
|
|
|
|
fd, name);
|
2014-10-13 04:27:20 +02:00
|
|
|
free(name);
|
2012-11-01 23:08:03 +01:00
|
|
|
return r;
|
|
|
|
}
|
2014-06-22 19:36:31 +02:00
|
|
|
|
2012-11-01 23:08:03 +01:00
|
|
|
r = sd_event_add_io(s->events, &source->event,
|
2014-06-22 19:36:31 +02:00
|
|
|
fd, EPOLLIN|EPOLLRDHUP|EPOLLPRI,
|
2015-03-13 05:02:28 +01:00
|
|
|
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,
|
|
|
|
dispatch_raw_source_until_block, source);
|
|
|
|
if (r == 0)
|
|
|
|
sd_event_source_set_enabled(source->buffer_event, SD_EVENT_OFF);
|
|
|
|
} else if (r == -EPERM) {
|
2014-09-28 02:00:00 +02:00
|
|
|
log_debug("Falling back to sd_event_add_defer for fd:%d (%s)", fd, name);
|
|
|
|
r = sd_event_add_defer(s->events, &source->event,
|
|
|
|
dispatch_blocking_source_event, source);
|
|
|
|
if (r == 0)
|
|
|
|
sd_event_source_set_enabled(source->event, SD_EVENT_ON);
|
|
|
|
}
|
2012-11-01 23:08:03 +01:00
|
|
|
if (r < 0) {
|
2014-11-28 17:09:20 +01:00
|
|
|
log_error_errno(r, "Failed to register event source for fd:%d: %m",
|
|
|
|
fd);
|
2012-11-01 23:08:03 +01:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2014-11-04 16:27:05 +01:00
|
|
|
r = sd_event_source_set_description(source->event, name);
|
2014-10-18 07:28:37 +02:00
|
|
|
if (r < 0) {
|
2014-11-28 13:19:16 +01:00
|
|
|
log_error_errno(r, "Failed to set source name for fd:%d: %m", fd);
|
2014-10-18 07:28:37 +02:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2012-11-01 23:08:03 +01:00
|
|
|
return 1; /* work to do */
|
|
|
|
|
|
|
|
error:
|
|
|
|
remove_source(s, fd);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
int journal_remote_add_raw_socket(RemoteServer *s, int fd) {
|
2014-03-17 03:33:35 +01:00
|
|
|
int r;
|
2014-10-18 07:28:37 +02:00
|
|
|
_cleanup_close_ int fd_ = fd;
|
2017-12-14 19:02:29 +01:00
|
|
|
char name[STRLEN("raw-socket-") + DECIMAL_STR_MAX(int) + 1];
|
2014-10-18 07:28:37 +02:00
|
|
|
|
|
|
|
assert(fd >= 0);
|
2012-11-01 23:08:03 +01:00
|
|
|
|
2014-06-22 19:36:31 +02:00
|
|
|
r = sd_event_add_io(s->events, &s->listen_event,
|
|
|
|
fd, EPOLLIN,
|
2012-11-01 23:08:03 +01:00
|
|
|
dispatch_raw_connection_event, s);
|
2014-10-18 07:28:37 +02:00
|
|
|
if (r < 0)
|
2012-11-01 23:08:03 +01:00
|
|
|
return r;
|
|
|
|
|
2015-01-27 14:00:11 +01:00
|
|
|
xsprintf(name, "raw-socket-%d", fd);
|
2014-10-18 07:28:37 +02:00
|
|
|
|
2014-11-04 16:27:05 +01:00
|
|
|
r = sd_event_source_set_description(s->listen_event, name);
|
2014-10-18 07:28:37 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
fd_ = -1;
|
2016-02-23 05:32:04 +01:00
|
|
|
s->active++;
|
2012-11-01 23:08:03 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-06-22 19:36:31 +02:00
|
|
|
/**********************************************************************
|
|
|
|
**********************************************************************
|
|
|
|
**********************************************************************/
|
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
int journal_remote_server_init(
|
|
|
|
RemoteServer *s,
|
|
|
|
const char *output,
|
|
|
|
JournalWriteSplitMode split_mode,
|
|
|
|
bool compress,
|
|
|
|
bool seal) {
|
2014-03-15 20:58:03 +01:00
|
|
|
|
2012-11-01 23:08:03 +01:00
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(s);
|
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
assert(journal_remote_server_global == NULL);
|
|
|
|
journal_remote_server_global = s;
|
2012-11-01 23:08:03 +01:00
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
s->split_mode = split_mode;
|
|
|
|
s->compress = compress;
|
|
|
|
s->seal = seal;
|
2014-10-18 07:28:37 +02:00
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
if (output)
|
|
|
|
s->output = output;
|
|
|
|
else if (split_mode == JOURNAL_WRITE_SPLIT_NONE)
|
|
|
|
s->output = REMOTE_JOURNAL_PATH "/remote.journal";
|
|
|
|
else if (split_mode == JOURNAL_WRITE_SPLIT_HOST)
|
|
|
|
s->output = REMOTE_JOURNAL_PATH;
|
2014-10-18 07:27:10 +02:00
|
|
|
else
|
2018-05-16 10:21:58 +02:00
|
|
|
assert_not_reached("bad split mode");
|
2014-03-31 05:08:02 +02:00
|
|
|
|
2014-09-18 17:52:54 +02:00
|
|
|
r = sd_event_default(&s->events);
|
2014-11-28 18:23:20 +01:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to allocate event loop: %m");
|
2012-11-01 23:08:03 +01:00
|
|
|
|
2014-09-24 15:59:06 +02:00
|
|
|
r = init_writer_hashmap(s);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2014-06-22 19:36:31 +02:00
|
|
|
return 0;
|
2012-11-01 23:08:03 +01:00
|
|
|
}
|
|
|
|
|
2018-05-16 13:30:37 +02:00
|
|
|
#if HAVE_MICROHTTPD
|
2017-11-28 12:38:15 +01:00
|
|
|
static void MHDDaemonWrapper_free(MHDDaemonWrapper *d) {
|
|
|
|
MHD_stop_daemon(d->daemon);
|
|
|
|
sd_event_source_unref(d->io_event);
|
|
|
|
sd_event_source_unref(d->timer_event);
|
|
|
|
free(d);
|
|
|
|
}
|
2018-05-16 13:30:37 +02:00
|
|
|
#endif
|
2017-11-28 12:38:15 +01:00
|
|
|
|
2018-11-26 09:50:52 +01:00
|
|
|
void journal_remote_server_destroy(RemoteServer *s) {
|
2014-04-10 15:48:59 +02:00
|
|
|
size_t i;
|
2014-03-15 20:58:03 +01:00
|
|
|
|
2018-05-16 13:30:37 +02:00
|
|
|
#if HAVE_MICROHTTPD
|
2017-11-28 12:38:15 +01:00
|
|
|
hashmap_free_with_destructor(s->daemons, MHDDaemonWrapper_free);
|
2018-05-16 13:30:37 +02:00
|
|
|
#endif
|
2014-03-15 20:58:03 +01:00
|
|
|
|
2012-11-01 23:08:03 +01:00
|
|
|
assert(s->sources_size == 0 || s->sources);
|
2014-03-15 20:58:03 +01:00
|
|
|
for (i = 0; i < s->sources_size; i++)
|
2012-11-01 23:08:03 +01:00
|
|
|
remove_source(s, i);
|
|
|
|
free(s->sources);
|
|
|
|
|
2014-07-02 06:15:37 +02:00
|
|
|
writer_unref(s->_single_writer);
|
|
|
|
hashmap_free(s->writers);
|
|
|
|
|
2012-11-01 23:08:03 +01:00
|
|
|
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);
|
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
if (s == journal_remote_server_global)
|
|
|
|
journal_remote_server_global = NULL;
|
|
|
|
|
2012-11-01 23:08:03 +01:00
|
|
|
/* fds that we're listening on remain open... */
|
|
|
|
}
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
**********************************************************************
|
|
|
|
**********************************************************************/
|
|
|
|
|
2018-05-16 11:36:52 +02:00
|
|
|
int journal_remote_handle_raw_source(
|
|
|
|
sd_event_source *event,
|
|
|
|
int fd,
|
|
|
|
uint32_t revents,
|
|
|
|
RemoteServer *s) {
|
2012-11-01 23:08:03 +01:00
|
|
|
|
|
|
|
RemoteSource *source;
|
|
|
|
int r;
|
|
|
|
|
2015-03-13 05:02:28 +01:00
|
|
|
/* Returns 1 if there might be more data pending,
|
|
|
|
* 0 if data is currently exhausted, negative on error.
|
|
|
|
*/
|
|
|
|
|
2014-04-10 15:48:59 +02:00
|
|
|
assert(fd >= 0 && fd < (ssize_t) s->sources_size);
|
2012-11-01 23:08:03 +01:00
|
|
|
source = s->sources[fd];
|
2016-11-06 03:40:54 +01:00
|
|
|
assert(source->importer.fd == fd);
|
2012-11-01 23:08:03 +01:00
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
r = process_source(source, s->compress, s->seal);
|
2016-11-06 03:40:54 +01:00
|
|
|
if (journal_importer_eof(&source->importer)) {
|
2014-07-02 05:07:45 +02:00
|
|
|
size_t remaining;
|
|
|
|
|
2016-11-06 03:40:54 +01:00
|
|
|
log_debug("EOF reached with source %s (fd=%d)",
|
|
|
|
source->importer.name, source->importer.fd);
|
2014-07-02 05:07:45 +02:00
|
|
|
|
2016-11-06 03:40:54 +01:00
|
|
|
remaining = journal_importer_bytes_remaining(&source->importer);
|
2014-07-02 05:07:45 +02:00
|
|
|
if (remaining > 0)
|
2015-03-13 02:29:28 +01:00
|
|
|
log_notice("Premature EOF. %zu bytes lost.", remaining);
|
2016-11-06 03:40:54 +01:00
|
|
|
remove_source(s, source->importer.fd);
|
2015-03-13 02:29:28 +01:00
|
|
|
log_debug("%zu active sources remaining", s->active);
|
2014-06-22 19:36:31 +02:00
|
|
|
return 0;
|
2012-11-01 23:08:03 +01:00
|
|
|
} else if (r == -E2BIG) {
|
2018-12-07 10:48:10 +01:00
|
|
|
log_notice("Entry with too many fields, skipped");
|
|
|
|
return 1;
|
|
|
|
} else if (r == -ENOBUFS) {
|
2018-11-22 00:51:29 +01:00
|
|
|
log_notice("Entry too big, skipped");
|
2014-06-22 19:36:31 +02:00
|
|
|
return 1;
|
2015-03-13 13:51:55 +01:00
|
|
|
} else if (r == -EAGAIN) {
|
2014-06-22 19:36:31 +02:00
|
|
|
return 0;
|
|
|
|
} else if (r < 0) {
|
2015-03-13 02:29:28 +01:00
|
|
|
log_debug_errno(r, "Closing connection: %m");
|
2018-05-16 10:21:58 +02:00
|
|
|
remove_source(s, fd);
|
2014-06-22 19:36:31 +02:00
|
|
|
return 0;
|
|
|
|
} else
|
|
|
|
return 1;
|
2012-11-01 23:08:03 +01:00
|
|
|
}
|
|
|
|
|
2015-03-13 05:02:28 +01:00
|
|
|
static int dispatch_raw_source_until_block(sd_event_source *event,
|
|
|
|
void *userdata) {
|
|
|
|
RemoteSource *source = userdata;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
/* Make sure event stays around even if source is destroyed */
|
|
|
|
sd_event_source_ref(event);
|
|
|
|
|
2018-05-16 11:36:52 +02:00
|
|
|
r = journal_remote_handle_raw_source(event, source->importer.fd, EPOLLIN, journal_remote_server_global);
|
2015-03-13 05:02:28 +01:00
|
|
|
if (r != 1)
|
|
|
|
/* No more data for now */
|
|
|
|
sd_event_source_set_enabled(event, SD_EVENT_OFF);
|
|
|
|
|
|
|
|
sd_event_source_unref(event);
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dispatch_raw_source_event(sd_event_source *event,
|
|
|
|
int fd,
|
|
|
|
uint32_t revents,
|
|
|
|
void *userdata) {
|
|
|
|
RemoteSource *source = userdata;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(source->event);
|
|
|
|
assert(source->buffer_event);
|
|
|
|
|
2018-05-16 11:36:52 +02:00
|
|
|
r = journal_remote_handle_raw_source(event, fd, EPOLLIN, journal_remote_server_global);
|
2015-03-13 05:02:28 +01:00
|
|
|
if (r == 1)
|
|
|
|
/* Might have more data. We need to rerun the handler
|
|
|
|
* until we are sure the buffer is exhausted. */
|
|
|
|
sd_event_source_set_enabled(source->buffer_event, SD_EVENT_ON);
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2014-09-28 02:00:00 +02:00
|
|
|
static int dispatch_blocking_source_event(sd_event_source *event,
|
|
|
|
void *userdata) {
|
|
|
|
RemoteSource *source = userdata;
|
|
|
|
|
2018-05-16 11:36:52 +02:00
|
|
|
return journal_remote_handle_raw_source(event, source->importer.fd, EPOLLIN, journal_remote_server_global);
|
2014-09-28 02:00:00 +02:00
|
|
|
}
|
|
|
|
|
2019-04-10 19:50:53 +02:00
|
|
|
static int accept_connection(
|
|
|
|
const char* type,
|
|
|
|
int fd,
|
|
|
|
SocketAddress *addr,
|
|
|
|
char **hostname) {
|
|
|
|
|
|
|
|
_cleanup_close_ int fd2 = -1;
|
|
|
|
int r;
|
2012-11-01 23:08:03 +01:00
|
|
|
|
2014-03-15 20:58:03 +01:00
|
|
|
log_debug("Accepting new %s connection on fd:%d", type, fd);
|
|
|
|
fd2 = accept4(fd, &addr->sockaddr.sa, &addr->size, SOCK_NONBLOCK|SOCK_CLOEXEC);
|
2019-04-10 19:50:53 +02:00
|
|
|
if (fd2 < 0) {
|
|
|
|
if (ERRNO_IS_ACCEPT_AGAIN(errno))
|
|
|
|
return -EAGAIN;
|
|
|
|
|
2014-11-28 19:57:32 +01:00
|
|
|
return log_error_errno(errno, "accept() on fd:%d failed: %m", fd);
|
2019-04-10 19:50:53 +02:00
|
|
|
}
|
2012-11-01 23:08:03 +01:00
|
|
|
|
2014-03-15 20:58:03 +01:00
|
|
|
switch(socket_address_family(addr)) {
|
2012-11-01 23:08:03 +01:00
|
|
|
case AF_INET:
|
|
|
|
case AF_INET6: {
|
2014-06-22 19:36:31 +02:00
|
|
|
_cleanup_free_ char *a = NULL;
|
|
|
|
char *b;
|
2012-11-01 23:08:03 +01:00
|
|
|
|
2014-03-15 20:58:03 +01:00
|
|
|
r = socket_address_print(addr, &a);
|
2019-04-10 19:50:53 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "socket_address_print(): %m");
|
2012-11-01 23:08:03 +01:00
|
|
|
|
2014-06-22 19:36:31 +02:00
|
|
|
r = socknameinfo_pretty(&addr->sockaddr, addr->size, &b);
|
2019-04-10 19:50:53 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Resolving hostname failed: %m");
|
2014-06-22 19:36:31 +02:00
|
|
|
|
2015-03-13 02:29:28 +01:00
|
|
|
log_debug("Accepted %s %s connection from %s",
|
|
|
|
type,
|
|
|
|
socket_address_family(addr) == AF_INET ? "IP" : "IPv6",
|
|
|
|
a);
|
2014-03-15 20:58:03 +01:00
|
|
|
|
2014-06-22 19:36:31 +02:00
|
|
|
*hostname = b;
|
2019-04-10 19:50:53 +02:00
|
|
|
return TAKE_FD(fd2);
|
|
|
|
}
|
2014-06-22 19:36:31 +02:00
|
|
|
|
2012-11-01 23:08:03 +01:00
|
|
|
default:
|
2019-04-10 19:50:53 +02:00
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"Rejected %s connection with unsupported family %d",
|
|
|
|
type, socket_address_family(addr));
|
2012-11-01 23:08:03 +01:00
|
|
|
}
|
2014-03-15 20:58:03 +01:00
|
|
|
}
|
2012-11-01 23:08:03 +01:00
|
|
|
|
2019-04-10 19:50:53 +02:00
|
|
|
static int dispatch_raw_connection_event(
|
|
|
|
sd_event_source *event,
|
|
|
|
int fd,
|
|
|
|
uint32_t revents,
|
|
|
|
void *userdata) {
|
|
|
|
|
2014-03-15 20:58:03 +01:00
|
|
|
RemoteServer *s = userdata;
|
2014-10-13 04:27:20 +02:00
|
|
|
int fd2;
|
2014-03-15 20:58:03 +01:00
|
|
|
SocketAddress addr = {
|
|
|
|
.size = sizeof(union sockaddr_union),
|
|
|
|
.type = SOCK_STREAM,
|
|
|
|
};
|
2015-03-27 12:02:49 +01:00
|
|
|
char *hostname = NULL;
|
2012-11-01 23:08:03 +01:00
|
|
|
|
2014-06-22 19:36:31 +02:00
|
|
|
fd2 = accept_connection("raw", fd, &addr, &hostname);
|
2019-04-10 19:50:53 +02:00
|
|
|
if (fd2 == -EAGAIN)
|
|
|
|
return 0;
|
2014-03-15 20:58:03 +01:00
|
|
|
if (fd2 < 0)
|
|
|
|
return fd2;
|
2012-11-01 23:08:03 +01:00
|
|
|
|
2018-05-16 10:21:58 +02:00
|
|
|
return journal_remote_add_source(s, fd2, hostname, true);
|
2012-11-01 23:08:03 +01:00
|
|
|
}
|