X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fjournal-remote%2Fjournal-remote.c;h=ad87783510cff94a02d8f5c42ba5c005322c5c3f;hp=08de9d03ae90e2a9ae01fa47768dd955a6346b08;hb=22259a00fdb54dee818eeb1019421e2c516a330d;hpb=40780a626def76f611807b71994fdaafac4d2b7b diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c index 08de9d03a..ad8778351 100644 --- a/src/journal-remote/journal-remote.c +++ b/src/journal-remote/journal-remote.c @@ -52,9 +52,9 @@ #define REMOTE_JOURNAL_PATH "/var/log/journal/remote" -#define KEY_FILE CERTIFICATE_ROOT "/private/journal-remote.pem" -#define CERT_FILE CERTIFICATE_ROOT "/certs/journal-remote.pem" -#define TRUST_FILE CERTIFICATE_ROOT "/ca/trusted.pem" +#define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-remote.pem" +#define CERT_FILE CERTIFICATE_ROOT "/certs/journal-remote.pem" +#define TRUST_FILE CERTIFICATE_ROOT "/ca/trusted.pem" static char* arg_url = NULL; static char* arg_getter = NULL; @@ -149,9 +149,11 @@ static int spawn_getter(const char *getter, const char *url) { _cleanup_strv_free_ char **words = NULL; assert(getter); - words = strv_split_quoted(getter); - if (!words) - return log_oom(); + r = strv_split_quoted(&words, getter); + if (r < 0) { + log_error("Failed to split getter option: %s", strerror(-r)); + return r; + } r = strv_extend(&words, url); if (r < 0) { @@ -220,20 +222,14 @@ static int open_output(Writer *w, const char* host) { **********************************************************************/ static int init_writer_hashmap(RemoteServer *s) { - static const struct { - hash_func_t hash_func; - compare_func_t compare_func; - } functions[] = { - [JOURNAL_WRITE_SPLIT_NONE] = {trivial_hash_func, - trivial_compare_func}, - [JOURNAL_WRITE_SPLIT_HOST] = {string_hash_func, - string_compare_func}, + static const struct hash_ops *hash_ops[] = { + [JOURNAL_WRITE_SPLIT_NONE] = NULL, + [JOURNAL_WRITE_SPLIT_HOST] = &string_hash_ops, }; - assert(arg_split_mode >= 0 && arg_split_mode < (int) ELEMENTSOF(functions)); + assert(arg_split_mode >= 0 && arg_split_mode < (int) ELEMENTSOF(hash_ops)); - s->writers = hashmap_new(functions[arg_split_mode].hash_func, - functions[arg_split_mode].compare_func); + s->writers = hashmap_new(hash_ops[arg_split_mode]); if (!s->writers) return log_oom(); @@ -577,7 +573,6 @@ static int request_handler( log_error("MHD_get_connection_info failed: cannot get remote fd"); return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Cannot check remote address"); - return code; } fd = ci->connect_fd; @@ -694,7 +689,7 @@ static int setup_microhttpd_server(RemoteServer *s, goto error; } - r = hashmap_ensure_allocated(&s->daemons, uint64_hash_func, uint64_compare_func); + r = hashmap_ensure_allocated(&s->daemons, &uint64_hash_ops); if (r < 0) { log_oom(); goto error; @@ -793,11 +788,12 @@ static int fd_fd(const char *spec) { r = safe_atoi(spec, &fd); if (r < 0) return r; + if (fd < 0) + return -EINVAL; - return -1; + return fd; } - static int remoteserver_init(RemoteServer *s, const char* key, const char* cert, @@ -807,19 +803,26 @@ static int remoteserver_init(RemoteServer *s, assert(s); - if ((arg_listen_raw || arg_listen_http) && trust) { log_error("Option --trust makes all non-HTTPS connections untrusted."); return -EINVAL; } - sd_event_default(&s->events); + r = sd_event_default(&s->events); + if (r < 0) { + log_error("Failed to allocate event loop: %s", strerror(-r)); + return r; + } setup_signals(s); assert(server == NULL); server = s; + r = init_writer_hashmap(s); + if (r < 0) + return r; + n = sd_listen_fds(true); if (n < 0) { log_error("Failed to read listening file descriptors from environment: %s", @@ -943,10 +946,6 @@ static int remoteserver_init(RemoteServer *s, return -EINVAL; } - r = init_writer_hashmap(s); - if (r < 0) - return r; - if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE) { /* In this case we know what the writer will be called, so we can create it and verify that we can @@ -1122,40 +1121,34 @@ static int parse_config(void) { { "Remote", "ServerCertificateFile", config_parse_path, 0, &arg_cert }, { "Remote", "TrustedCertificateFile", config_parse_path, 0, &arg_trust }, {}}; - int r; - r = config_parse(NULL, PKGSYSCONFDIR "/journal-remote.conf", NULL, - "Remote\0", - config_item_table_lookup, items, - false, false, NULL); - if (r < 0) - log_error("Failed to parse configuration file: %s", strerror(-r)); - - return r; + return config_parse(NULL, PKGSYSCONFDIR "/journal-remote.conf", NULL, + "Remote\0", + config_item_table_lookup, items, + false, false, true, NULL); } static void help(void) { printf("%s [OPTIONS...] {FILE|-}...\n\n" "Write external journal events to journal file(s).\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" + " -h --help Show this help\n" + " --version Show package version\n" + " --url=URL Read events from systemd-journal-gatewayd at URL\n" + " --getter=COMMAND Read events from the output of COMMAND\n" + " --listen-raw=ADDR Listen for connections at ADDR\n" + " --listen-http=ADDR Listen for HTTP connections at ADDR\n" + " --listen-https=ADDR Listen for HTTPS connections at ADDR\n" " -o --output=FILE|DIR Write output to FILE or DIR/external-*.journal\n" - " --[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 (default:\n" - " \"" KEY_FILE "\")\n" - " --cert=FILENAME Specify certificate in PEM format (default:\n" - " \"" CERT_FILE "\")\n" - " --trust=FILENAME|all Specify CA certificate or disable checking (default:\n" - " \"" TRUST_FILE "\")\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" + " --compress[=BOOL] Use XZ-compression in the output journal (default: yes)\n" + " --seal[=BOOL] Use Event sealing in the output journal (default: no)\n" + " --key=FILENAME Specify key in PEM format (default:\n" + " \"" PRIV_KEY_FILE "\")\n" + " --cert=FILENAME Specify certificate in PEM format (default:\n" + " \"" CERT_FILE "\")\n" + " --trust=FILENAME|all Specify CA certificate or disable checking (default:\n" + " \"" TRUST_FILE "\")\n" + " --gnutls-log=CATEGORY...\n" + " Specify a list of gnutls logging categories\n" "\n" "Note: file descriptors from sd_listen_fds() will be consumed, too.\n" , program_invocation_short_name); @@ -1171,9 +1164,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_GETTER, ARG_SPLIT_MODE, ARG_COMPRESS, - ARG_NO_COMPRESS, ARG_SEAL, - ARG_NO_SEAL, ARG_KEY, ARG_CERT, ARG_TRUST, @@ -1190,10 +1181,8 @@ static int parse_argv(int argc, char *argv[]) { { "listen-https", required_argument, NULL, ARG_LISTEN_HTTPS }, { "output", required_argument, NULL, 'o' }, { "split-mode", required_argument, NULL, ARG_SPLIT_MODE }, - { "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 }, + { "compress", optional_argument, NULL, ARG_COMPRESS }, + { "seal", optional_argument, NULL, ARG_SEAL }, { "key", required_argument, NULL, ARG_KEY }, { "cert", required_argument, NULL, ARG_CERT }, { "trust", required_argument, NULL, ARG_TRUST }, @@ -1335,21 +1324,36 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_COMPRESS: - arg_compress = true; - break; - case ARG_NO_COMPRESS: - arg_compress = false; + if (optarg) { + r = parse_boolean(optarg); + if (r < 0) { + log_error("Failed to parse --compress= parameter."); + return -EINVAL; + } + + arg_compress = !!r; + } else + arg_compress = true; + break; + case ARG_SEAL: - arg_seal = true; - break; - case ARG_NO_SEAL: - arg_seal = false; + if (optarg) { + r = parse_boolean(optarg); + if (r < 0) { + log_error("Failed to parse --seal= parameter."); + return -EINVAL; + } + + arg_seal = !!r; + } else + arg_seal = true; + break; case ARG_GNUTLS_LOG: { #ifdef HAVE_GNUTLS - char *word, *state; + const char *word, *state; size_t size; FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) { @@ -1373,8 +1377,7 @@ static int parse_argv(int argc, char *argv[]) { return -EINVAL; default: - log_error("Unknown option code %c", c); - return -EINVAL; + assert_not_reached("Unknown option code."); } if (optind < argc) @@ -1423,10 +1426,10 @@ static int parse_argv(int argc, char *argv[]) { static int load_certificates(char **key, char **cert, char **trust) { int r; - r = read_full_file(arg_key ?: KEY_FILE, key, NULL); + r = read_full_file(arg_key ?: PRIV_KEY_FILE, key, NULL); if (r < 0) { log_error("Failed to read key from file '%s': %s", - arg_key ?: KEY_FILE, strerror(-r)); + arg_key ?: PRIV_KEY_FILE, strerror(-r)); return r; } @@ -1525,10 +1528,12 @@ int main(int argc, char **argv) { } } - server_destroy(&s); + sd_notifyf(false, + "STOPPING=1\n" + "STATUS=Shutting down after writing %" PRIu64 " entries...", s.event_count); log_info("Finishing after writing %" PRIu64 " entries", s.event_count); - sd_notify(false, "STATUS=Shutting down..."); + server_destroy(&s); free(arg_key); free(arg_cert);