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