| File: | build-scan/../src/journal-remote/journal-remote-main.c |
| Warning: | line 930, column 29 Null pointer passed to 1st parameter expecting 'nonnull' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
| 2 | ||||
| 3 | #include <getopt.h> | |||
| 4 | #include <unistd.h> | |||
| 5 | ||||
| 6 | #include "sd-daemon.h" | |||
| 7 | ||||
| 8 | #include "conf-parser.h" | |||
| 9 | #include "def.h" | |||
| 10 | #include "fd-util.h" | |||
| 11 | #include "fileio.h" | |||
| 12 | #include "journal-remote-write.h" | |||
| 13 | #include "journal-remote.h" | |||
| 14 | #include "process-util.h" | |||
| 15 | #include "signal-util.h" | |||
| 16 | #include "socket-util.h" | |||
| 17 | #include "stat-util.h" | |||
| 18 | #include "string-table.h" | |||
| 19 | #include "strv.h" | |||
| 20 | ||||
| 21 | #define PRIV_KEY_FILE"/etc/ssl" "/private/journal-remote.pem" CERTIFICATE_ROOT"/etc/ssl" "/private/journal-remote.pem" | |||
| 22 | #define CERT_FILE"/etc/ssl" "/certs/journal-remote.pem" CERTIFICATE_ROOT"/etc/ssl" "/certs/journal-remote.pem" | |||
| 23 | #define TRUST_FILE"/etc/ssl" "/ca/trusted.pem" CERTIFICATE_ROOT"/etc/ssl" "/ca/trusted.pem" | |||
| 24 | ||||
| 25 | static char* arg_url = NULL((void*)0); | |||
| 26 | static char* arg_getter = NULL((void*)0); | |||
| 27 | static char* arg_listen_raw = NULL((void*)0); | |||
| 28 | static char* arg_listen_http = NULL((void*)0); | |||
| 29 | static char* arg_listen_https = NULL((void*)0); | |||
| 30 | static char** arg_files = NULL((void*)0); | |||
| 31 | static int arg_compress = true1; | |||
| 32 | static int arg_seal = false0; | |||
| 33 | static int http_socket = -1, https_socket = -1; | |||
| 34 | static char** arg_gnutls_log = NULL((void*)0); | |||
| 35 | ||||
| 36 | static JournalWriteSplitMode arg_split_mode = _JOURNAL_WRITE_SPLIT_INVALID; | |||
| 37 | static char* arg_output = NULL((void*)0); | |||
| 38 | ||||
| 39 | static char *arg_key = NULL((void*)0); | |||
| 40 | static char *arg_cert = NULL((void*)0); | |||
| 41 | static char *arg_trust = NULL((void*)0); | |||
| 42 | static bool_Bool arg_trust_all = false0; | |||
| 43 | ||||
| 44 | static const char* const journal_write_split_mode_table[_JOURNAL_WRITE_SPLIT_MAX] = { | |||
| 45 | [JOURNAL_WRITE_SPLIT_NONE] = "none", | |||
| 46 | [JOURNAL_WRITE_SPLIT_HOST] = "host", | |||
| 47 | }; | |||
| 48 | ||||
| 49 | DEFINE_PRIVATE_STRING_TABLE_LOOKUP(journal_write_split_mode, JournalWriteSplitMode)static const char *journal_write_split_mode_to_string(JournalWriteSplitMode i) { if (i < 0 || i >= (JournalWriteSplitMode) __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (journal_write_split_mode_table), typeof(&*(journal_write_split_mode_table ))), sizeof(journal_write_split_mode_table)/sizeof((journal_write_split_mode_table )[0]), ((void)0)))) return ((void*)0); return journal_write_split_mode_table [i]; } static JournalWriteSplitMode journal_write_split_mode_from_string (const char *s) { return (JournalWriteSplitMode) string_table_lookup (journal_write_split_mode_table, __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(journal_write_split_mode_table ), typeof(&*(journal_write_split_mode_table))), sizeof(journal_write_split_mode_table )/sizeof((journal_write_split_mode_table)[0]), ((void)0))), s ); }; | |||
| 50 | static DEFINE_CONFIG_PARSE_ENUM(config_parse_write_split_mode,int config_parse_write_split_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line , const char *lvalue, int ltype, const char *rvalue, void *data , void *userdata) { JournalWriteSplitMode *i = data, x; do { if ((__builtin_expect(!!(!(filename)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("filename"), "../src/journal-remote/journal-remote-main.c" , 53, __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect (!!(!(lvalue)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("lvalue"), "../src/journal-remote/journal-remote-main.c", 53 , __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect (!!(!(rvalue)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("rvalue"), "../src/journal-remote/journal-remote-main.c", 53 , __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect (!!(!(data)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ( "data"), "../src/journal-remote/journal-remote-main.c", 53, __PRETTY_FUNCTION__ ); } while (0); x = journal_write_split_mode_from_string(rvalue ); if (x < 0) { ({ int _level = (3), _e = (0); (log_get_max_level_realm (LOG_REALM_SYSTEMD) >= ((_level) & 0x07)) ? log_syntax_internal (unit, _level, filename, line, _e, "../src/journal-remote/journal-remote-main.c" , 53, __func__, "Failed to parse split mode setting" ", ignoring: %s" , rvalue) : -abs(_e); }); return 0; } *i = x; return 0; } | |||
| 51 | journal_write_split_mode,int config_parse_write_split_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line , const char *lvalue, int ltype, const char *rvalue, void *data , void *userdata) { JournalWriteSplitMode *i = data, x; do { if ((__builtin_expect(!!(!(filename)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("filename"), "../src/journal-remote/journal-remote-main.c" , 53, __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect (!!(!(lvalue)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("lvalue"), "../src/journal-remote/journal-remote-main.c", 53 , __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect (!!(!(rvalue)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("rvalue"), "../src/journal-remote/journal-remote-main.c", 53 , __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect (!!(!(data)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ( "data"), "../src/journal-remote/journal-remote-main.c", 53, __PRETTY_FUNCTION__ ); } while (0); x = journal_write_split_mode_from_string(rvalue ); if (x < 0) { ({ int _level = (3), _e = (0); (log_get_max_level_realm (LOG_REALM_SYSTEMD) >= ((_level) & 0x07)) ? log_syntax_internal (unit, _level, filename, line, _e, "../src/journal-remote/journal-remote-main.c" , 53, __func__, "Failed to parse split mode setting" ", ignoring: %s" , rvalue) : -abs(_e); }); return 0; } *i = x; return 0; } | |||
| 52 | JournalWriteSplitMode,int config_parse_write_split_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line , const char *lvalue, int ltype, const char *rvalue, void *data , void *userdata) { JournalWriteSplitMode *i = data, x; do { if ((__builtin_expect(!!(!(filename)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("filename"), "../src/journal-remote/journal-remote-main.c" , 53, __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect (!!(!(lvalue)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("lvalue"), "../src/journal-remote/journal-remote-main.c", 53 , __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect (!!(!(rvalue)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("rvalue"), "../src/journal-remote/journal-remote-main.c", 53 , __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect (!!(!(data)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ( "data"), "../src/journal-remote/journal-remote-main.c", 53, __PRETTY_FUNCTION__ ); } while (0); x = journal_write_split_mode_from_string(rvalue ); if (x < 0) { ({ int _level = (3), _e = (0); (log_get_max_level_realm (LOG_REALM_SYSTEMD) >= ((_level) & 0x07)) ? log_syntax_internal (unit, _level, filename, line, _e, "../src/journal-remote/journal-remote-main.c" , 53, __func__, "Failed to parse split mode setting" ", ignoring: %s" , rvalue) : -abs(_e); }); return 0; } *i = x; return 0; } | |||
| 53 | "Failed to parse split mode setting")int config_parse_write_split_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line , const char *lvalue, int ltype, const char *rvalue, void *data , void *userdata) { JournalWriteSplitMode *i = data, x; do { if ((__builtin_expect(!!(!(filename)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("filename"), "../src/journal-remote/journal-remote-main.c" , 53, __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect (!!(!(lvalue)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("lvalue"), "../src/journal-remote/journal-remote-main.c", 53 , __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect (!!(!(rvalue)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("rvalue"), "../src/journal-remote/journal-remote-main.c", 53 , __PRETTY_FUNCTION__); } while (0); do { if ((__builtin_expect (!!(!(data)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ( "data"), "../src/journal-remote/journal-remote-main.c", 53, __PRETTY_FUNCTION__ ); } while (0); x = journal_write_split_mode_from_string(rvalue ); if (x < 0) { ({ int _level = (3), _e = (0); (log_get_max_level_realm (LOG_REALM_SYSTEMD) >= ((_level) & 0x07)) ? log_syntax_internal (unit, _level, filename, line, _e, "../src/journal-remote/journal-remote-main.c" , 53, __func__, "Failed to parse split mode setting" ", ignoring: %s" , rvalue) : -abs(_e); }); return 0; } *i = x; return 0; }; | |||
| 54 | ||||
| 55 | /********************************************************************** | |||
| 56 | ********************************************************************** | |||
| 57 | **********************************************************************/ | |||
| 58 | ||||
| 59 | static int spawn_child(const char* child, char** argv) { | |||
| 60 | pid_t child_pid; | |||
| 61 | int fd[2], r; | |||
| 62 | ||||
| 63 | if (pipe(fd) < 0) | |||
| 64 | return log_error_errno(errno, "Failed to create pager pipe: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal-remote/journal-remote-main.c" , 64, __func__, "Failed to create pager pipe: %m") : -abs(_e) ; }); | |||
| 65 | ||||
| 66 | r = safe_fork("(remote)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &child_pid); | |||
| 67 | if (r < 0) { | |||
| 68 | safe_close_pair(fd); | |||
| 69 | return r; | |||
| 70 | } | |||
| 71 | ||||
| 72 | /* In the child */ | |||
| 73 | if (r == 0) { | |||
| 74 | safe_close(fd[0]); | |||
| 75 | ||||
| 76 | r = rearrange_stdio(STDIN_FILENO0, fd[1], STDERR_FILENO2); | |||
| 77 | if (r < 0) { | |||
| 78 | log_error_errno(r, "Failed to dup pipe to stdout: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 78, __func__ , "Failed to dup pipe to stdout: %m") : -abs(_e); }); | |||
| 79 | _exit(EXIT_FAILURE1); | |||
| 80 | } | |||
| 81 | ||||
| 82 | execvp(child, argv); | |||
| 83 | log_error_errno(errno, "Failed to exec child %s: %m", child)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal-remote/journal-remote-main.c" , 83, __func__, "Failed to exec child %s: %m", child) : -abs( _e); }); | |||
| 84 | _exit(EXIT_FAILURE1); | |||
| 85 | } | |||
| 86 | ||||
| 87 | safe_close(fd[1]); | |||
| 88 | ||||
| 89 | r = fd_nonblock(fd[0], true1); | |||
| 90 | if (r < 0) | |||
| 91 | log_warning_errno(errno, "Failed to set child pipe to non-blocking: %m")({ int _level = ((4)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal-remote/journal-remote-main.c" , 91, __func__, "Failed to set child pipe to non-blocking: %m" ) : -abs(_e); }); | |||
| 92 | ||||
| 93 | return fd[0]; | |||
| 94 | } | |||
| 95 | ||||
| 96 | static int spawn_curl(const char* url) { | |||
| 97 | char **argv = STRV_MAKE("curl",((char**) ((const char*[]) { "curl", "-HAccept: application/vnd.fdo.journal" , "--silent", "--show-error", url, ((void*)0) })) | |||
| 98 | "-HAccept: application/vnd.fdo.journal",((char**) ((const char*[]) { "curl", "-HAccept: application/vnd.fdo.journal" , "--silent", "--show-error", url, ((void*)0) })) | |||
| 99 | "--silent",((char**) ((const char*[]) { "curl", "-HAccept: application/vnd.fdo.journal" , "--silent", "--show-error", url, ((void*)0) })) | |||
| 100 | "--show-error",((char**) ((const char*[]) { "curl", "-HAccept: application/vnd.fdo.journal" , "--silent", "--show-error", url, ((void*)0) })) | |||
| 101 | url)((char**) ((const char*[]) { "curl", "-HAccept: application/vnd.fdo.journal" , "--silent", "--show-error", url, ((void*)0) })); | |||
| 102 | int r; | |||
| 103 | ||||
| 104 | r = spawn_child("curl", argv); | |||
| 105 | if (r < 0) | |||
| 106 | log_error_errno(r, "Failed to spawn curl: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 106, __func__ , "Failed to spawn curl: %m") : -abs(_e); }); | |||
| 107 | return r; | |||
| 108 | } | |||
| 109 | ||||
| 110 | static int spawn_getter(const char *getter) { | |||
| 111 | int r; | |||
| 112 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **words = NULL((void*)0); | |||
| 113 | ||||
| 114 | assert(getter)do { if ((__builtin_expect(!!(!(getter)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("getter"), "../src/journal-remote/journal-remote-main.c" , 114, __PRETTY_FUNCTION__); } while (0); | |||
| 115 | r = strv_split_extract(&words, getter, WHITESPACE" \t\n\r", EXTRACT_QUOTES); | |||
| 116 | if (r < 0) | |||
| 117 | return log_error_errno(r, "Failed to split getter option: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 117, __func__ , "Failed to split getter option: %m") : -abs(_e); }); | |||
| 118 | ||||
| 119 | r = spawn_child(words[0], words); | |||
| 120 | if (r < 0) | |||
| 121 | log_error_errno(r, "Failed to spawn getter %s: %m", getter)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 121, __func__ , "Failed to spawn getter %s: %m", getter) : -abs(_e); }); | |||
| 122 | ||||
| 123 | return r; | |||
| 124 | } | |||
| 125 | ||||
| 126 | /********************************************************************** | |||
| 127 | ********************************************************************** | |||
| 128 | **********************************************************************/ | |||
| 129 | ||||
| 130 | static int null_timer_event_handler(sd_event_source *s, | |||
| 131 | uint64_t usec, | |||
| 132 | void *userdata); | |||
| 133 | static int dispatch_http_event(sd_event_source *event, | |||
| 134 | int fd, | |||
| 135 | uint32_t revents, | |||
| 136 | void *userdata); | |||
| 137 | ||||
| 138 | static int request_meta(void **connection_cls, int fd, char *hostname) { | |||
| 139 | RemoteSource *source; | |||
| 140 | Writer *writer; | |||
| 141 | int r; | |||
| 142 | ||||
| 143 | assert(connection_cls)do { if ((__builtin_expect(!!(!(connection_cls)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("connection_cls"), "../src/journal-remote/journal-remote-main.c" , 143, __PRETTY_FUNCTION__); } while (0); | |||
| 144 | if (*connection_cls) | |||
| 145 | return 0; | |||
| 146 | ||||
| 147 | r = journal_remote_get_writer(journal_remote_server_global, hostname, &writer); | |||
| 148 | if (r < 0) | |||
| 149 | return log_warning_errno(r, "Failed to get writer for source %s: %m",({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 150, __func__ , "Failed to get writer for source %s: %m", hostname) : -abs( _e); }) | |||
| 150 | hostname)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 150, __func__ , "Failed to get writer for source %s: %m", hostname) : -abs( _e); }); | |||
| 151 | ||||
| 152 | source = source_new(fd, true1, hostname, writer); | |||
| 153 | if (!source) { | |||
| 154 | writer_unref(writer); | |||
| 155 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-remote-main.c" , 155, __func__); | |||
| 156 | } | |||
| 157 | ||||
| 158 | log_debug("Added RemoteSource as connection metadata %p", source)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 158, __func__ , "Added RemoteSource as connection metadata %p", source) : - abs(_e); }); | |||
| 159 | ||||
| 160 | *connection_cls = source; | |||
| 161 | return 0; | |||
| 162 | } | |||
| 163 | ||||
| 164 | static void request_meta_free(void *cls, | |||
| 165 | struct MHD_Connection *connection, | |||
| 166 | void **connection_cls, | |||
| 167 | enum MHD_RequestTerminationCode toe) { | |||
| 168 | RemoteSource *s; | |||
| 169 | ||||
| 170 | assert(connection_cls)do { if ((__builtin_expect(!!(!(connection_cls)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("connection_cls"), "../src/journal-remote/journal-remote-main.c" , 170, __PRETTY_FUNCTION__); } while (0); | |||
| 171 | s = *connection_cls; | |||
| 172 | ||||
| 173 | if (s) { | |||
| 174 | log_debug("Cleaning up connection metadata %p", s)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 174, __func__ , "Cleaning up connection metadata %p", s) : -abs(_e); }); | |||
| 175 | source_free(s); | |||
| 176 | *connection_cls = NULL((void*)0); | |||
| 177 | } | |||
| 178 | } | |||
| 179 | ||||
| 180 | static int process_http_upload( | |||
| 181 | struct MHD_Connection *connection, | |||
| 182 | const char *upload_data, | |||
| 183 | size_t *upload_data_size, | |||
| 184 | RemoteSource *source) { | |||
| 185 | ||||
| 186 | bool_Bool finished = false0; | |||
| 187 | size_t remaining; | |||
| 188 | int r; | |||
| 189 | ||||
| 190 | assert(source)do { if ((__builtin_expect(!!(!(source)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("source"), "../src/journal-remote/journal-remote-main.c" , 190, __PRETTY_FUNCTION__); } while (0); | |||
| 191 | ||||
| 192 | log_trace("%s: connection %p, %zu bytes",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 193, __func__ , "%s: connection %p, %zu bytes", __func__, connection, *upload_data_size ) : -abs(_e); }) | |||
| 193 | __func__, connection, *upload_data_size)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 193, __func__ , "%s: connection %p, %zu bytes", __func__, connection, *upload_data_size ) : -abs(_e); }); | |||
| 194 | ||||
| 195 | if (*upload_data_size) { | |||
| 196 | log_trace("Received %zu bytes", *upload_data_size)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 196, __func__ , "Received %zu bytes", *upload_data_size) : -abs(_e); }); | |||
| 197 | ||||
| 198 | r = journal_importer_push_data(&source->importer, | |||
| 199 | upload_data, *upload_data_size); | |||
| 200 | if (r < 0) | |||
| 201 | return mhd_respond_oom(connection); | |||
| 202 | ||||
| 203 | *upload_data_size = 0; | |||
| 204 | } else | |||
| 205 | finished = true1; | |||
| 206 | ||||
| 207 | for (;;) { | |||
| 208 | r = process_source(source, | |||
| 209 | journal_remote_server_global->compress, | |||
| 210 | journal_remote_server_global->seal); | |||
| 211 | if (r == -EAGAIN11) | |||
| 212 | break; | |||
| 213 | if (r < 0) { | |||
| 214 | if (r == -ENOBUFS105) | |||
| 215 | log_warning_errno(r, "Entry is above the maximum of %u, aborting connection %p.",({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 216, __func__ , "Entry is above the maximum of %u, aborting connection %p." , (1024*1024*768u), connection) : -abs(_e); }) | |||
| 216 | DATA_SIZE_MAX, connection)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 216, __func__ , "Entry is above the maximum of %u, aborting connection %p." , (1024*1024*768u), connection) : -abs(_e); }); | |||
| 217 | else if (r == -E2BIG7) | |||
| 218 | log_warning_errno(r, "Entry with more fields than the maximum of %u, aborting connection %p.",({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 219, __func__ , "Entry with more fields than the maximum of %u, aborting connection %p." , 1024, connection) : -abs(_e); }) | |||
| 219 | ENTRY_FIELD_COUNT_MAX, connection)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 219, __func__ , "Entry with more fields than the maximum of %u, aborting connection %p." , 1024, connection) : -abs(_e); }); | |||
| 220 | else | |||
| 221 | log_warning_errno(r, "Failed to process data, aborting connection %p: %m",({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 222, __func__ , "Failed to process data, aborting connection %p: %m", connection ) : -abs(_e); }) | |||
| 222 | connection)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 222, __func__ , "Failed to process data, aborting connection %p: %m", connection ) : -abs(_e); }); | |||
| 223 | return MHD_NO; | |||
| 224 | } | |||
| 225 | } | |||
| 226 | ||||
| 227 | if (!finished) | |||
| 228 | return MHD_YES; | |||
| 229 | ||||
| 230 | /* The upload is finished */ | |||
| 231 | ||||
| 232 | remaining = journal_importer_bytes_remaining(&source->importer); | |||
| 233 | if (remaining > 0) { | |||
| 234 | log_warning("Premature EOF byte. %zu bytes lost.", remaining)({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 234, __func__ , "Premature EOF byte. %zu bytes lost.", remaining) : -abs(_e ); }); | |||
| 235 | return mhd_respondf(connection, | |||
| 236 | 0, MHD_HTTP_EXPECTATION_FAILED417, | |||
| 237 | "Premature EOF. %zu bytes of trailing data not processed.", | |||
| 238 | remaining); | |||
| 239 | } | |||
| 240 | ||||
| 241 | return mhd_respond(connection, MHD_HTTP_ACCEPTED202, "OK."); | |||
| 242 | }; | |||
| 243 | ||||
| 244 | static mhd_resultenum MHD_Result request_handler( | |||
| 245 | void *cls, | |||
| 246 | struct MHD_Connection *connection, | |||
| 247 | const char *url, | |||
| 248 | const char *method, | |||
| 249 | const char *version, | |||
| 250 | const char *upload_data, | |||
| 251 | size_t *upload_data_size, | |||
| 252 | void **connection_cls) { | |||
| 253 | ||||
| 254 | const char *header; | |||
| 255 | int r, code, fd; | |||
| 256 | _cleanup_free___attribute__((cleanup(freep))) char *hostname = NULL((void*)0); | |||
| 257 | bool_Bool chunked = false0; | |||
| 258 | size_t len; | |||
| 259 | ||||
| 260 | assert(connection)do { if ((__builtin_expect(!!(!(connection)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("connection"), "../src/journal-remote/journal-remote-main.c" , 260, __PRETTY_FUNCTION__); } while (0); | |||
| 261 | assert(connection_cls)do { if ((__builtin_expect(!!(!(connection_cls)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("connection_cls"), "../src/journal-remote/journal-remote-main.c" , 261, __PRETTY_FUNCTION__); } while (0); | |||
| 262 | assert(url)do { if ((__builtin_expect(!!(!(url)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("url"), "../src/journal-remote/journal-remote-main.c" , 262, __PRETTY_FUNCTION__); } while (0); | |||
| 263 | assert(method)do { if ((__builtin_expect(!!(!(method)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("method"), "../src/journal-remote/journal-remote-main.c" , 263, __PRETTY_FUNCTION__); } while (0); | |||
| 264 | ||||
| 265 | log_trace("Handling a connection %s %s %s", method, url, version)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 265, __func__ , "Handling a connection %s %s %s", method, url, version) : - abs(_e); }); | |||
| 266 | ||||
| 267 | if (*connection_cls) | |||
| 268 | return process_http_upload(connection, | |||
| 269 | upload_data, upload_data_size, | |||
| 270 | *connection_cls); | |||
| 271 | ||||
| 272 | if (!streq(method, "POST")(strcmp((method),("POST")) == 0)) | |||
| 273 | return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE406, "Unsupported method."); | |||
| 274 | ||||
| 275 | if (!streq(url, "/upload")(strcmp((url),("/upload")) == 0)) | |||
| 276 | return mhd_respond(connection, MHD_HTTP_NOT_FOUND404, "Not found."); | |||
| 277 | ||||
| 278 | header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-Type"); | |||
| 279 | if (!header || !streq(header, "application/vnd.fdo.journal")(strcmp((header),("application/vnd.fdo.journal")) == 0)) | |||
| 280 | return mhd_respond(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE415, | |||
| 281 | "Content-Type: application/vnd.fdo.journal is required."); | |||
| 282 | ||||
| 283 | header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Transfer-Encoding"); | |||
| 284 | if (header) { | |||
| 285 | if (!strcaseeq(header, "chunked")(strcasecmp((header),("chunked")) == 0)) | |||
| 286 | return mhd_respondf(connection, 0, MHD_HTTP_BAD_REQUEST400, | |||
| 287 | "Unsupported Transfer-Encoding type: %s", header); | |||
| 288 | ||||
| 289 | chunked = true1; | |||
| 290 | } | |||
| 291 | ||||
| 292 | header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-Length"); | |||
| 293 | if (header) { | |||
| 294 | if (chunked) | |||
| 295 | return mhd_respond(connection, MHD_HTTP_BAD_REQUEST400, | |||
| 296 | "Content-Length must not specified when Transfer-Encoding type is 'chuncked'"); | |||
| 297 | ||||
| 298 | r = safe_atozu(header, &len); | |||
| 299 | if (r < 0) | |||
| 300 | return mhd_respondf(connection, r, MHD_HTTP_LENGTH_REQUIRED411, | |||
| 301 | "Content-Length: %s cannot be parsed: %m", header); | |||
| 302 | ||||
| 303 | if (len > ENTRY_SIZE_MAX(1024*1024*770u)) | |||
| 304 | /* When serialized, an entry of maximum size might be slightly larger, | |||
| 305 | * so this does not correspond exactly to the limit in journald. Oh well. | |||
| 306 | */ | |||
| 307 | return mhd_respondf(connection, 0, MHD_HTTP_PAYLOAD_TOO_LARGE413, | |||
| 308 | "Payload larger than maximum size of %u bytes", ENTRY_SIZE_MAX(1024*1024*770u)); | |||
| 309 | } | |||
| 310 | ||||
| 311 | { | |||
| 312 | const union MHD_ConnectionInfo *ci; | |||
| 313 | ||||
| 314 | ci = MHD_get_connection_info(connection, | |||
| 315 | MHD_CONNECTION_INFO_CONNECTION_FD); | |||
| 316 | if (!ci) { | |||
| 317 | log_error("MHD_get_connection_info failed: cannot get remote fd")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 317, __func__ , "MHD_get_connection_info failed: cannot get remote fd") : - abs(_e); }); | |||
| 318 | return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR500, | |||
| 319 | "Cannot check remote address."); | |||
| 320 | } | |||
| 321 | ||||
| 322 | fd = ci->connect_fd; | |||
| 323 | assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/journal-remote/journal-remote-main.c" , 323, __PRETTY_FUNCTION__); } while (0); | |||
| 324 | } | |||
| 325 | ||||
| 326 | if (journal_remote_server_global->check_trust) { | |||
| 327 | r = check_permissions(connection, &code, &hostname); | |||
| 328 | if (r < 0) | |||
| 329 | return code; | |||
| 330 | } else { | |||
| 331 | r = getpeername_pretty(fd, false0, &hostname); | |||
| 332 | if (r < 0) | |||
| 333 | return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR500, | |||
| 334 | "Cannot check remote hostname."); | |||
| 335 | } | |||
| 336 | ||||
| 337 | assert(hostname)do { if ((__builtin_expect(!!(!(hostname)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("hostname"), "../src/journal-remote/journal-remote-main.c" , 337, __PRETTY_FUNCTION__); } while (0); | |||
| 338 | ||||
| 339 | r = request_meta(connection_cls, fd, hostname); | |||
| 340 | if (r == -ENOMEM12) | |||
| 341 | return respond_oom(connection)log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-remote-main.c" , 341, __func__), mhd_respond_oom(connection); | |||
| 342 | else if (r < 0) | |||
| 343 | return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR500, "%m"); | |||
| 344 | ||||
| 345 | hostname = NULL((void*)0); | |||
| 346 | return MHD_YES; | |||
| 347 | } | |||
| 348 | ||||
| 349 | static int setup_microhttpd_server(RemoteServer *s, | |||
| 350 | int fd, | |||
| 351 | const char *key, | |||
| 352 | const char *cert, | |||
| 353 | const char *trust) { | |||
| 354 | struct MHD_OptionItem opts[] = { | |||
| 355 | { MHD_OPTION_NOTIFY_COMPLETED, (intptr_t) request_meta_free}, | |||
| 356 | { MHD_OPTION_EXTERNAL_LOGGER, (intptr_t) microhttpd_logger}, | |||
| 357 | { MHD_OPTION_LISTEN_SOCKET, fd}, | |||
| 358 | { MHD_OPTION_CONNECTION_MEMORY_LIMIT, 128*1024}, | |||
| 359 | { MHD_OPTION_END}, | |||
| 360 | { MHD_OPTION_END}, | |||
| 361 | { MHD_OPTION_END}, | |||
| 362 | { MHD_OPTION_END}, | |||
| 363 | { MHD_OPTION_END}}; | |||
| 364 | int opts_pos = 4; | |||
| 365 | int flags = | |||
| 366 | MHD_USE_DEBUG | | |||
| 367 | MHD_USE_DUAL_STACK | | |||
| 368 | MHD_USE_EPOLLMHD_USE_EPOLL_LINUX_ONLY | | |||
| 369 | MHD_USE_ITCMHD_USE_PIPE_FOR_SHUTDOWN; | |||
| 370 | ||||
| 371 | const union MHD_DaemonInfo *info; | |||
| 372 | int r, epoll_fd; | |||
| 373 | MHDDaemonWrapper *d; | |||
| 374 | ||||
| 375 | assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/journal-remote/journal-remote-main.c" , 375, __PRETTY_FUNCTION__); } while (0); | |||
| 376 | ||||
| 377 | r = fd_nonblock(fd, true1); | |||
| 378 | if (r < 0) | |||
| 379 | return log_error_errno(r, "Failed to make fd:%d nonblocking: %m", fd)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 379, __func__ , "Failed to make fd:%d nonblocking: %m", fd) : -abs(_e); }); | |||
| 380 | ||||
| 381 | /* MHD_OPTION_STRICT_FOR_CLIENT is introduced in microhttpd 0.9.54, | |||
| 382 | * and MHD_USE_PEDANTIC_CHECKS will be deprecated in future. | |||
| 383 | * If MHD_USE_PEDANTIC_CHECKS is '#define'd, then it is deprecated | |||
| 384 | * and we should use MHD_OPTION_STRICT_FOR_CLIENT. On the other hand, | |||
| 385 | * if MHD_USE_PEDANTIC_CHECKS is not '#define'd, then it is not | |||
| 386 | * deprecated yet and there exists an enum element with the same name. | |||
| 387 | * So we can safely use it. */ | |||
| 388 | #ifdef MHD_USE_PEDANTIC_CHECKS | |||
| 389 | opts[opts_pos++] = (struct MHD_OptionItem) | |||
| 390 | {MHD_OPTION_STRICT_FOR_CLIENT, 1}; | |||
| 391 | #else | |||
| 392 | flags |= MHD_USE_PEDANTIC_CHECKS; | |||
| 393 | #endif | |||
| 394 | ||||
| 395 | if (key) { | |||
| 396 | assert(cert)do { if ((__builtin_expect(!!(!(cert)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("cert"), "../src/journal-remote/journal-remote-main.c" , 396, __PRETTY_FUNCTION__); } while (0); | |||
| 397 | ||||
| 398 | opts[opts_pos++] = (struct MHD_OptionItem) | |||
| 399 | {MHD_OPTION_HTTPS_MEM_KEY, 0, (char*) key}; | |||
| 400 | opts[opts_pos++] = (struct MHD_OptionItem) | |||
| 401 | {MHD_OPTION_HTTPS_MEM_CERT, 0, (char*) cert}; | |||
| 402 | ||||
| 403 | flags |= MHD_USE_TLSMHD_USE_SSL; | |||
| 404 | ||||
| 405 | if (trust) | |||
| 406 | opts[opts_pos++] = (struct MHD_OptionItem) | |||
| 407 | {MHD_OPTION_HTTPS_MEM_TRUST, 0, (char*) trust}; | |||
| 408 | } | |||
| 409 | ||||
| 410 | d = new(MHDDaemonWrapper, 1)((MHDDaemonWrapper*) malloc_multiply(sizeof(MHDDaemonWrapper) , (1))); | |||
| 411 | if (!d) | |||
| 412 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-remote-main.c" , 412, __func__); | |||
| 413 | ||||
| 414 | d->fd = (uint64_t) fd; | |||
| 415 | ||||
| 416 | d->daemon = MHD_start_daemon(flags, 0, | |||
| 417 | NULL((void*)0), NULL((void*)0), | |||
| 418 | request_handler, NULL((void*)0), | |||
| 419 | MHD_OPTION_ARRAY, opts, | |||
| 420 | MHD_OPTION_END); | |||
| 421 | if (!d->daemon) { | |||
| 422 | log_error("Failed to start µhttp daemon")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 422, __func__ , "Failed to start µhttp daemon") : -abs(_e); }); | |||
| 423 | r = -EINVAL22; | |||
| 424 | goto error; | |||
| 425 | } | |||
| 426 | ||||
| 427 | log_debug("Started MHD %s daemon on fd:%d (wrapper @ %p)",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 428, __func__ , "Started MHD %s daemon on fd:%d (wrapper @ %p)", key ? "HTTPS" : "HTTP", fd, d) : -abs(_e); }) | |||
| 428 | key ? "HTTPS" : "HTTP", fd, d)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 428, __func__ , "Started MHD %s daemon on fd:%d (wrapper @ %p)", key ? "HTTPS" : "HTTP", fd, d) : -abs(_e); }); | |||
| 429 | ||||
| 430 | info = MHD_get_daemon_info(d->daemon, MHD_DAEMON_INFO_EPOLL_FD_LINUX_ONLY); | |||
| 431 | if (!info) { | |||
| 432 | log_error("µhttp returned NULL daemon info")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 432, __func__ , "µhttp returned NULL daemon info") : -abs(_e); }); | |||
| 433 | r = -EOPNOTSUPP95; | |||
| 434 | goto error; | |||
| 435 | } | |||
| 436 | ||||
| 437 | epoll_fd = info->listen_fd; | |||
| 438 | if (epoll_fd < 0) { | |||
| 439 | log_error("µhttp epoll fd is invalid")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 439, __func__ , "µhttp epoll fd is invalid") : -abs(_e); }); | |||
| 440 | r = -EUCLEAN117; | |||
| 441 | goto error; | |||
| 442 | } | |||
| 443 | ||||
| 444 | r = sd_event_add_io(s->events, &d->io_event, | |||
| 445 | epoll_fd, EPOLLINEPOLLIN, | |||
| 446 | dispatch_http_event, d); | |||
| 447 | if (r < 0) { | |||
| 448 | log_error_errno(r, "Failed to add event callback: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 448, __func__ , "Failed to add event callback: %m") : -abs(_e); }); | |||
| 449 | goto error; | |||
| 450 | } | |||
| 451 | ||||
| 452 | r = sd_event_source_set_description(d->io_event, "io_event"); | |||
| 453 | if (r < 0) { | |||
| 454 | log_error_errno(r, "Failed to set source name: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 454, __func__ , "Failed to set source name: %m") : -abs(_e); }); | |||
| 455 | goto error; | |||
| 456 | } | |||
| 457 | ||||
| 458 | r = sd_event_add_time(s->events, &d->timer_event, | |||
| 459 | CLOCK_MONOTONIC1, (uint64_t) -1, 0, | |||
| 460 | null_timer_event_handler, d); | |||
| 461 | if (r < 0) { | |||
| 462 | log_error_errno(r, "Failed to add timer_event: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 462, __func__ , "Failed to add timer_event: %m") : -abs(_e); }); | |||
| 463 | goto error; | |||
| 464 | } | |||
| 465 | ||||
| 466 | r = sd_event_source_set_description(d->timer_event, "timer_event"); | |||
| 467 | if (r < 0) { | |||
| 468 | log_error_errno(r, "Failed to set source name: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 468, __func__ , "Failed to set source name: %m") : -abs(_e); }); | |||
| 469 | goto error; | |||
| 470 | } | |||
| 471 | ||||
| 472 | r = hashmap_ensure_allocated(&s->daemons, &uint64_hash_ops)internal_hashmap_ensure_allocated(&s->daemons, &uint64_hash_ops ); | |||
| 473 | if (r < 0) { | |||
| 474 | log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-remote-main.c" , 474, __func__); | |||
| 475 | goto error; | |||
| 476 | } | |||
| 477 | ||||
| 478 | r = hashmap_put(s->daemons, &d->fd, d); | |||
| 479 | if (r < 0) { | |||
| 480 | log_error_errno(r, "Failed to add daemon to hashmap: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 480, __func__ , "Failed to add daemon to hashmap: %m") : -abs(_e); }); | |||
| 481 | goto error; | |||
| 482 | } | |||
| 483 | ||||
| 484 | s->active++; | |||
| 485 | return 0; | |||
| 486 | ||||
| 487 | error: | |||
| 488 | MHD_stop_daemon(d->daemon); | |||
| 489 | free(d->daemon); | |||
| 490 | free(d); | |||
| 491 | return r; | |||
| 492 | } | |||
| 493 | ||||
| 494 | static int setup_microhttpd_socket(RemoteServer *s, | |||
| 495 | const char *address, | |||
| 496 | const char *key, | |||
| 497 | const char *cert, | |||
| 498 | const char *trust) { | |||
| 499 | int fd; | |||
| 500 | ||||
| 501 | fd = make_socket_fd(LOG_DEBUG7, address, SOCK_STREAMSOCK_STREAM, SOCK_CLOEXECSOCK_CLOEXEC); | |||
| 502 | if (fd < 0) | |||
| 503 | return fd; | |||
| 504 | ||||
| 505 | return setup_microhttpd_server(s, fd, key, cert, trust); | |||
| 506 | } | |||
| 507 | ||||
| 508 | static int null_timer_event_handler(sd_event_source *timer_event, | |||
| 509 | uint64_t usec, | |||
| 510 | void *userdata) { | |||
| 511 | return dispatch_http_event(timer_event, 0, 0, userdata); | |||
| 512 | } | |||
| 513 | ||||
| 514 | static int dispatch_http_event(sd_event_source *event, | |||
| 515 | int fd, | |||
| 516 | uint32_t revents, | |||
| 517 | void *userdata) { | |||
| 518 | MHDDaemonWrapper *d = userdata; | |||
| 519 | int r; | |||
| 520 | MHD_UNSIGNED_LONG_LONGunsigned long long timeout = ULONG_LONG_MAX(9223372036854775807LL*2ULL+1ULL); | |||
| 521 | ||||
| 522 | assert(d)do { if ((__builtin_expect(!!(!(d)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("d"), "../src/journal-remote/journal-remote-main.c" , 522, __PRETTY_FUNCTION__); } while (0); | |||
| 523 | ||||
| 524 | r = MHD_run(d->daemon); | |||
| 525 | if (r == MHD_NO) { | |||
| 526 | log_error("MHD_run failed!")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 526, __func__ , "MHD_run failed!") : -abs(_e); }); | |||
| 527 | // XXX: unregister daemon | |||
| 528 | return -EINVAL22; | |||
| 529 | } | |||
| 530 | if (MHD_get_timeout(d->daemon, &timeout) == MHD_NO) | |||
| 531 | timeout = ULONG_LONG_MAX(9223372036854775807LL*2ULL+1ULL); | |||
| 532 | ||||
| 533 | r = sd_event_source_set_time(d->timer_event, timeout); | |||
| 534 | if (r < 0) { | |||
| 535 | log_warning_errno(r, "Unable to set event loop timeout: %m, this may result in indefinite blocking!")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 535, __func__ , "Unable to set event loop timeout: %m, this may result in indefinite blocking!" ) : -abs(_e); }); | |||
| 536 | return 1; | |||
| 537 | } | |||
| 538 | ||||
| 539 | r = sd_event_source_set_enabled(d->timer_event, SD_EVENT_ON); | |||
| 540 | if (r < 0) | |||
| 541 | log_warning_errno(r, "Unable to enable timer_event: %m, this may result in indefinite blocking!")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 541, __func__ , "Unable to enable timer_event: %m, this may result in indefinite blocking!" ) : -abs(_e); }); | |||
| 542 | ||||
| 543 | return 1; /* work to do */ | |||
| 544 | } | |||
| 545 | ||||
| 546 | /********************************************************************** | |||
| 547 | ********************************************************************** | |||
| 548 | **********************************************************************/ | |||
| 549 | ||||
| 550 | static int setup_signals(RemoteServer *s) { | |||
| 551 | int r; | |||
| 552 | ||||
| 553 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/journal-remote/journal-remote-main.c" , 553, __PRETTY_FUNCTION__); } while (0); | |||
| 554 | ||||
| 555 | assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, -1) >= 0)do { if ((__builtin_expect(!!(!(sigprocmask_many(2, ((void*)0 ), 2, 15, -1) >= 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, -1) >= 0" ), "../src/journal-remote/journal-remote-main.c", 555, __PRETTY_FUNCTION__ ); } while (0); | |||
| 556 | ||||
| 557 | r = sd_event_add_signal(s->events, &s->sigterm_event, SIGTERM15, NULL((void*)0), s); | |||
| 558 | if (r < 0) | |||
| 559 | return r; | |||
| 560 | ||||
| 561 | r = sd_event_add_signal(s->events, &s->sigint_event, SIGINT2, NULL((void*)0), s); | |||
| 562 | if (r < 0) | |||
| 563 | return r; | |||
| 564 | ||||
| 565 | return 0; | |||
| 566 | } | |||
| 567 | ||||
| 568 | static int setup_raw_socket(RemoteServer *s, const char *address) { | |||
| 569 | int fd; | |||
| 570 | ||||
| 571 | fd = make_socket_fd(LOG_INFO6, address, SOCK_STREAMSOCK_STREAM, SOCK_CLOEXECSOCK_CLOEXEC); | |||
| 572 | if (fd < 0) | |||
| 573 | return fd; | |||
| 574 | ||||
| 575 | return journal_remote_add_raw_socket(s, fd); | |||
| 576 | } | |||
| 577 | ||||
| 578 | static int create_remoteserver( | |||
| 579 | RemoteServer *s, | |||
| 580 | const char* key, | |||
| 581 | const char* cert, | |||
| 582 | const char* trust) { | |||
| 583 | ||||
| 584 | int r, n, fd; | |||
| 585 | char **file; | |||
| 586 | ||||
| 587 | r = journal_remote_server_init(s, arg_output, arg_split_mode, arg_compress, arg_seal); | |||
| 588 | if (r < 0) | |||
| 589 | return r; | |||
| 590 | ||||
| 591 | setup_signals(s); | |||
| 592 | ||||
| 593 | n = sd_listen_fds(true1); | |||
| 594 | if (n < 0) | |||
| 595 | return log_error_errno(n, "Failed to read listening file descriptors from environment: %m")({ int _level = ((3)), _e = ((n)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 595, __func__ , "Failed to read listening file descriptors from environment: %m" ) : -abs(_e); }); | |||
| 596 | else | |||
| 597 | log_debug("Received %d descriptors", n)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 597, __func__ , "Received %d descriptors", n) : -abs(_e); }); | |||
| 598 | ||||
| 599 | if (MAX(http_socket, https_socket)__extension__ ({ const typeof((http_socket)) __unique_prefix_A15 = ((http_socket)); const typeof((https_socket)) __unique_prefix_B16 = ((https_socket)); __unique_prefix_A15 > __unique_prefix_B16 ? __unique_prefix_A15 : __unique_prefix_B16; }) >= SD_LISTEN_FDS_START3 + n) { | |||
| 600 | log_error("Received fewer sockets than expected")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 600, __func__ , "Received fewer sockets than expected") : -abs(_e); }); | |||
| 601 | return -EBADFD77; | |||
| 602 | } | |||
| 603 | ||||
| 604 | for (fd = SD_LISTEN_FDS_START3; fd < SD_LISTEN_FDS_START3 + n; fd++) { | |||
| 605 | if (sd_is_socket(fd, AF_UNSPEC0, 0, true1)) { | |||
| 606 | log_debug("Received a listening socket (fd:%d)", fd)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 606, __func__ , "Received a listening socket (fd:%d)", fd) : -abs(_e); }); | |||
| 607 | ||||
| 608 | if (fd == http_socket) | |||
| 609 | r = setup_microhttpd_server(s, fd, NULL((void*)0), NULL((void*)0), NULL((void*)0)); | |||
| 610 | else if (fd == https_socket) | |||
| 611 | r = setup_microhttpd_server(s, fd, key, cert, trust); | |||
| 612 | else | |||
| 613 | r = journal_remote_add_raw_socket(s, fd); | |||
| 614 | } else if (sd_is_socket(fd, AF_UNSPEC0, 0, false0)) { | |||
| 615 | char *hostname; | |||
| 616 | ||||
| 617 | r = getpeername_pretty(fd, false0, &hostname); | |||
| 618 | if (r < 0) | |||
| 619 | return log_error_errno(r, "Failed to retrieve remote name: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 619, __func__ , "Failed to retrieve remote name: %m") : -abs(_e); }); | |||
| 620 | ||||
| 621 | log_debug("Received a connection socket (fd:%d) from %s", fd, hostname)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 621, __func__ , "Received a connection socket (fd:%d) from %s", fd, hostname ) : -abs(_e); }); | |||
| 622 | ||||
| 623 | r = journal_remote_add_source(s, fd, hostname, true1); | |||
| 624 | } else { | |||
| 625 | log_error("Unknown socket passed on fd:%d", fd)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 625, __func__ , "Unknown socket passed on fd:%d", fd) : -abs(_e); }); | |||
| 626 | ||||
| 627 | return -EINVAL22; | |||
| 628 | } | |||
| 629 | ||||
| 630 | if (r < 0) | |||
| 631 | return log_error_errno(r, "Failed to register socket (fd:%d): %m",({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 632, __func__ , "Failed to register socket (fd:%d): %m", fd) : -abs(_e); }) | |||
| 632 | fd)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 632, __func__ , "Failed to register socket (fd:%d): %m", fd) : -abs(_e); }); | |||
| 633 | } | |||
| 634 | ||||
| 635 | if (arg_getter) { | |||
| 636 | log_info("Spawning getter %s...", arg_getter)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 636, __func__ , "Spawning getter %s...", arg_getter) : -abs(_e); }); | |||
| 637 | fd = spawn_getter(arg_getter); | |||
| 638 | if (fd < 0) | |||
| 639 | return fd; | |||
| 640 | ||||
| 641 | r = journal_remote_add_source(s, fd, (char*) arg_output, false0); | |||
| 642 | if (r < 0) | |||
| 643 | return r; | |||
| 644 | } | |||
| 645 | ||||
| 646 | if (arg_url) { | |||
| 647 | const char *url; | |||
| 648 | char *hostname, *p; | |||
| 649 | ||||
| 650 | if (!strstr(arg_url, "/entries")) { | |||
| 651 | if (endswith(arg_url, "/")) | |||
| 652 | url = strjoina(arg_url, "entries")({ const char *_appendees_[] = { arg_url, "entries" }; char * _d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }); | |||
| 653 | else | |||
| 654 | url = strjoina(arg_url, "/entries")({ const char *_appendees_[] = { arg_url, "/entries" }; char * _d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }); | |||
| 655 | } | |||
| 656 | else | |||
| 657 | url = strdupa(arg_url)(__extension__ ({ const char *__old = (arg_url); size_t __len = strlen (__old) + 1; char *__new = (char *) __builtin_alloca (__len); (char *) memcpy (__new, __old, __len); })); | |||
| 658 | ||||
| 659 | log_info("Spawning curl %s...", url)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 659, __func__ , "Spawning curl %s...", url) : -abs(_e); }); | |||
| 660 | fd = spawn_curl(url); | |||
| 661 | if (fd < 0) | |||
| 662 | return fd; | |||
| 663 | ||||
| 664 | hostname = | |||
| 665 | startswith(arg_url, "https://") ?: | |||
| 666 | startswith(arg_url, "http://") ?: | |||
| 667 | arg_url; | |||
| 668 | ||||
| 669 | hostname = strdupa(hostname)(__extension__ ({ const char *__old = (hostname); size_t __len = strlen (__old) + 1; char *__new = (char *) __builtin_alloca (__len); (char *) memcpy (__new, __old, __len); })); | |||
| 670 | if ((p = strchr(hostname, '/'))) | |||
| 671 | *p = '\0'; | |||
| 672 | if ((p = strchr(hostname, ':'))) | |||
| 673 | *p = '\0'; | |||
| 674 | ||||
| 675 | r = journal_remote_add_source(s, fd, hostname, false0); | |||
| 676 | if (r < 0) | |||
| 677 | return r; | |||
| 678 | } | |||
| 679 | ||||
| 680 | if (arg_listen_raw) { | |||
| 681 | log_debug("Listening on a socket...")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 681, __func__ , "Listening on a socket...") : -abs(_e); }); | |||
| 682 | r = setup_raw_socket(s, arg_listen_raw); | |||
| 683 | if (r < 0) | |||
| 684 | return r; | |||
| 685 | } | |||
| 686 | ||||
| 687 | if (arg_listen_http) { | |||
| 688 | r = setup_microhttpd_socket(s, arg_listen_http, NULL((void*)0), NULL((void*)0), NULL((void*)0)); | |||
| 689 | if (r < 0) | |||
| 690 | return r; | |||
| 691 | } | |||
| 692 | ||||
| 693 | if (arg_listen_https) { | |||
| 694 | r = setup_microhttpd_socket(s, arg_listen_https, key, cert, trust); | |||
| 695 | if (r < 0) | |||
| 696 | return r; | |||
| 697 | } | |||
| 698 | ||||
| 699 | STRV_FOREACH(file, arg_files)for ((file) = (arg_files); (file) && *(file); (file)++ ) { | |||
| 700 | const char *output_name; | |||
| 701 | ||||
| 702 | if (streq(*file, "-")(strcmp((*file),("-")) == 0)) { | |||
| 703 | log_debug("Using standard input as source.")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 703, __func__ , "Using standard input as source.") : -abs(_e); }); | |||
| 704 | ||||
| 705 | fd = STDIN_FILENO0; | |||
| 706 | output_name = "stdin"; | |||
| 707 | } else { | |||
| 708 | log_debug("Reading file %s...", *file)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 708, __func__ , "Reading file %s...", *file) : -abs(_e); }); | |||
| 709 | ||||
| 710 | fd = open(*file, O_RDONLY00|O_CLOEXEC02000000|O_NOCTTY0400|O_NONBLOCK04000); | |||
| 711 | if (fd < 0) | |||
| 712 | return log_error_errno(errno, "Failed to open %s: %m", *file)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal-remote/journal-remote-main.c" , 712, __func__, "Failed to open %s: %m", *file) : -abs(_e); } ); | |||
| 713 | output_name = *file; | |||
| 714 | } | |||
| 715 | ||||
| 716 | r = journal_remote_add_source(s, fd, (char*) output_name, false0); | |||
| 717 | if (r < 0) | |||
| 718 | return r; | |||
| 719 | } | |||
| 720 | ||||
| 721 | if (s->active == 0) { | |||
| 722 | log_error("Zero sources specified")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 722, __func__ , "Zero sources specified") : -abs(_e); }); | |||
| 723 | return -EINVAL22; | |||
| 724 | } | |||
| 725 | ||||
| 726 | if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE) { | |||
| 727 | /* In this case we know what the writer will be | |||
| 728 | called, so we can create it and verify that we can | |||
| 729 | create output as expected. */ | |||
| 730 | r = journal_remote_get_writer(s, NULL((void*)0), &s->_single_writer); | |||
| 731 | if (r < 0) | |||
| 732 | return r; | |||
| 733 | } | |||
| 734 | ||||
| 735 | return 0; | |||
| 736 | } | |||
| 737 | ||||
| 738 | static int negative_fd(const char *spec) { | |||
| 739 | /* Return a non-positive number as its inverse, -EINVAL otherwise. */ | |||
| 740 | ||||
| 741 | int fd, r; | |||
| 742 | ||||
| 743 | r = safe_atoi(spec, &fd); | |||
| 744 | if (r < 0) | |||
| 745 | return r; | |||
| 746 | ||||
| 747 | if (fd > 0) | |||
| 748 | return -EINVAL22; | |||
| 749 | else | |||
| 750 | return -fd; | |||
| 751 | } | |||
| 752 | ||||
| 753 | static int parse_config(void) { | |||
| 754 | const ConfigTableItem items[] = { | |||
| 755 | { "Remote", "Seal", config_parse_bool, 0, &arg_seal }, | |||
| 756 | { "Remote", "SplitMode", config_parse_write_split_mode, 0, &arg_split_mode }, | |||
| 757 | { "Remote", "ServerKeyFile", config_parse_path, 0, &arg_key }, | |||
| 758 | { "Remote", "ServerCertificateFile", config_parse_path, 0, &arg_cert }, | |||
| 759 | { "Remote", "TrustedCertificateFile", config_parse_path, 0, &arg_trust }, | |||
| 760 | {}}; | |||
| 761 | ||||
| 762 | return config_parse_many_nulstr(PKGSYSCONFDIR"/etc/systemd" "/journal-remote.conf", | |||
| 763 | CONF_PATHS_NULSTR("systemd/journal-remote.conf.d")"/etc/" "systemd/journal-remote.conf.d" "\0" "/run/" "systemd/journal-remote.conf.d" "\0" "/usr/local/lib/" "systemd/journal-remote.conf.d" "\0" "/usr/lib/" "systemd/journal-remote.conf.d" "\0", | |||
| 764 | "Remote\0", config_item_table_lookup, items, | |||
| 765 | CONFIG_PARSE_WARN, NULL((void*)0)); | |||
| 766 | } | |||
| 767 | ||||
| 768 | static void help(void) { | |||
| 769 | printf("%s [OPTIONS...] {FILE|-}...\n\n" | |||
| 770 | "Write external journal events to journal file(s).\n\n" | |||
| 771 | " -h --help Show this help\n" | |||
| 772 | " --version Show package version\n" | |||
| 773 | " --url=URL Read events from systemd-journal-gatewayd at URL\n" | |||
| 774 | " --getter=COMMAND Read events from the output of COMMAND\n" | |||
| 775 | " --listen-raw=ADDR Listen for connections at ADDR\n" | |||
| 776 | " --listen-http=ADDR Listen for HTTP connections at ADDR\n" | |||
| 777 | " --listen-https=ADDR Listen for HTTPS connections at ADDR\n" | |||
| 778 | " -o --output=FILE|DIR Write output to FILE or DIR/external-*.journal\n" | |||
| 779 | " --compress[=BOOL] XZ-compress the output journal (default: yes)\n" | |||
| 780 | " --seal[=BOOL] Use event sealing (default: no)\n" | |||
| 781 | " --key=FILENAME SSL key in PEM format (default:\n" | |||
| 782 | " \"" PRIV_KEY_FILE"/etc/ssl" "/private/journal-remote.pem" "\")\n" | |||
| 783 | " --cert=FILENAME SSL certificate in PEM format (default:\n" | |||
| 784 | " \"" CERT_FILE"/etc/ssl" "/certs/journal-remote.pem" "\")\n" | |||
| 785 | " --trust=FILENAME|all SSL CA certificate or disable checking (default:\n" | |||
| 786 | " \"" TRUST_FILE"/etc/ssl" "/ca/trusted.pem" "\")\n" | |||
| 787 | " --gnutls-log=CATEGORY...\n" | |||
| 788 | " Specify a list of gnutls logging categories\n" | |||
| 789 | " --split-mode=none|host How many output files to create\n" | |||
| 790 | "\n" | |||
| 791 | "Note: file descriptors from sd_listen_fds() will be consumed, too.\n" | |||
| 792 | , program_invocation_short_name); | |||
| 793 | } | |||
| 794 | ||||
| 795 | static int parse_argv(int argc, char *argv[]) { | |||
| 796 | enum { | |||
| 797 | ARG_VERSION = 0x100, | |||
| 798 | ARG_URL, | |||
| 799 | ARG_LISTEN_RAW, | |||
| 800 | ARG_LISTEN_HTTP, | |||
| 801 | ARG_LISTEN_HTTPS, | |||
| 802 | ARG_GETTER, | |||
| 803 | ARG_SPLIT_MODE, | |||
| 804 | ARG_COMPRESS, | |||
| 805 | ARG_SEAL, | |||
| 806 | ARG_KEY, | |||
| 807 | ARG_CERT, | |||
| 808 | ARG_TRUST, | |||
| 809 | ARG_GNUTLS_LOG, | |||
| 810 | }; | |||
| 811 | ||||
| 812 | static const struct option options[] = { | |||
| 813 | { "help", no_argument0, NULL((void*)0), 'h' }, | |||
| 814 | { "version", no_argument0, NULL((void*)0), ARG_VERSION }, | |||
| 815 | { "url", required_argument1, NULL((void*)0), ARG_URL }, | |||
| 816 | { "getter", required_argument1, NULL((void*)0), ARG_GETTER }, | |||
| 817 | { "listen-raw", required_argument1, NULL((void*)0), ARG_LISTEN_RAW }, | |||
| 818 | { "listen-http", required_argument1, NULL((void*)0), ARG_LISTEN_HTTP }, | |||
| 819 | { "listen-https", required_argument1, NULL((void*)0), ARG_LISTEN_HTTPS }, | |||
| 820 | { "output", required_argument1, NULL((void*)0), 'o' }, | |||
| 821 | { "split-mode", required_argument1, NULL((void*)0), ARG_SPLIT_MODE }, | |||
| 822 | { "compress", optional_argument2, NULL((void*)0), ARG_COMPRESS }, | |||
| 823 | { "seal", optional_argument2, NULL((void*)0), ARG_SEAL }, | |||
| 824 | { "key", required_argument1, NULL((void*)0), ARG_KEY }, | |||
| 825 | { "cert", required_argument1, NULL((void*)0), ARG_CERT }, | |||
| 826 | { "trust", required_argument1, NULL((void*)0), ARG_TRUST }, | |||
| 827 | { "gnutls-log", required_argument1, NULL((void*)0), ARG_GNUTLS_LOG }, | |||
| 828 | {} | |||
| 829 | }; | |||
| 830 | ||||
| 831 | int c, r; | |||
| 832 | bool_Bool type_a, type_b; | |||
| 833 | ||||
| 834 | assert(argc >= 0)do { if ((__builtin_expect(!!(!(argc >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("argc >= 0"), "../src/journal-remote/journal-remote-main.c" , 834, __PRETTY_FUNCTION__); } while (0); | |||
| ||||
| 835 | assert(argv)do { if ((__builtin_expect(!!(!(argv)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("argv"), "../src/journal-remote/journal-remote-main.c" , 835, __PRETTY_FUNCTION__); } while (0); | |||
| 836 | ||||
| 837 | while ((c = getopt_long(argc, argv, "ho:", options, NULL((void*)0))) >= 0) | |||
| 838 | switch(c) { | |||
| 839 | case 'h': | |||
| 840 | help(); | |||
| 841 | return 0 /* done */; | |||
| 842 | ||||
| 843 | case ARG_VERSION: | |||
| 844 | return version(); | |||
| 845 | ||||
| 846 | case ARG_URL: | |||
| 847 | if (arg_url) { | |||
| 848 | log_error("cannot currently set more than one --url")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 848, __func__ , "cannot currently set more than one --url") : -abs(_e); }); | |||
| 849 | return -EINVAL22; | |||
| 850 | } | |||
| 851 | ||||
| 852 | arg_url = optarg; | |||
| 853 | break; | |||
| 854 | ||||
| 855 | case ARG_GETTER: | |||
| 856 | if (arg_getter) { | |||
| 857 | log_error("cannot currently use --getter more than once")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 857, __func__ , "cannot currently use --getter more than once") : -abs(_e); }); | |||
| 858 | return -EINVAL22; | |||
| 859 | } | |||
| 860 | ||||
| 861 | arg_getter = optarg; | |||
| 862 | break; | |||
| 863 | ||||
| 864 | case ARG_LISTEN_RAW: | |||
| 865 | if (arg_listen_raw) { | |||
| 866 | log_error("cannot currently use --listen-raw more than once")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 866, __func__ , "cannot currently use --listen-raw more than once") : -abs( _e); }); | |||
| 867 | return -EINVAL22; | |||
| 868 | } | |||
| 869 | ||||
| 870 | arg_listen_raw = optarg; | |||
| 871 | break; | |||
| 872 | ||||
| 873 | case ARG_LISTEN_HTTP: | |||
| 874 | if (arg_listen_http || http_socket >= 0) { | |||
| 875 | log_error("cannot currently use --listen-http more than once")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 875, __func__ , "cannot currently use --listen-http more than once") : -abs (_e); }); | |||
| 876 | return -EINVAL22; | |||
| 877 | } | |||
| 878 | ||||
| 879 | r = negative_fd(optarg); | |||
| 880 | if (r >= 0) | |||
| 881 | http_socket = r; | |||
| 882 | else | |||
| 883 | arg_listen_http = optarg; | |||
| 884 | break; | |||
| 885 | ||||
| 886 | case ARG_LISTEN_HTTPS: | |||
| 887 | if (arg_listen_https || https_socket >= 0) { | |||
| 888 | log_error("cannot currently use --listen-https more than once")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 888, __func__ , "cannot currently use --listen-https more than once") : -abs (_e); }); | |||
| 889 | return -EINVAL22; | |||
| 890 | } | |||
| 891 | ||||
| 892 | r = negative_fd(optarg); | |||
| 893 | if (r >= 0) | |||
| 894 | https_socket = r; | |||
| 895 | else | |||
| 896 | arg_listen_https = optarg; | |||
| 897 | ||||
| 898 | break; | |||
| 899 | ||||
| 900 | case ARG_KEY: | |||
| 901 | if (arg_key) { | |||
| 902 | log_error("Key file specified twice")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 902, __func__ , "Key file specified twice") : -abs(_e); }); | |||
| 903 | return -EINVAL22; | |||
| 904 | } | |||
| 905 | ||||
| 906 | arg_key = strdup(optarg); | |||
| 907 | if (!arg_key) | |||
| 908 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-remote-main.c" , 908, __func__); | |||
| 909 | ||||
| 910 | break; | |||
| 911 | ||||
| 912 | case ARG_CERT: | |||
| 913 | if (arg_cert) { | |||
| 914 | log_error("Certificate file specified twice")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 914, __func__ , "Certificate file specified twice") : -abs(_e); }); | |||
| 915 | return -EINVAL22; | |||
| 916 | } | |||
| 917 | ||||
| 918 | arg_cert = strdup(optarg); | |||
| 919 | if (!arg_cert) | |||
| 920 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-remote-main.c" , 920, __func__); | |||
| 921 | ||||
| 922 | break; | |||
| 923 | ||||
| 924 | case ARG_TRUST: | |||
| 925 | if (arg_trust || arg_trust_all) { | |||
| 926 | log_error("Confusing trusted CA configuration")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 926, __func__ , "Confusing trusted CA configuration") : -abs(_e); }); | |||
| 927 | return -EINVAL22; | |||
| 928 | } | |||
| 929 | ||||
| 930 | if (streq(optarg, "all")(strcmp((optarg),("all")) == 0)) | |||
| ||||
| 931 | arg_trust_all = true1; | |||
| 932 | else { | |||
| 933 | #if HAVE_GNUTLS1 | |||
| 934 | arg_trust = strdup(optarg); | |||
| 935 | if (!arg_trust) | |||
| 936 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-remote-main.c" , 936, __func__); | |||
| 937 | #else | |||
| 938 | log_error("Option --trust is not available.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 938, __func__ , "Option --trust is not available.") : -abs(_e); }); | |||
| 939 | return -EINVAL22; | |||
| 940 | #endif | |||
| 941 | } | |||
| 942 | ||||
| 943 | break; | |||
| 944 | ||||
| 945 | case 'o': | |||
| 946 | if (arg_output) { | |||
| 947 | log_error("cannot use --output/-o more than once")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 947, __func__ , "cannot use --output/-o more than once") : -abs(_e); }); | |||
| 948 | return -EINVAL22; | |||
| 949 | } | |||
| 950 | ||||
| 951 | arg_output = optarg; | |||
| 952 | break; | |||
| 953 | ||||
| 954 | case ARG_SPLIT_MODE: | |||
| 955 | arg_split_mode = journal_write_split_mode_from_string(optarg); | |||
| 956 | if (arg_split_mode == _JOURNAL_WRITE_SPLIT_INVALID) { | |||
| 957 | log_error("Invalid split mode: %s", optarg)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 957, __func__ , "Invalid split mode: %s", optarg) : -abs(_e); }); | |||
| 958 | return -EINVAL22; | |||
| 959 | } | |||
| 960 | break; | |||
| 961 | ||||
| 962 | case ARG_COMPRESS: | |||
| 963 | if (optarg) { | |||
| 964 | r = parse_boolean(optarg); | |||
| 965 | if (r < 0) { | |||
| 966 | log_error("Failed to parse --compress= parameter.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 966, __func__ , "Failed to parse --compress= parameter.") : -abs(_e); }); | |||
| 967 | return -EINVAL22; | |||
| 968 | } | |||
| 969 | ||||
| 970 | arg_compress = !!r; | |||
| 971 | } else | |||
| 972 | arg_compress = true1; | |||
| 973 | ||||
| 974 | break; | |||
| 975 | ||||
| 976 | case ARG_SEAL: | |||
| 977 | if (optarg) { | |||
| 978 | r = parse_boolean(optarg); | |||
| 979 | if (r < 0) { | |||
| 980 | log_error("Failed to parse --seal= parameter.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 980, __func__ , "Failed to parse --seal= parameter.") : -abs(_e); }); | |||
| 981 | return -EINVAL22; | |||
| 982 | } | |||
| 983 | ||||
| 984 | arg_seal = !!r; | |||
| 985 | } else | |||
| 986 | arg_seal = true1; | |||
| 987 | ||||
| 988 | break; | |||
| 989 | ||||
| 990 | case ARG_GNUTLS_LOG: { | |||
| 991 | #if HAVE_GNUTLS1 | |||
| 992 | const char* p = optarg; | |||
| 993 | for (;;) { | |||
| 994 | _cleanup_free___attribute__((cleanup(freep))) char *word = NULL((void*)0); | |||
| 995 | ||||
| 996 | r = extract_first_word(&p, &word, ",", 0); | |||
| 997 | if (r < 0) | |||
| 998 | return log_error_errno(r, "Failed to parse --gnutls-log= argument: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 998, __func__ , "Failed to parse --gnutls-log= argument: %m") : -abs(_e); } ); | |||
| 999 | ||||
| 1000 | if (r == 0) | |||
| 1001 | break; | |||
| 1002 | ||||
| 1003 | if (strv_push(&arg_gnutls_log, word) < 0) | |||
| 1004 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-remote-main.c" , 1004, __func__); | |||
| 1005 | ||||
| 1006 | word = NULL((void*)0); | |||
| 1007 | } | |||
| 1008 | break; | |||
| 1009 | #else | |||
| 1010 | log_error("Option --gnutls-log is not available.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1010, __func__ , "Option --gnutls-log is not available.") : -abs(_e); }); | |||
| 1011 | return -EINVAL22; | |||
| 1012 | #endif | |||
| 1013 | } | |||
| 1014 | ||||
| 1015 | case '?': | |||
| 1016 | return -EINVAL22; | |||
| 1017 | ||||
| 1018 | default: | |||
| 1019 | assert_not_reached("Unknown option code.")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Unknown option code."), "../src/journal-remote/journal-remote-main.c" , 1019, __PRETTY_FUNCTION__); } while (0); | |||
| 1020 | } | |||
| 1021 | ||||
| 1022 | if (optind < argc) | |||
| 1023 | arg_files = argv + optind; | |||
| 1024 | ||||
| 1025 | type_a = arg_getter || !strv_isempty(arg_files); | |||
| 1026 | type_b = arg_url | |||
| 1027 | || arg_listen_raw | |||
| 1028 | || arg_listen_http || arg_listen_https | |||
| 1029 | || sd_listen_fds(false0) > 0; | |||
| 1030 | if (type_a && type_b) { | |||
| 1031 | log_error("Cannot use file input or --getter with "({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1032, __func__ , "Cannot use file input or --getter with " "--arg-listen-... or socket activation." ) : -abs(_e); }) | |||
| 1032 | "--arg-listen-... or socket activation.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1032, __func__ , "Cannot use file input or --getter with " "--arg-listen-... or socket activation." ) : -abs(_e); }); | |||
| 1033 | return -EINVAL22; | |||
| 1034 | } | |||
| 1035 | if (type_a) { | |||
| 1036 | if (!arg_output) { | |||
| 1037 | log_error("Option --output must be specified with file input or --getter.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1037, __func__ , "Option --output must be specified with file input or --getter." ) : -abs(_e); }); | |||
| 1038 | return -EINVAL22; | |||
| 1039 | } | |||
| 1040 | ||||
| 1041 | if (!IN_SET(arg_split_mode, JOURNAL_WRITE_SPLIT_NONE, _JOURNAL_WRITE_SPLIT_INVALID)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){JOURNAL_WRITE_SPLIT_NONE, _JOURNAL_WRITE_SPLIT_INVALID })/sizeof(int)]; switch(arg_split_mode) { case JOURNAL_WRITE_SPLIT_NONE : case _JOURNAL_WRITE_SPLIT_INVALID: _found = 1; break; default : break; } _found; })) { | |||
| 1042 | log_error("For active sources, only --split-mode=none is allowed.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1042, __func__ , "For active sources, only --split-mode=none is allowed.") : -abs(_e); }); | |||
| 1043 | return -EINVAL22; | |||
| 1044 | } | |||
| 1045 | ||||
| 1046 | arg_split_mode = JOURNAL_WRITE_SPLIT_NONE; | |||
| 1047 | } | |||
| 1048 | ||||
| 1049 | if (arg_split_mode == _JOURNAL_WRITE_SPLIT_INVALID) | |||
| 1050 | arg_split_mode = JOURNAL_WRITE_SPLIT_HOST; | |||
| 1051 | ||||
| 1052 | if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE && arg_output) { | |||
| 1053 | if (is_dir(arg_output, true1) > 0) { | |||
| 1054 | log_error("For SplitMode=none, output must be a file.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1054, __func__ , "For SplitMode=none, output must be a file.") : -abs(_e); } ); | |||
| 1055 | return -EINVAL22; | |||
| 1056 | } | |||
| 1057 | if (!endswith(arg_output, ".journal")) { | |||
| 1058 | log_error("For SplitMode=none, output file name must end with .journal.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1058, __func__ , "For SplitMode=none, output file name must end with .journal." ) : -abs(_e); }); | |||
| 1059 | return -EINVAL22; | |||
| 1060 | } | |||
| 1061 | } | |||
| 1062 | ||||
| 1063 | if (arg_split_mode == JOURNAL_WRITE_SPLIT_HOST | |||
| 1064 | && arg_output && is_dir(arg_output, true1) <= 0) { | |||
| 1065 | log_error("For SplitMode=host, output must be a directory.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1065, __func__ , "For SplitMode=host, output must be a directory.") : -abs(_e ); }); | |||
| 1066 | return -EINVAL22; | |||
| 1067 | } | |||
| 1068 | ||||
| 1069 | log_debug("Full config: SplitMode=%s Key=%s Cert=%s Trust=%s",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1073, __func__ , "Full config: SplitMode=%s Key=%s Cert=%s Trust=%s", journal_write_split_mode_to_string (arg_split_mode), strna(arg_key), strna(arg_cert), strna(arg_trust )) : -abs(_e); }) | |||
| 1070 | journal_write_split_mode_to_string(arg_split_mode),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1073, __func__ , "Full config: SplitMode=%s Key=%s Cert=%s Trust=%s", journal_write_split_mode_to_string (arg_split_mode), strna(arg_key), strna(arg_cert), strna(arg_trust )) : -abs(_e); }) | |||
| 1071 | strna(arg_key),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1073, __func__ , "Full config: SplitMode=%s Key=%s Cert=%s Trust=%s", journal_write_split_mode_to_string (arg_split_mode), strna(arg_key), strna(arg_cert), strna(arg_trust )) : -abs(_e); }) | |||
| 1072 | strna(arg_cert),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1073, __func__ , "Full config: SplitMode=%s Key=%s Cert=%s Trust=%s", journal_write_split_mode_to_string (arg_split_mode), strna(arg_key), strna(arg_cert), strna(arg_trust )) : -abs(_e); }) | |||
| 1073 | strna(arg_trust))({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1073, __func__ , "Full config: SplitMode=%s Key=%s Cert=%s Trust=%s", journal_write_split_mode_to_string (arg_split_mode), strna(arg_key), strna(arg_cert), strna(arg_trust )) : -abs(_e); }); | |||
| 1074 | ||||
| 1075 | return 1 /* work to do */; | |||
| 1076 | } | |||
| 1077 | ||||
| 1078 | static int load_certificates(char **key, char **cert, char **trust) { | |||
| 1079 | int r; | |||
| 1080 | ||||
| 1081 | r = read_full_file(arg_key ?: PRIV_KEY_FILE"/etc/ssl" "/private/journal-remote.pem", key, NULL((void*)0)); | |||
| 1082 | if (r < 0) | |||
| 1083 | return log_error_errno(r, "Failed to read key from file '%s': %m",({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1084, __func__ , "Failed to read key from file '%s': %m", arg_key ?: "/etc/ssl" "/private/journal-remote.pem") : -abs(_e); }) | |||
| 1084 | arg_key ?: PRIV_KEY_FILE)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1084, __func__ , "Failed to read key from file '%s': %m", arg_key ?: "/etc/ssl" "/private/journal-remote.pem") : -abs(_e); }); | |||
| 1085 | ||||
| 1086 | r = read_full_file(arg_cert ?: CERT_FILE"/etc/ssl" "/certs/journal-remote.pem", cert, NULL((void*)0)); | |||
| 1087 | if (r < 0) | |||
| 1088 | return log_error_errno(r, "Failed to read certificate from file '%s': %m",({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1089, __func__ , "Failed to read certificate from file '%s': %m", arg_cert ? : "/etc/ssl" "/certs/journal-remote.pem") : -abs(_e); }) | |||
| 1089 | arg_cert ?: CERT_FILE)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1089, __func__ , "Failed to read certificate from file '%s': %m", arg_cert ? : "/etc/ssl" "/certs/journal-remote.pem") : -abs(_e); }); | |||
| 1090 | ||||
| 1091 | if (arg_trust_all) | |||
| 1092 | log_info("Certificate checking disabled.")({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1092, __func__ , "Certificate checking disabled.") : -abs(_e); }); | |||
| 1093 | else { | |||
| 1094 | r = read_full_file(arg_trust ?: TRUST_FILE"/etc/ssl" "/ca/trusted.pem", trust, NULL((void*)0)); | |||
| 1095 | if (r < 0) | |||
| 1096 | return log_error_errno(r, "Failed to read CA certificate file '%s': %m",({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1097, __func__ , "Failed to read CA certificate file '%s': %m", arg_trust ?: "/etc/ssl" "/ca/trusted.pem") : -abs(_e); }) | |||
| 1097 | arg_trust ?: TRUST_FILE)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1097, __func__ , "Failed to read CA certificate file '%s': %m", arg_trust ?: "/etc/ssl" "/ca/trusted.pem") : -abs(_e); }); | |||
| 1098 | } | |||
| 1099 | ||||
| 1100 | if ((arg_listen_raw || arg_listen_http) && *trust) { | |||
| 1101 | log_error("Option --trust makes all non-HTTPS connections untrusted.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1101, __func__ , "Option --trust makes all non-HTTPS connections untrusted." ) : -abs(_e); }); | |||
| 1102 | return -EINVAL22; | |||
| 1103 | } | |||
| 1104 | ||||
| 1105 | return 0; | |||
| 1106 | } | |||
| 1107 | ||||
| 1108 | int main(int argc, char **argv) { | |||
| 1109 | RemoteServer s = {}; | |||
| 1110 | int r; | |||
| 1111 | _cleanup_free___attribute__((cleanup(freep))) char *key = NULL((void*)0), *cert = NULL((void*)0), *trust = NULL((void*)0); | |||
| 1112 | ||||
| 1113 | log_show_color(true1); | |||
| 1114 | log_parse_environment()log_parse_environment_realm(LOG_REALM_SYSTEMD); | |||
| 1115 | ||||
| 1116 | r = parse_config(); | |||
| 1117 | if (r < 0) | |||
| 1118 | return EXIT_FAILURE1; | |||
| 1119 | ||||
| 1120 | r = parse_argv(argc, argv); | |||
| 1121 | if (r <= 0) | |||
| 1122 | return r == 0 ? EXIT_SUCCESS0 : EXIT_FAILURE1; | |||
| 1123 | ||||
| 1124 | if (arg_listen_http || arg_listen_https) { | |||
| 1125 | r = setup_gnutls_logger(arg_gnutls_log); | |||
| 1126 | if (r < 0) | |||
| 1127 | return EXIT_FAILURE1; | |||
| 1128 | } | |||
| 1129 | ||||
| 1130 | if (arg_listen_https || https_socket >= 0) | |||
| 1131 | if (load_certificates(&key, &cert, &trust) < 0) | |||
| 1132 | return EXIT_FAILURE1; | |||
| 1133 | ||||
| 1134 | if (create_remoteserver(&s, key, cert, trust) < 0) | |||
| 1135 | return EXIT_FAILURE1; | |||
| 1136 | ||||
| 1137 | r = sd_event_set_watchdog(s.events, true1); | |||
| 1138 | if (r < 0) | |||
| 1139 | log_error_errno(r, "Failed to enable watchdog: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1139, __func__ , "Failed to enable watchdog: %m") : -abs(_e); }); | |||
| 1140 | else | |||
| 1141 | log_debug("Watchdog is %sd.", enable_disable(r > 0))({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1141, __func__ , "Watchdog is %sd.", enable_disable(r > 0)) : -abs(_e); } ); | |||
| 1142 | ||||
| 1143 | log_debug("%s running as pid "PID_FMT,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1144, __func__ , "%s running as pid ""%" "i", program_invocation_short_name, getpid_cached()) : -abs(_e); }) | |||
| 1144 | program_invocation_short_name, getpid_cached())({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1144, __func__ , "%s running as pid ""%" "i", program_invocation_short_name, getpid_cached()) : -abs(_e); }); | |||
| 1145 | sd_notify(false0, | |||
| 1146 | "READY=1\n" | |||
| 1147 | "STATUS=Processing requests..."); | |||
| 1148 | ||||
| 1149 | while (s.active) { | |||
| 1150 | r = sd_event_get_state(s.events); | |||
| 1151 | if (r < 0) | |||
| 1152 | break; | |||
| 1153 | if (r == SD_EVENT_FINISHED) | |||
| 1154 | break; | |||
| 1155 | ||||
| 1156 | r = sd_event_run(s.events, -1); | |||
| 1157 | if (r < 0) { | |||
| 1158 | log_error_errno(r, "Failed to run event loop: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1158, __func__ , "Failed to run event loop: %m") : -abs(_e); }); | |||
| 1159 | break; | |||
| 1160 | } | |||
| 1161 | } | |||
| 1162 | ||||
| 1163 | sd_notifyf(false0, | |||
| 1164 | "STOPPING=1\n" | |||
| 1165 | "STATUS=Shutting down after writing %" PRIu64"l" "u" " entries...", s.event_count); | |||
| 1166 | log_info("Finishing after writing %" PRIu64 " entries", s.event_count)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal-remote/journal-remote-main.c", 1166, __func__ , "Finishing after writing %" "l" "u" " entries", s.event_count ) : -abs(_e); }); | |||
| 1167 | ||||
| 1168 | journal_remote_server_destroy(&s); | |||
| 1169 | ||||
| 1170 | free(arg_key); | |||
| 1171 | free(arg_cert); | |||
| 1172 | free(arg_trust); | |||
| 1173 | ||||
| 1174 | return r >= 0 ? EXIT_SUCCESS0 : EXIT_FAILURE1; | |||
| 1175 | } |