]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/journal-remote/journal-remote.c
Merge pull request #1655 from ssahani/net
[thirdparty/systemd.git] / src / journal-remote / journal-remote.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2012 Zbigniew Jędrzejewski-Szmek
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <getopt.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/prctl.h>
29 #include <sys/socket.h>
30 #include <unistd.h>
31
32 #ifdef HAVE_GNUTLS
33 #include <gnutls/gnutls.h>
34 #endif
35
36 #include "sd-daemon.h"
37
38 #include "alloc-util.h"
39 #include "conf-parser.h"
40 #include "def.h"
41 #include "escape.h"
42 #include "fd-util.h"
43 #include "fileio.h"
44 #include "journal-file.h"
45 #include "journal-remote-write.h"
46 #include "journal-remote.h"
47 #include "journald-native.h"
48 #include "macro.h"
49 #include "parse-util.h"
50 #include "signal-util.h"
51 #include "socket-util.h"
52 #include "stat-util.h"
53 #include "stdio-util.h"
54 #include "string-table.h"
55 #include "string-util.h"
56 #include "strv.h"
57
58 #define REMOTE_JOURNAL_PATH "/var/log/journal/remote"
59
60 #define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-remote.pem"
61 #define CERT_FILE CERTIFICATE_ROOT "/certs/journal-remote.pem"
62 #define TRUST_FILE CERTIFICATE_ROOT "/ca/trusted.pem"
63
64 static char* arg_url = NULL;
65 static char* arg_getter = NULL;
66 static char* arg_listen_raw = NULL;
67 static char* arg_listen_http = NULL;
68 static char* arg_listen_https = NULL;
69 static char** arg_files = NULL;
70 static int arg_compress = true;
71 static int arg_seal = false;
72 static int http_socket = -1, https_socket = -1;
73 static char** arg_gnutls_log = NULL;
74
75 static JournalWriteSplitMode arg_split_mode = JOURNAL_WRITE_SPLIT_HOST;
76 static char* arg_output = NULL;
77
78 static char *arg_key = NULL;
79 static char *arg_cert = NULL;
80 static char *arg_trust = NULL;
81 static bool arg_trust_all = false;
82
83 /**********************************************************************
84 **********************************************************************
85 **********************************************************************/
86
87 static int spawn_child(const char* child, char** argv) {
88 int fd[2];
89 pid_t parent_pid, child_pid;
90 int r;
91
92 if (pipe(fd) < 0)
93 return log_error_errno(errno, "Failed to create pager pipe: %m");
94
95 parent_pid = getpid();
96
97 child_pid = fork();
98 if (child_pid < 0) {
99 r = log_error_errno(errno, "Failed to fork: %m");
100 safe_close_pair(fd);
101 return r;
102 }
103
104 /* In the child */
105 if (child_pid == 0) {
106
107 (void) reset_all_signal_handlers();
108 (void) reset_signal_mask();
109
110 r = dup2(fd[1], STDOUT_FILENO);
111 if (r < 0) {
112 log_error_errno(errno, "Failed to dup pipe to stdout: %m");
113 _exit(EXIT_FAILURE);
114 }
115
116 safe_close_pair(fd);
117
118 /* Make sure the child goes away when the parent dies */
119 if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
120 _exit(EXIT_FAILURE);
121
122 /* Check whether our parent died before we were able
123 * to set the death signal */
124 if (getppid() != parent_pid)
125 _exit(EXIT_SUCCESS);
126
127 execvp(child, argv);
128 log_error_errno(errno, "Failed to exec child %s: %m", child);
129 _exit(EXIT_FAILURE);
130 }
131
132 r = close(fd[1]);
133 if (r < 0)
134 log_warning_errno(errno, "Failed to close write end of pipe: %m");
135
136 return fd[0];
137 }
138
139 static int spawn_curl(const char* url) {
140 char **argv = STRV_MAKE("curl",
141 "-HAccept: application/vnd.fdo.journal",
142 "--silent",
143 "--show-error",
144 url);
145 int r;
146
147 r = spawn_child("curl", argv);
148 if (r < 0)
149 log_error_errno(r, "Failed to spawn curl: %m");
150 return r;
151 }
152
153 static int spawn_getter(const char *getter, const char *url) {
154 int r;
155 _cleanup_strv_free_ char **words = NULL;
156
157 assert(getter);
158 r = strv_split_extract(&words, getter, WHITESPACE, EXTRACT_QUOTES);
159 if (r < 0)
160 return log_error_errno(r, "Failed to split getter option: %m");
161
162 r = strv_extend(&words, url);
163 if (r < 0)
164 return log_error_errno(r, "Failed to create command line: %m");
165
166 r = spawn_child(words[0], words);
167 if (r < 0)
168 log_error_errno(r, "Failed to spawn getter %s: %m", getter);
169
170 return r;
171 }
172
173 #define filename_escape(s) xescape((s), "/ ")
174
175 static int open_output(Writer *w, const char* host) {
176 _cleanup_free_ char *_output = NULL;
177 const char *output;
178 int r;
179
180 switch (arg_split_mode) {
181 case JOURNAL_WRITE_SPLIT_NONE:
182 output = arg_output ?: REMOTE_JOURNAL_PATH "/remote.journal";
183 break;
184
185 case JOURNAL_WRITE_SPLIT_HOST: {
186 _cleanup_free_ char *name;
187
188 assert(host);
189
190 name = filename_escape(host);
191 if (!name)
192 return log_oom();
193
194 r = asprintf(&_output, "%s/remote-%s.journal",
195 arg_output ?: REMOTE_JOURNAL_PATH,
196 name);
197 if (r < 0)
198 return log_oom();
199
200 output = _output;
201 break;
202 }
203
204 default:
205 assert_not_reached("what?");
206 }
207
208 r = journal_file_open_reliably(output,
209 O_RDWR|O_CREAT, 0640,
210 arg_compress, arg_seal,
211 &w->metrics,
212 w->mmap,
213 NULL, &w->journal);
214 if (r < 0)
215 log_error_errno(r, "Failed to open output journal %s: %m",
216 output);
217 else
218 log_debug("Opened output file %s", w->journal->path);
219 return r;
220 }
221
222 /**********************************************************************
223 **********************************************************************
224 **********************************************************************/
225
226 static int init_writer_hashmap(RemoteServer *s) {
227 static const struct hash_ops *hash_ops[] = {
228 [JOURNAL_WRITE_SPLIT_NONE] = NULL,
229 [JOURNAL_WRITE_SPLIT_HOST] = &string_hash_ops,
230 };
231
232 assert(arg_split_mode >= 0 && arg_split_mode < (int) ELEMENTSOF(hash_ops));
233
234 s->writers = hashmap_new(hash_ops[arg_split_mode]);
235 if (!s->writers)
236 return log_oom();
237
238 return 0;
239 }
240
241 static int get_writer(RemoteServer *s, const char *host,
242 Writer **writer) {
243 const void *key;
244 _cleanup_writer_unref_ Writer *w = NULL;
245 int r;
246
247 switch(arg_split_mode) {
248 case JOURNAL_WRITE_SPLIT_NONE:
249 key = "one and only";
250 break;
251
252 case JOURNAL_WRITE_SPLIT_HOST:
253 assert(host);
254 key = host;
255 break;
256
257 default:
258 assert_not_reached("what split mode?");
259 }
260
261 w = hashmap_get(s->writers, key);
262 if (w)
263 writer_ref(w);
264 else {
265 w = writer_new(s);
266 if (!w)
267 return log_oom();
268
269 if (arg_split_mode == JOURNAL_WRITE_SPLIT_HOST) {
270 w->hashmap_key = strdup(key);
271 if (!w->hashmap_key)
272 return log_oom();
273 }
274
275 r = open_output(w, host);
276 if (r < 0)
277 return r;
278
279 r = hashmap_put(s->writers, w->hashmap_key ?: key, w);
280 if (r < 0)
281 return r;
282 }
283
284 *writer = w;
285 w = NULL;
286 return 0;
287 }
288
289 /**********************************************************************
290 **********************************************************************
291 **********************************************************************/
292
293 /* This should go away as soon as µhttpd allows state to be passed around. */
294 static RemoteServer *server;
295
296 static int dispatch_raw_source_event(sd_event_source *event,
297 int fd,
298 uint32_t revents,
299 void *userdata);
300 static int dispatch_raw_source_until_block(sd_event_source *event,
301 void *userdata);
302 static int dispatch_blocking_source_event(sd_event_source *event,
303 void *userdata);
304 static int dispatch_raw_connection_event(sd_event_source *event,
305 int fd,
306 uint32_t revents,
307 void *userdata);
308 static int dispatch_http_event(sd_event_source *event,
309 int fd,
310 uint32_t revents,
311 void *userdata);
312
313 static int get_source_for_fd(RemoteServer *s,
314 int fd, char *name, RemoteSource **source) {
315 Writer *writer;
316 int r;
317
318 /* This takes ownership of name, but only on success. */
319
320 assert(fd >= 0);
321 assert(source);
322
323 if (!GREEDY_REALLOC0(s->sources, s->sources_size, fd + 1))
324 return log_oom();
325
326 r = get_writer(s, name, &writer);
327 if (r < 0)
328 return log_warning_errno(r, "Failed to get writer for source %s: %m",
329 name);
330
331 if (s->sources[fd] == NULL) {
332 s->sources[fd] = source_new(fd, false, name, writer);
333 if (!s->sources[fd]) {
334 writer_unref(writer);
335 return log_oom();
336 }
337
338 s->active++;
339 }
340
341 *source = s->sources[fd];
342 return 0;
343 }
344
345 static int remove_source(RemoteServer *s, int fd) {
346 RemoteSource *source;
347
348 assert(s);
349 assert(fd >= 0 && fd < (ssize_t) s->sources_size);
350
351 source = s->sources[fd];
352 if (source) {
353 /* this closes fd too */
354 source_free(source);
355 s->sources[fd] = NULL;
356 s->active--;
357 }
358
359 return 0;
360 }
361
362 static int add_source(RemoteServer *s, int fd, char* name, bool own_name) {
363
364 RemoteSource *source = NULL;
365 int r;
366
367 /* This takes ownership of name, even on failure, if own_name is true. */
368
369 assert(s);
370 assert(fd >= 0);
371 assert(name);
372
373 if (!own_name) {
374 name = strdup(name);
375 if (!name)
376 return log_oom();
377 }
378
379 r = get_source_for_fd(s, fd, name, &source);
380 if (r < 0) {
381 log_error_errno(r, "Failed to create source for fd:%d (%s): %m",
382 fd, name);
383 free(name);
384 return r;
385 }
386
387 r = sd_event_add_io(s->events, &source->event,
388 fd, EPOLLIN|EPOLLRDHUP|EPOLLPRI,
389 dispatch_raw_source_event, source);
390 if (r == 0) {
391 /* Add additional source for buffer processing. It will be
392 * enabled later. */
393 r = sd_event_add_defer(s->events, &source->buffer_event,
394 dispatch_raw_source_until_block, source);
395 if (r == 0)
396 sd_event_source_set_enabled(source->buffer_event, SD_EVENT_OFF);
397 } else if (r == -EPERM) {
398 log_debug("Falling back to sd_event_add_defer for fd:%d (%s)", fd, name);
399 r = sd_event_add_defer(s->events, &source->event,
400 dispatch_blocking_source_event, source);
401 if (r == 0)
402 sd_event_source_set_enabled(source->event, SD_EVENT_ON);
403 }
404 if (r < 0) {
405 log_error_errno(r, "Failed to register event source for fd:%d: %m",
406 fd);
407 goto error;
408 }
409
410 r = sd_event_source_set_description(source->event, name);
411 if (r < 0) {
412 log_error_errno(r, "Failed to set source name for fd:%d: %m", fd);
413 goto error;
414 }
415
416 return 1; /* work to do */
417
418 error:
419 remove_source(s, fd);
420 return r;
421 }
422
423 static int add_raw_socket(RemoteServer *s, int fd) {
424 int r;
425 _cleanup_close_ int fd_ = fd;
426 char name[sizeof("raw-socket-")-1 + DECIMAL_STR_MAX(int) + 1];
427
428 assert(fd >= 0);
429
430 r = sd_event_add_io(s->events, &s->listen_event,
431 fd, EPOLLIN,
432 dispatch_raw_connection_event, s);
433 if (r < 0)
434 return r;
435
436 xsprintf(name, "raw-socket-%d", fd);
437
438 r = sd_event_source_set_description(s->listen_event, name);
439 if (r < 0)
440 return r;
441
442 fd_ = -1;
443 s->active ++;
444 return 0;
445 }
446
447 static int setup_raw_socket(RemoteServer *s, const char *address) {
448 int fd;
449
450 fd = make_socket_fd(LOG_INFO, address, SOCK_STREAM | SOCK_CLOEXEC);
451 if (fd < 0)
452 return fd;
453
454 return add_raw_socket(s, fd);
455 }
456
457 /**********************************************************************
458 **********************************************************************
459 **********************************************************************/
460
461 static int request_meta(void **connection_cls, int fd, char *hostname) {
462 RemoteSource *source;
463 Writer *writer;
464 int r;
465
466 assert(connection_cls);
467 if (*connection_cls)
468 return 0;
469
470 r = get_writer(server, hostname, &writer);
471 if (r < 0)
472 return log_warning_errno(r, "Failed to get writer for source %s: %m",
473 hostname);
474
475 source = source_new(fd, true, hostname, writer);
476 if (!source) {
477 writer_unref(writer);
478 return log_oom();
479 }
480
481 log_debug("Added RemoteSource as connection metadata %p", source);
482
483 *connection_cls = source;
484 return 0;
485 }
486
487 static void request_meta_free(void *cls,
488 struct MHD_Connection *connection,
489 void **connection_cls,
490 enum MHD_RequestTerminationCode toe) {
491 RemoteSource *s;
492
493 assert(connection_cls);
494 s = *connection_cls;
495
496 if (s) {
497 log_debug("Cleaning up connection metadata %p", s);
498 source_free(s);
499 *connection_cls = NULL;
500 }
501 }
502
503 static int process_http_upload(
504 struct MHD_Connection *connection,
505 const char *upload_data,
506 size_t *upload_data_size,
507 RemoteSource *source) {
508
509 bool finished = false;
510 size_t remaining;
511 int r;
512
513 assert(source);
514
515 log_trace("%s: connection %p, %zu bytes",
516 __func__, connection, *upload_data_size);
517
518 if (*upload_data_size) {
519 log_trace("Received %zu bytes", *upload_data_size);
520
521 r = push_data(source, upload_data, *upload_data_size);
522 if (r < 0)
523 return mhd_respond_oom(connection);
524
525 *upload_data_size = 0;
526 } else
527 finished = true;
528
529 for (;;) {
530 r = process_source(source, arg_compress, arg_seal);
531 if (r == -EAGAIN)
532 break;
533 else if (r < 0) {
534 log_warning("Failed to process data for connection %p", connection);
535 if (r == -E2BIG)
536 return mhd_respondf(connection,
537 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
538 "Entry is too large, maximum is %u bytes.\n",
539 DATA_SIZE_MAX);
540 else
541 return mhd_respondf(connection,
542 MHD_HTTP_UNPROCESSABLE_ENTITY,
543 "Processing failed: %s.", strerror(-r));
544 }
545 }
546
547 if (!finished)
548 return MHD_YES;
549
550 /* The upload is finished */
551
552 remaining = source_non_empty(source);
553 if (remaining > 0) {
554 log_warning("Premature EOFbyte. %zu bytes lost.", remaining);
555 return mhd_respondf(connection, MHD_HTTP_EXPECTATION_FAILED,
556 "Premature EOF. %zu bytes of trailing data not processed.",
557 remaining);
558 }
559
560 return mhd_respond(connection, MHD_HTTP_ACCEPTED, "OK.\n");
561 };
562
563 static int request_handler(
564 void *cls,
565 struct MHD_Connection *connection,
566 const char *url,
567 const char *method,
568 const char *version,
569 const char *upload_data,
570 size_t *upload_data_size,
571 void **connection_cls) {
572
573 const char *header;
574 int r, code, fd;
575 _cleanup_free_ char *hostname = NULL;
576
577 assert(connection);
578 assert(connection_cls);
579 assert(url);
580 assert(method);
581
582 log_trace("Handling a connection %s %s %s", method, url, version);
583
584 if (*connection_cls)
585 return process_http_upload(connection,
586 upload_data, upload_data_size,
587 *connection_cls);
588
589 if (!streq(method, "POST"))
590 return mhd_respond(connection, MHD_HTTP_METHOD_NOT_ACCEPTABLE,
591 "Unsupported method.\n");
592
593 if (!streq(url, "/upload"))
594 return mhd_respond(connection, MHD_HTTP_NOT_FOUND,
595 "Not found.\n");
596
597 header = MHD_lookup_connection_value(connection,
598 MHD_HEADER_KIND, "Content-Type");
599 if (!header || !streq(header, "application/vnd.fdo.journal"))
600 return mhd_respond(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE,
601 "Content-Type: application/vnd.fdo.journal"
602 " is required.\n");
603
604 {
605 const union MHD_ConnectionInfo *ci;
606
607 ci = MHD_get_connection_info(connection,
608 MHD_CONNECTION_INFO_CONNECTION_FD);
609 if (!ci) {
610 log_error("MHD_get_connection_info failed: cannot get remote fd");
611 return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
612 "Cannot check remote address");
613 }
614
615 fd = ci->connect_fd;
616 assert(fd >= 0);
617 }
618
619 if (server->check_trust) {
620 r = check_permissions(connection, &code, &hostname);
621 if (r < 0)
622 return code;
623 } else {
624 r = getnameinfo_pretty(fd, &hostname);
625 if (r < 0)
626 return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
627 "Cannot check remote hostname");
628 }
629
630 assert(hostname);
631
632 r = request_meta(connection_cls, fd, hostname);
633 if (r == -ENOMEM)
634 return respond_oom(connection);
635 else if (r < 0)
636 return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
637 strerror(-r));
638
639 hostname = NULL;
640 return MHD_YES;
641 }
642
643 static int setup_microhttpd_server(RemoteServer *s,
644 int fd,
645 const char *key,
646 const char *cert,
647 const char *trust) {
648 struct MHD_OptionItem opts[] = {
649 { MHD_OPTION_NOTIFY_COMPLETED, (intptr_t) request_meta_free},
650 { MHD_OPTION_EXTERNAL_LOGGER, (intptr_t) microhttpd_logger},
651 { MHD_OPTION_LISTEN_SOCKET, fd},
652 { MHD_OPTION_CONNECTION_MEMORY_LIMIT, DATA_SIZE_MAX},
653 { MHD_OPTION_END},
654 { MHD_OPTION_END},
655 { MHD_OPTION_END},
656 { MHD_OPTION_END}};
657 int opts_pos = 4;
658 int flags =
659 MHD_USE_DEBUG |
660 MHD_USE_DUAL_STACK |
661 MHD_USE_EPOLL_LINUX_ONLY |
662 MHD_USE_PEDANTIC_CHECKS |
663 MHD_USE_PIPE_FOR_SHUTDOWN;
664
665 const union MHD_DaemonInfo *info;
666 int r, epoll_fd;
667 MHDDaemonWrapper *d;
668
669 assert(fd >= 0);
670
671 r = fd_nonblock(fd, true);
672 if (r < 0)
673 return log_error_errno(r, "Failed to make fd:%d nonblocking: %m", fd);
674
675 if (key) {
676 assert(cert);
677
678 opts[opts_pos++] = (struct MHD_OptionItem)
679 {MHD_OPTION_HTTPS_MEM_KEY, 0, (char*) key};
680 opts[opts_pos++] = (struct MHD_OptionItem)
681 {MHD_OPTION_HTTPS_MEM_CERT, 0, (char*) cert};
682
683 flags |= MHD_USE_SSL;
684
685 if (trust)
686 opts[opts_pos++] = (struct MHD_OptionItem)
687 {MHD_OPTION_HTTPS_MEM_TRUST, 0, (char*) trust};
688 }
689
690 d = new(MHDDaemonWrapper, 1);
691 if (!d)
692 return log_oom();
693
694 d->fd = (uint64_t) fd;
695
696 d->daemon = MHD_start_daemon(flags, 0,
697 NULL, NULL,
698 request_handler, NULL,
699 MHD_OPTION_ARRAY, opts,
700 MHD_OPTION_END);
701 if (!d->daemon) {
702 log_error("Failed to start µhttp daemon");
703 r = -EINVAL;
704 goto error;
705 }
706
707 log_debug("Started MHD %s daemon on fd:%d (wrapper @ %p)",
708 key ? "HTTPS" : "HTTP", fd, d);
709
710
711 info = MHD_get_daemon_info(d->daemon, MHD_DAEMON_INFO_EPOLL_FD_LINUX_ONLY);
712 if (!info) {
713 log_error("µhttp returned NULL daemon info");
714 r = -EOPNOTSUPP;
715 goto error;
716 }
717
718 epoll_fd = info->listen_fd;
719 if (epoll_fd < 0) {
720 log_error("µhttp epoll fd is invalid");
721 r = -EUCLEAN;
722 goto error;
723 }
724
725 r = sd_event_add_io(s->events, &d->event,
726 epoll_fd, EPOLLIN,
727 dispatch_http_event, d);
728 if (r < 0) {
729 log_error_errno(r, "Failed to add event callback: %m");
730 goto error;
731 }
732
733 r = sd_event_source_set_description(d->event, "epoll-fd");
734 if (r < 0) {
735 log_error_errno(r, "Failed to set source name: %m");
736 goto error;
737 }
738
739 r = hashmap_ensure_allocated(&s->daemons, &uint64_hash_ops);
740 if (r < 0) {
741 log_oom();
742 goto error;
743 }
744
745 r = hashmap_put(s->daemons, &d->fd, d);
746 if (r < 0) {
747 log_error_errno(r, "Failed to add daemon to hashmap: %m");
748 goto error;
749 }
750
751 s->active ++;
752 return 0;
753
754 error:
755 MHD_stop_daemon(d->daemon);
756 free(d->daemon);
757 free(d);
758 return r;
759 }
760
761 static int setup_microhttpd_socket(RemoteServer *s,
762 const char *address,
763 const char *key,
764 const char *cert,
765 const char *trust) {
766 int fd;
767
768 fd = make_socket_fd(LOG_DEBUG, address, SOCK_STREAM | SOCK_CLOEXEC);
769 if (fd < 0)
770 return fd;
771
772 return setup_microhttpd_server(s, fd, key, cert, trust);
773 }
774
775 static int dispatch_http_event(sd_event_source *event,
776 int fd,
777 uint32_t revents,
778 void *userdata) {
779 MHDDaemonWrapper *d = userdata;
780 int r;
781
782 assert(d);
783
784 r = MHD_run(d->daemon);
785 if (r == MHD_NO) {
786 log_error("MHD_run failed!");
787 // XXX: unregister daemon
788 return -EINVAL;
789 }
790
791 return 1; /* work to do */
792 }
793
794 /**********************************************************************
795 **********************************************************************
796 **********************************************************************/
797
798 static int setup_signals(RemoteServer *s) {
799 int r;
800
801 assert(s);
802
803 assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, -1) >= 0);
804
805 r = sd_event_add_signal(s->events, &s->sigterm_event, SIGTERM, NULL, s);
806 if (r < 0)
807 return r;
808
809 r = sd_event_add_signal(s->events, &s->sigint_event, SIGINT, NULL, s);
810 if (r < 0)
811 return r;
812
813 return 0;
814 }
815
816 static int negative_fd(const char *spec) {
817 /* Return a non-positive number as its inverse, -EINVAL otherwise. */
818
819 int fd, r;
820
821 r = safe_atoi(spec, &fd);
822 if (r < 0)
823 return r;
824
825 if (fd > 0)
826 return -EINVAL;
827 else
828 return -fd;
829 }
830
831 static int remoteserver_init(RemoteServer *s,
832 const char* key,
833 const char* cert,
834 const char* trust) {
835 int r, n, fd;
836 char **file;
837
838 assert(s);
839
840 if ((arg_listen_raw || arg_listen_http) && trust) {
841 log_error("Option --trust makes all non-HTTPS connections untrusted.");
842 return -EINVAL;
843 }
844
845 r = sd_event_default(&s->events);
846 if (r < 0)
847 return log_error_errno(r, "Failed to allocate event loop: %m");
848
849 setup_signals(s);
850
851 assert(server == NULL);
852 server = s;
853
854 r = init_writer_hashmap(s);
855 if (r < 0)
856 return r;
857
858 n = sd_listen_fds(true);
859 if (n < 0)
860 return log_error_errno(n, "Failed to read listening file descriptors from environment: %m");
861 else
862 log_debug("Received %d descriptors", n);
863
864 if (MAX(http_socket, https_socket) >= SD_LISTEN_FDS_START + n) {
865 log_error("Received fewer sockets than expected");
866 return -EBADFD;
867 }
868
869 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
870 if (sd_is_socket(fd, AF_UNSPEC, 0, true)) {
871 log_debug("Received a listening socket (fd:%d)", fd);
872
873 if (fd == http_socket)
874 r = setup_microhttpd_server(s, fd, NULL, NULL, NULL);
875 else if (fd == https_socket)
876 r = setup_microhttpd_server(s, fd, key, cert, trust);
877 else
878 r = add_raw_socket(s, fd);
879 } else if (sd_is_socket(fd, AF_UNSPEC, 0, false)) {
880 char *hostname;
881
882 r = getnameinfo_pretty(fd, &hostname);
883 if (r < 0)
884 return log_error_errno(r, "Failed to retrieve remote name: %m");
885
886 log_debug("Received a connection socket (fd:%d) from %s", fd, hostname);
887
888 r = add_source(s, fd, hostname, true);
889 } else {
890 log_error("Unknown socket passed on fd:%d", fd);
891
892 return -EINVAL;
893 }
894
895 if (r < 0)
896 return log_error_errno(r, "Failed to register socket (fd:%d): %m",
897 fd);
898 }
899
900 if (arg_url) {
901 const char *url, *hostname;
902
903 url = strjoina(arg_url, "/entries");
904
905 if (arg_getter) {
906 log_info("Spawning getter %s...", url);
907 fd = spawn_getter(arg_getter, url);
908 } else {
909 log_info("Spawning curl %s...", url);
910 fd = spawn_curl(url);
911 }
912 if (fd < 0)
913 return fd;
914
915 hostname =
916 startswith(arg_url, "https://") ?:
917 startswith(arg_url, "http://") ?:
918 arg_url;
919
920 r = add_source(s, fd, (char*) hostname, false);
921 if (r < 0)
922 return r;
923 }
924
925 if (arg_listen_raw) {
926 log_debug("Listening on a socket...");
927 r = setup_raw_socket(s, arg_listen_raw);
928 if (r < 0)
929 return r;
930 }
931
932 if (arg_listen_http) {
933 r = setup_microhttpd_socket(s, arg_listen_http, NULL, NULL, NULL);
934 if (r < 0)
935 return r;
936 }
937
938 if (arg_listen_https) {
939 r = setup_microhttpd_socket(s, arg_listen_https, key, cert, trust);
940 if (r < 0)
941 return r;
942 }
943
944 STRV_FOREACH(file, arg_files) {
945 const char *output_name;
946
947 if (streq(*file, "-")) {
948 log_debug("Using standard input as source.");
949
950 fd = STDIN_FILENO;
951 output_name = "stdin";
952 } else {
953 log_debug("Reading file %s...", *file);
954
955 fd = open(*file, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
956 if (fd < 0)
957 return log_error_errno(errno, "Failed to open %s: %m", *file);
958 output_name = *file;
959 }
960
961 r = add_source(s, fd, (char*) output_name, false);
962 if (r < 0)
963 return r;
964 }
965
966 if (s->active == 0) {
967 log_error("Zero sources specified");
968 return -EINVAL;
969 }
970
971 if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE) {
972 /* In this case we know what the writer will be
973 called, so we can create it and verify that we can
974 create output as expected. */
975 r = get_writer(s, NULL, &s->_single_writer);
976 if (r < 0)
977 return r;
978 }
979
980 return 0;
981 }
982
983 static void server_destroy(RemoteServer *s) {
984 size_t i;
985 MHDDaemonWrapper *d;
986
987 while ((d = hashmap_steal_first(s->daemons))) {
988 MHD_stop_daemon(d->daemon);
989 sd_event_source_unref(d->event);
990 free(d);
991 }
992
993 hashmap_free(s->daemons);
994
995 assert(s->sources_size == 0 || s->sources);
996 for (i = 0; i < s->sources_size; i++)
997 remove_source(s, i);
998 free(s->sources);
999
1000 writer_unref(s->_single_writer);
1001 hashmap_free(s->writers);
1002
1003 sd_event_source_unref(s->sigterm_event);
1004 sd_event_source_unref(s->sigint_event);
1005 sd_event_source_unref(s->listen_event);
1006 sd_event_unref(s->events);
1007
1008 /* fds that we're listening on remain open... */
1009 }
1010
1011 /**********************************************************************
1012 **********************************************************************
1013 **********************************************************************/
1014
1015 static int handle_raw_source(sd_event_source *event,
1016 int fd,
1017 uint32_t revents,
1018 RemoteServer *s) {
1019
1020 RemoteSource *source;
1021 int r;
1022
1023 /* Returns 1 if there might be more data pending,
1024 * 0 if data is currently exhausted, negative on error.
1025 */
1026
1027 assert(fd >= 0 && fd < (ssize_t) s->sources_size);
1028 source = s->sources[fd];
1029 assert(source->fd == fd);
1030
1031 r = process_source(source, arg_compress, arg_seal);
1032 if (source->state == STATE_EOF) {
1033 size_t remaining;
1034
1035 log_debug("EOF reached with source fd:%d (%s)",
1036 source->fd, source->name);
1037
1038 remaining = source_non_empty(source);
1039 if (remaining > 0)
1040 log_notice("Premature EOF. %zu bytes lost.", remaining);
1041 remove_source(s, source->fd);
1042 log_debug("%zu active sources remaining", s->active);
1043 return 0;
1044 } else if (r == -E2BIG) {
1045 log_notice_errno(E2BIG, "Entry too big, skipped");
1046 return 1;
1047 } else if (r == -EAGAIN) {
1048 return 0;
1049 } else if (r < 0) {
1050 log_debug_errno(r, "Closing connection: %m");
1051 remove_source(server, fd);
1052 return 0;
1053 } else
1054 return 1;
1055 }
1056
1057 static int dispatch_raw_source_until_block(sd_event_source *event,
1058 void *userdata) {
1059 RemoteSource *source = userdata;
1060 int r;
1061
1062 /* Make sure event stays around even if source is destroyed */
1063 sd_event_source_ref(event);
1064
1065 r = handle_raw_source(event, source->fd, EPOLLIN, server);
1066 if (r != 1)
1067 /* No more data for now */
1068 sd_event_source_set_enabled(event, SD_EVENT_OFF);
1069
1070 sd_event_source_unref(event);
1071
1072 return r;
1073 }
1074
1075 static int dispatch_raw_source_event(sd_event_source *event,
1076 int fd,
1077 uint32_t revents,
1078 void *userdata) {
1079 RemoteSource *source = userdata;
1080 int r;
1081
1082 assert(source->event);
1083 assert(source->buffer_event);
1084
1085 r = handle_raw_source(event, fd, EPOLLIN, server);
1086 if (r == 1)
1087 /* Might have more data. We need to rerun the handler
1088 * until we are sure the buffer is exhausted. */
1089 sd_event_source_set_enabled(source->buffer_event, SD_EVENT_ON);
1090
1091 return r;
1092 }
1093
1094 static int dispatch_blocking_source_event(sd_event_source *event,
1095 void *userdata) {
1096 RemoteSource *source = userdata;
1097
1098 return handle_raw_source(event, source->fd, EPOLLIN, server);
1099 }
1100
1101 static int accept_connection(const char* type, int fd,
1102 SocketAddress *addr, char **hostname) {
1103 int fd2, r;
1104
1105 log_debug("Accepting new %s connection on fd:%d", type, fd);
1106 fd2 = accept4(fd, &addr->sockaddr.sa, &addr->size, SOCK_NONBLOCK|SOCK_CLOEXEC);
1107 if (fd2 < 0)
1108 return log_error_errno(errno, "accept() on fd:%d failed: %m", fd);
1109
1110 switch(socket_address_family(addr)) {
1111 case AF_INET:
1112 case AF_INET6: {
1113 _cleanup_free_ char *a = NULL;
1114 char *b;
1115
1116 r = socket_address_print(addr, &a);
1117 if (r < 0) {
1118 log_error_errno(r, "socket_address_print(): %m");
1119 close(fd2);
1120 return r;
1121 }
1122
1123 r = socknameinfo_pretty(&addr->sockaddr, addr->size, &b);
1124 if (r < 0) {
1125 log_error_errno(r, "Resolving hostname failed: %m");
1126 close(fd2);
1127 return r;
1128 }
1129
1130 log_debug("Accepted %s %s connection from %s",
1131 type,
1132 socket_address_family(addr) == AF_INET ? "IP" : "IPv6",
1133 a);
1134
1135 *hostname = b;
1136
1137 return fd2;
1138 };
1139 default:
1140 log_error("Rejected %s connection with unsupported family %d",
1141 type, socket_address_family(addr));
1142 close(fd2);
1143
1144 return -EINVAL;
1145 }
1146 }
1147
1148 static int dispatch_raw_connection_event(sd_event_source *event,
1149 int fd,
1150 uint32_t revents,
1151 void *userdata) {
1152 RemoteServer *s = userdata;
1153 int fd2;
1154 SocketAddress addr = {
1155 .size = sizeof(union sockaddr_union),
1156 .type = SOCK_STREAM,
1157 };
1158 char *hostname = NULL;
1159
1160 fd2 = accept_connection("raw", fd, &addr, &hostname);
1161 if (fd2 < 0)
1162 return fd2;
1163
1164 return add_source(s, fd2, hostname, true);
1165 }
1166
1167 /**********************************************************************
1168 **********************************************************************
1169 **********************************************************************/
1170
1171 static const char* const journal_write_split_mode_table[_JOURNAL_WRITE_SPLIT_MAX] = {
1172 [JOURNAL_WRITE_SPLIT_NONE] = "none",
1173 [JOURNAL_WRITE_SPLIT_HOST] = "host",
1174 };
1175
1176 DEFINE_PRIVATE_STRING_TABLE_LOOKUP(journal_write_split_mode, JournalWriteSplitMode);
1177 static DEFINE_CONFIG_PARSE_ENUM(config_parse_write_split_mode,
1178 journal_write_split_mode,
1179 JournalWriteSplitMode,
1180 "Failed to parse split mode setting");
1181
1182 static int parse_config(void) {
1183 const ConfigTableItem items[] = {
1184 { "Remote", "SplitMode", config_parse_write_split_mode, 0, &arg_split_mode },
1185 { "Remote", "ServerKeyFile", config_parse_path, 0, &arg_key },
1186 { "Remote", "ServerCertificateFile", config_parse_path, 0, &arg_cert },
1187 { "Remote", "TrustedCertificateFile", config_parse_path, 0, &arg_trust },
1188 {}};
1189
1190 return config_parse_many(PKGSYSCONFDIR "/journal-remote.conf",
1191 CONF_PATHS_NULSTR("systemd/journal-remote.conf.d"),
1192 "Remote\0", config_item_table_lookup, items,
1193 false, NULL);
1194 }
1195
1196 static void help(void) {
1197 printf("%s [OPTIONS...] {FILE|-}...\n\n"
1198 "Write external journal events to journal file(s).\n\n"
1199 " -h --help Show this help\n"
1200 " --version Show package version\n"
1201 " --url=URL Read events from systemd-journal-gatewayd at URL\n"
1202 " --getter=COMMAND Read events from the output of COMMAND\n"
1203 " --listen-raw=ADDR Listen for connections at ADDR\n"
1204 " --listen-http=ADDR Listen for HTTP connections at ADDR\n"
1205 " --listen-https=ADDR Listen for HTTPS connections at ADDR\n"
1206 " -o --output=FILE|DIR Write output to FILE or DIR/external-*.journal\n"
1207 " --compress[=BOOL] XZ-compress the output journal (default: yes)\n"
1208 " --seal[=BOOL] Use event sealing (default: no)\n"
1209 " --key=FILENAME SSL key in PEM format (default:\n"
1210 " \"" PRIV_KEY_FILE "\")\n"
1211 " --cert=FILENAME SSL certificate in PEM format (default:\n"
1212 " \"" CERT_FILE "\")\n"
1213 " --trust=FILENAME|all SSL CA certificate or disable checking (default:\n"
1214 " \"" TRUST_FILE "\")\n"
1215 " --gnutls-log=CATEGORY...\n"
1216 " Specify a list of gnutls logging categories\n"
1217 " --split-mode=none|host How many output files to create\n"
1218 "\n"
1219 "Note: file descriptors from sd_listen_fds() will be consumed, too.\n"
1220 , program_invocation_short_name);
1221 }
1222
1223 static int parse_argv(int argc, char *argv[]) {
1224 enum {
1225 ARG_VERSION = 0x100,
1226 ARG_URL,
1227 ARG_LISTEN_RAW,
1228 ARG_LISTEN_HTTP,
1229 ARG_LISTEN_HTTPS,
1230 ARG_GETTER,
1231 ARG_SPLIT_MODE,
1232 ARG_COMPRESS,
1233 ARG_SEAL,
1234 ARG_KEY,
1235 ARG_CERT,
1236 ARG_TRUST,
1237 ARG_GNUTLS_LOG,
1238 };
1239
1240 static const struct option options[] = {
1241 { "help", no_argument, NULL, 'h' },
1242 { "version", no_argument, NULL, ARG_VERSION },
1243 { "url", required_argument, NULL, ARG_URL },
1244 { "getter", required_argument, NULL, ARG_GETTER },
1245 { "listen-raw", required_argument, NULL, ARG_LISTEN_RAW },
1246 { "listen-http", required_argument, NULL, ARG_LISTEN_HTTP },
1247 { "listen-https", required_argument, NULL, ARG_LISTEN_HTTPS },
1248 { "output", required_argument, NULL, 'o' },
1249 { "split-mode", required_argument, NULL, ARG_SPLIT_MODE },
1250 { "compress", optional_argument, NULL, ARG_COMPRESS },
1251 { "seal", optional_argument, NULL, ARG_SEAL },
1252 { "key", required_argument, NULL, ARG_KEY },
1253 { "cert", required_argument, NULL, ARG_CERT },
1254 { "trust", required_argument, NULL, ARG_TRUST },
1255 { "gnutls-log", required_argument, NULL, ARG_GNUTLS_LOG },
1256 {}
1257 };
1258
1259 int c, r;
1260 bool type_a, type_b;
1261
1262 assert(argc >= 0);
1263 assert(argv);
1264
1265 while ((c = getopt_long(argc, argv, "ho:", options, NULL)) >= 0)
1266 switch(c) {
1267 case 'h':
1268 help();
1269 return 0 /* done */;
1270
1271 case ARG_VERSION:
1272 return version();
1273
1274 case ARG_URL:
1275 if (arg_url) {
1276 log_error("cannot currently set more than one --url");
1277 return -EINVAL;
1278 }
1279
1280 arg_url = optarg;
1281 break;
1282
1283 case ARG_GETTER:
1284 if (arg_getter) {
1285 log_error("cannot currently use --getter more than once");
1286 return -EINVAL;
1287 }
1288
1289 arg_getter = optarg;
1290 break;
1291
1292 case ARG_LISTEN_RAW:
1293 if (arg_listen_raw) {
1294 log_error("cannot currently use --listen-raw more than once");
1295 return -EINVAL;
1296 }
1297
1298 arg_listen_raw = optarg;
1299 break;
1300
1301 case ARG_LISTEN_HTTP:
1302 if (arg_listen_http || http_socket >= 0) {
1303 log_error("cannot currently use --listen-http more than once");
1304 return -EINVAL;
1305 }
1306
1307 r = negative_fd(optarg);
1308 if (r >= 0)
1309 http_socket = r;
1310 else
1311 arg_listen_http = optarg;
1312 break;
1313
1314 case ARG_LISTEN_HTTPS:
1315 if (arg_listen_https || https_socket >= 0) {
1316 log_error("cannot currently use --listen-https more than once");
1317 return -EINVAL;
1318 }
1319
1320 r = negative_fd(optarg);
1321 if (r >= 0)
1322 https_socket = r;
1323 else
1324 arg_listen_https = optarg;
1325
1326 break;
1327
1328 case ARG_KEY:
1329 if (arg_key) {
1330 log_error("Key file specified twice");
1331 return -EINVAL;
1332 }
1333
1334 arg_key = strdup(optarg);
1335 if (!arg_key)
1336 return log_oom();
1337
1338 break;
1339
1340 case ARG_CERT:
1341 if (arg_cert) {
1342 log_error("Certificate file specified twice");
1343 return -EINVAL;
1344 }
1345
1346 arg_cert = strdup(optarg);
1347 if (!arg_cert)
1348 return log_oom();
1349
1350 break;
1351
1352 case ARG_TRUST:
1353 if (arg_trust || arg_trust_all) {
1354 log_error("Confusing trusted CA configuration");
1355 return -EINVAL;
1356 }
1357
1358 if (streq(optarg, "all"))
1359 arg_trust_all = true;
1360 else {
1361 #ifdef HAVE_GNUTLS
1362 arg_trust = strdup(optarg);
1363 if (!arg_trust)
1364 return log_oom();
1365 #else
1366 log_error("Option --trust is not available.");
1367 return -EINVAL;
1368 #endif
1369 }
1370
1371 break;
1372
1373 case 'o':
1374 if (arg_output) {
1375 log_error("cannot use --output/-o more than once");
1376 return -EINVAL;
1377 }
1378
1379 arg_output = optarg;
1380 break;
1381
1382 case ARG_SPLIT_MODE:
1383 arg_split_mode = journal_write_split_mode_from_string(optarg);
1384 if (arg_split_mode == _JOURNAL_WRITE_SPLIT_INVALID) {
1385 log_error("Invalid split mode: %s", optarg);
1386 return -EINVAL;
1387 }
1388 break;
1389
1390 case ARG_COMPRESS:
1391 if (optarg) {
1392 r = parse_boolean(optarg);
1393 if (r < 0) {
1394 log_error("Failed to parse --compress= parameter.");
1395 return -EINVAL;
1396 }
1397
1398 arg_compress = !!r;
1399 } else
1400 arg_compress = true;
1401
1402 break;
1403
1404 case ARG_SEAL:
1405 if (optarg) {
1406 r = parse_boolean(optarg);
1407 if (r < 0) {
1408 log_error("Failed to parse --seal= parameter.");
1409 return -EINVAL;
1410 }
1411
1412 arg_seal = !!r;
1413 } else
1414 arg_seal = true;
1415
1416 break;
1417
1418 case ARG_GNUTLS_LOG: {
1419 #ifdef HAVE_GNUTLS
1420 const char* p = optarg;
1421 for (;;) {
1422 _cleanup_free_ char *word = NULL;
1423
1424 r = extract_first_word(&p, &word, ",", 0);
1425 if (r < 0)
1426 return log_error_errno(r, "Failed to parse --gnutls-log= argument: %m");
1427
1428 if (r == 0)
1429 break;
1430
1431 if (strv_push(&arg_gnutls_log, word) < 0)
1432 return log_oom();
1433
1434 word = NULL;
1435 }
1436 break;
1437 #else
1438 log_error("Option --gnutls-log is not available.");
1439 return -EINVAL;
1440 #endif
1441 }
1442
1443 case '?':
1444 return -EINVAL;
1445
1446 default:
1447 assert_not_reached("Unknown option code.");
1448 }
1449
1450 if (optind < argc)
1451 arg_files = argv + optind;
1452
1453 type_a = arg_getter || !strv_isempty(arg_files);
1454 type_b = arg_url
1455 || arg_listen_raw
1456 || arg_listen_http || arg_listen_https
1457 || sd_listen_fds(false) > 0;
1458 if (type_a && type_b) {
1459 log_error("Cannot use file input or --getter with "
1460 "--arg-listen-... or socket activation.");
1461 return -EINVAL;
1462 }
1463 if (type_a) {
1464 if (!arg_output) {
1465 log_error("Option --output must be specified with file input or --getter.");
1466 return -EINVAL;
1467 }
1468
1469 arg_split_mode = JOURNAL_WRITE_SPLIT_NONE;
1470 }
1471
1472 if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE
1473 && arg_output && is_dir(arg_output, true) > 0) {
1474 log_error("For SplitMode=none, output must be a file.");
1475 return -EINVAL;
1476 }
1477
1478 if (arg_split_mode == JOURNAL_WRITE_SPLIT_HOST
1479 && arg_output && is_dir(arg_output, true) <= 0) {
1480 log_error("For SplitMode=host, output must be a directory.");
1481 return -EINVAL;
1482 }
1483
1484 log_debug("Full config: SplitMode=%s Key=%s Cert=%s Trust=%s",
1485 journal_write_split_mode_to_string(arg_split_mode),
1486 strna(arg_key),
1487 strna(arg_cert),
1488 strna(arg_trust));
1489
1490 return 1 /* work to do */;
1491 }
1492
1493 static int load_certificates(char **key, char **cert, char **trust) {
1494 int r;
1495
1496 r = read_full_file(arg_key ?: PRIV_KEY_FILE, key, NULL);
1497 if (r < 0)
1498 return log_error_errno(r, "Failed to read key from file '%s': %m",
1499 arg_key ?: PRIV_KEY_FILE);
1500
1501 r = read_full_file(arg_cert ?: CERT_FILE, cert, NULL);
1502 if (r < 0)
1503 return log_error_errno(r, "Failed to read certificate from file '%s': %m",
1504 arg_cert ?: CERT_FILE);
1505
1506 if (arg_trust_all)
1507 log_info("Certificate checking disabled.");
1508 else {
1509 r = read_full_file(arg_trust ?: TRUST_FILE, trust, NULL);
1510 if (r < 0)
1511 return log_error_errno(r, "Failed to read CA certificate file '%s': %m",
1512 arg_trust ?: TRUST_FILE);
1513 }
1514
1515 return 0;
1516 }
1517
1518 int main(int argc, char **argv) {
1519 RemoteServer s = {};
1520 int r;
1521 _cleanup_free_ char *key = NULL, *cert = NULL, *trust = NULL;
1522
1523 log_show_color(true);
1524 log_parse_environment();
1525
1526 r = parse_config();
1527 if (r < 0)
1528 return EXIT_FAILURE;
1529
1530 r = parse_argv(argc, argv);
1531 if (r <= 0)
1532 return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
1533
1534
1535 if (arg_listen_http || arg_listen_https) {
1536 r = setup_gnutls_logger(arg_gnutls_log);
1537 if (r < 0)
1538 return EXIT_FAILURE;
1539 }
1540
1541 if (arg_listen_https || https_socket >= 0)
1542 if (load_certificates(&key, &cert, &trust) < 0)
1543 return EXIT_FAILURE;
1544
1545 if (remoteserver_init(&s, key, cert, trust) < 0)
1546 return EXIT_FAILURE;
1547
1548 r = sd_event_set_watchdog(s.events, true);
1549 if (r < 0)
1550 log_error_errno(r, "Failed to enable watchdog: %m");
1551 else
1552 log_debug("Watchdog is %s.", r > 0 ? "enabled" : "disabled");
1553
1554 log_debug("%s running as pid "PID_FMT,
1555 program_invocation_short_name, getpid());
1556 sd_notify(false,
1557 "READY=1\n"
1558 "STATUS=Processing requests...");
1559
1560 while (s.active) {
1561 r = sd_event_get_state(s.events);
1562 if (r < 0)
1563 break;
1564 if (r == SD_EVENT_FINISHED)
1565 break;
1566
1567 r = sd_event_run(s.events, -1);
1568 if (r < 0) {
1569 log_error_errno(r, "Failed to run event loop: %m");
1570 break;
1571 }
1572 }
1573
1574 sd_notifyf(false,
1575 "STOPPING=1\n"
1576 "STATUS=Shutting down after writing %" PRIu64 " entries...", s.event_count);
1577 log_info("Finishing after writing %" PRIu64 " entries", s.event_count);
1578
1579 server_destroy(&s);
1580
1581 free(arg_key);
1582 free(arg_cert);
1583 free(arg_trust);
1584
1585 return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
1586 }