chiark / gitweb /
journal-remote: fix mem leak on error
[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 fd_fd(const char *spec) {
800         int fd, r;
801
802         r = safe_atoi(spec, &fd);
803         if (r < 0)
804                 return r;
805         if (fd < 0)
806                 return -EINVAL;
807
808         return fd;
809 }
810
811 static int remoteserver_init(RemoteServer *s,
812                              const char* key,
813                              const char* cert,
814                              const char* trust) {
815         int r, n, fd;
816         char **file;
817
818         assert(s);
819
820         if ((arg_listen_raw || arg_listen_http) && trust) {
821                 log_error("Option --trust makes all non-HTTPS connections untrusted.");
822                 return -EINVAL;
823         }
824
825         r = sd_event_default(&s->events);
826         if (r < 0) {
827                 log_error("Failed to allocate event loop: %s", strerror(-r));
828                 return r;
829         }
830
831         setup_signals(s);
832
833         assert(server == NULL);
834         server = s;
835
836         r = init_writer_hashmap(s);
837         if (r < 0)
838                 return r;
839
840         n = sd_listen_fds(true);
841         if (n < 0) {
842                 log_error("Failed to read listening file descriptors from environment: %s",
843                           strerror(-n));
844                 return n;
845         } else
846                 log_info("Received %d descriptors", n);
847
848         if (MAX(http_socket, https_socket) >= SD_LISTEN_FDS_START + n) {
849                 log_error("Received fewer sockets than expected");
850                 return -EBADFD;
851         }
852
853         for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
854                 if (sd_is_socket(fd, AF_UNSPEC, 0, false)) {
855                         log_info("Received a listening socket (fd:%d)", fd);
856
857                         if (fd == http_socket)
858                                 r = setup_microhttpd_server(s, fd, NULL, NULL, NULL);
859                         else if (fd == https_socket)
860                                 r = setup_microhttpd_server(s, fd, key, cert, trust);
861                         else
862                                 r = add_raw_socket(s, fd);
863                 } else if (sd_is_socket(fd, AF_UNSPEC, 0, true)) {
864                         char *hostname;
865
866                         r = getnameinfo_pretty(fd, &hostname);
867                         if (r < 0) {
868                                 log_error("Failed to retrieve remote name: %s", strerror(-r));
869                                 return r;
870                         }
871
872                         log_info("Received a connection socket (fd:%d) from %s", fd, hostname);
873
874                         r = add_source(s, fd, hostname, true);
875                 } else {
876                         log_error("Unknown socket passed on fd:%d", fd);
877
878                         return -EINVAL;
879                 }
880
881                 if(r < 0) {
882                         log_error("Failed to register socket (fd:%d): %s",
883                                   fd, strerror(-r));
884                         return r;
885                 }
886         }
887
888         if (arg_url) {
889                 const char *url, *hostname;
890
891                 url = strappenda(arg_url, "/entries");
892
893                 if (arg_getter) {
894                         log_info("Spawning getter %s...", url);
895                         fd = spawn_getter(arg_getter, url);
896                 } else {
897                         log_info("Spawning curl %s...", url);
898                         fd = spawn_curl(url);
899                 }
900                 if (fd < 0)
901                         return fd;
902
903                 hostname =
904                         startswith(arg_url, "https://") ?:
905                         startswith(arg_url, "http://") ?:
906                         arg_url;
907
908                 r = add_source(s, fd, (char*) hostname, false);
909                 if (r < 0)
910                         return r;
911         }
912
913         if (arg_listen_raw) {
914                 log_info("Listening on a socket...");
915                 r = setup_raw_socket(s, arg_listen_raw);
916                 if (r < 0)
917                         return r;
918         }
919
920         if (arg_listen_http) {
921                 r = setup_microhttpd_socket(s, arg_listen_http, NULL, NULL, NULL);
922                 if (r < 0)
923                         return r;
924         }
925
926         if (arg_listen_https) {
927                 r = setup_microhttpd_socket(s, arg_listen_https, key, cert, trust);
928                 if (r < 0)
929                         return r;
930         }
931
932         STRV_FOREACH(file, arg_files) {
933                 const char *output_name;
934
935                 if (streq(*file, "-")) {
936                         log_info("Using standard input as source.");
937
938                         fd = STDIN_FILENO;
939                         output_name = "stdin";
940                 } else {
941                         log_info("Reading file %s...", *file);
942
943                         fd = open(*file, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
944                         if (fd < 0) {
945                                 log_error("Failed to open %s: %m", *file);
946                                 return -errno;
947                         }
948                         output_name = *file;
949                 }
950
951                 r = add_source(s, fd, (char*) output_name, false);
952                 if (r < 0)
953                         return r;
954         }
955
956         if (s->active == 0) {
957                 log_error("Zarro sources specified");
958                 return -EINVAL;
959         }
960
961         if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE) {
962                 /* In this case we know what the writer will be
963                    called, so we can create it and verify that we can
964                    create output as expected. */
965                 r = get_writer(s, NULL, &s->_single_writer);
966                 if (r < 0)
967                         return r;
968         }
969
970         return 0;
971 }
972
973 static void server_destroy(RemoteServer *s) {
974         size_t i;
975         MHDDaemonWrapper *d;
976
977         while ((d = hashmap_steal_first(s->daemons))) {
978                 MHD_stop_daemon(d->daemon);
979                 sd_event_source_unref(d->event);
980                 free(d);
981         }
982
983         hashmap_free(s->daemons);
984
985         assert(s->sources_size == 0 || s->sources);
986         for (i = 0; i < s->sources_size; i++)
987                 remove_source(s, i);
988         free(s->sources);
989
990         writer_unref(s->_single_writer);
991         hashmap_free(s->writers);
992
993         sd_event_source_unref(s->sigterm_event);
994         sd_event_source_unref(s->sigint_event);
995         sd_event_source_unref(s->listen_event);
996         sd_event_unref(s->events);
997
998         /* fds that we're listening on remain open... */
999 }
1000
1001 /**********************************************************************
1002  **********************************************************************
1003  **********************************************************************/
1004
1005 static int dispatch_raw_source_event(sd_event_source *event,
1006                                      int fd,
1007                                      uint32_t revents,
1008                                      void *userdata) {
1009
1010         RemoteServer *s = userdata;
1011         RemoteSource *source;
1012         int r;
1013
1014         assert(fd >= 0 && fd < (ssize_t) s->sources_size);
1015         source = s->sources[fd];
1016         assert(source->fd == fd);
1017
1018         r = process_source(source, arg_compress, arg_seal);
1019         if (source->state == STATE_EOF) {
1020                 size_t remaining;
1021
1022                 log_info("EOF reached with source fd:%d (%s)",
1023                          source->fd, source->name);
1024
1025                 remaining = source_non_empty(source);
1026                 if (remaining > 0)
1027                         log_warning("Premature EOF. %zu bytes lost.", remaining);
1028                 remove_source(s, source->fd);
1029                 log_info("%zd active sources remaining", s->active);
1030                 return 0;
1031         } else if (r == -E2BIG) {
1032                 log_error("Entry too big, skipped");
1033                 return 1;
1034         } else if (r == -EAGAIN) {
1035                 return 0;
1036         } else if (r < 0) {
1037                 log_info("Closing connection: %s", strerror(-r));
1038                 remove_source(server, fd);
1039                 return 0;
1040         } else
1041                 return 1;
1042 }
1043
1044 static int dispatch_blocking_source_event(sd_event_source *event,
1045                                           void *userdata) {
1046         RemoteSource *source = userdata;
1047
1048         return dispatch_raw_source_event(event, source->fd, EPOLLIN, server);
1049 }
1050
1051 static int accept_connection(const char* type, int fd,
1052                              SocketAddress *addr, char **hostname) {
1053         int fd2, r;
1054
1055         log_debug("Accepting new %s connection on fd:%d", type, fd);
1056         fd2 = accept4(fd, &addr->sockaddr.sa, &addr->size, SOCK_NONBLOCK|SOCK_CLOEXEC);
1057         if (fd2 < 0) {
1058                 log_error("accept() on fd:%d failed: %m", fd);
1059                 return -errno;
1060         }
1061
1062         switch(socket_address_family(addr)) {
1063         case AF_INET:
1064         case AF_INET6: {
1065                 _cleanup_free_ char *a = NULL;
1066                 char *b;
1067
1068                 r = socket_address_print(addr, &a);
1069                 if (r < 0) {
1070                         log_error("socket_address_print(): %s", strerror(-r));
1071                         close(fd2);
1072                         return r;
1073                 }
1074
1075                 r = socknameinfo_pretty(&addr->sockaddr, addr->size, &b);
1076                 if (r < 0) {
1077                         close(fd2);
1078                         return r;
1079                 }
1080
1081                 log_info("Accepted %s %s connection from %s",
1082                          type,
1083                          socket_address_family(addr) == AF_INET ? "IP" : "IPv6",
1084                          a);
1085
1086                 *hostname = b;
1087
1088                 return fd2;
1089         };
1090         default:
1091                 log_error("Rejected %s connection with unsupported family %d",
1092                           type, socket_address_family(addr));
1093                 close(fd2);
1094
1095                 return -EINVAL;
1096         }
1097 }
1098
1099 static int dispatch_raw_connection_event(sd_event_source *event,
1100                                          int fd,
1101                                          uint32_t revents,
1102                                          void *userdata) {
1103         RemoteServer *s = userdata;
1104         int fd2;
1105         SocketAddress addr = {
1106                 .size = sizeof(union sockaddr_union),
1107                 .type = SOCK_STREAM,
1108         };
1109         char *hostname;
1110
1111         fd2 = accept_connection("raw", fd, &addr, &hostname);
1112         if (fd2 < 0)
1113                 return fd2;
1114
1115         return add_source(s, fd2, hostname, true);
1116 }
1117
1118 /**********************************************************************
1119  **********************************************************************
1120  **********************************************************************/
1121
1122 static const char* const journal_write_split_mode_table[_JOURNAL_WRITE_SPLIT_MAX] = {
1123         [JOURNAL_WRITE_SPLIT_NONE] = "none",
1124         [JOURNAL_WRITE_SPLIT_HOST] = "host",
1125 };
1126
1127 DEFINE_PRIVATE_STRING_TABLE_LOOKUP(journal_write_split_mode, JournalWriteSplitMode);
1128 static DEFINE_CONFIG_PARSE_ENUM(config_parse_write_split_mode,
1129                                 journal_write_split_mode,
1130                                 JournalWriteSplitMode,
1131                                 "Failed to parse split mode setting");
1132
1133 static int parse_config(void) {
1134         const ConfigTableItem items[] = {
1135                 { "Remote",  "SplitMode",              config_parse_write_split_mode, 0, &arg_split_mode },
1136                 { "Remote",  "ServerKeyFile",          config_parse_path,             0, &arg_key        },
1137                 { "Remote",  "ServerCertificateFile",  config_parse_path,             0, &arg_cert       },
1138                 { "Remote",  "TrustedCertificateFile", config_parse_path,             0, &arg_trust      },
1139                 {}};
1140
1141         return config_parse(NULL, PKGSYSCONFDIR "/journal-remote.conf", NULL,
1142                             "Remote\0",
1143                             config_item_table_lookup, items,
1144                             false, false, true, NULL);
1145 }
1146
1147 static void help(void) {
1148         printf("%s [OPTIONS...] {FILE|-}...\n\n"
1149                "Write external journal events to journal file(s).\n\n"
1150                "  -h --help               Show this help\n"
1151                "     --version            Show package version\n"
1152                "     --url=URL            Read events from systemd-journal-gatewayd at URL\n"
1153                "     --getter=COMMAND     Read events from the output of COMMAND\n"
1154                "     --listen-raw=ADDR    Listen for connections at ADDR\n"
1155                "     --listen-http=ADDR   Listen for HTTP connections at ADDR\n"
1156                "     --listen-https=ADDR  Listen for HTTPS connections at ADDR\n"
1157                "  -o --output=FILE|DIR Write output to FILE or DIR/external-*.journal\n"
1158                "     --compress[=BOOL]    Use XZ-compression in the output journal (default: yes)\n"
1159                "     --seal[=BOOL]        Use Event sealing in the output journal (default: no)\n"
1160                "     --key=FILENAME       Specify key in PEM format (default:\n"
1161                "                          \"" PRIV_KEY_FILE "\")\n"
1162                "     --cert=FILENAME      Specify certificate in PEM format (default:\n"
1163                "                          \"" CERT_FILE "\")\n"
1164                "     --trust=FILENAME|all Specify CA certificate or disable checking (default:\n"
1165                "                          \"" TRUST_FILE "\")\n"
1166                "     --gnutls-log=CATEGORY...\n"
1167                "                          Specify a list of gnutls logging categories\n"
1168                "\n"
1169                "Note: file descriptors from sd_listen_fds() will be consumed, too.\n"
1170                , program_invocation_short_name);
1171 }
1172
1173 static int parse_argv(int argc, char *argv[]) {
1174         enum {
1175                 ARG_VERSION = 0x100,
1176                 ARG_URL,
1177                 ARG_LISTEN_RAW,
1178                 ARG_LISTEN_HTTP,
1179                 ARG_LISTEN_HTTPS,
1180                 ARG_GETTER,
1181                 ARG_SPLIT_MODE,
1182                 ARG_COMPRESS,
1183                 ARG_SEAL,
1184                 ARG_KEY,
1185                 ARG_CERT,
1186                 ARG_TRUST,
1187                 ARG_GNUTLS_LOG,
1188         };
1189
1190         static const struct option options[] = {
1191                 { "help",         no_argument,       NULL, 'h'              },
1192                 { "version",      no_argument,       NULL, ARG_VERSION      },
1193                 { "url",          required_argument, NULL, ARG_URL          },
1194                 { "getter",       required_argument, NULL, ARG_GETTER       },
1195                 { "listen-raw",   required_argument, NULL, ARG_LISTEN_RAW   },
1196                 { "listen-http",  required_argument, NULL, ARG_LISTEN_HTTP  },
1197                 { "listen-https", required_argument, NULL, ARG_LISTEN_HTTPS },
1198                 { "output",       required_argument, NULL, 'o'              },
1199                 { "split-mode",   required_argument, NULL, ARG_SPLIT_MODE   },
1200                 { "compress",     optional_argument, NULL, ARG_COMPRESS     },
1201                 { "seal",         optional_argument, NULL, ARG_SEAL         },
1202                 { "key",          required_argument, NULL, ARG_KEY          },
1203                 { "cert",         required_argument, NULL, ARG_CERT         },
1204                 { "trust",        required_argument, NULL, ARG_TRUST        },
1205                 { "gnutls-log",   required_argument, NULL, ARG_GNUTLS_LOG   },
1206                 {}
1207         };
1208
1209         int c, r;
1210         bool type_a, type_b;
1211
1212         assert(argc >= 0);
1213         assert(argv);
1214
1215         while ((c = getopt_long(argc, argv, "ho:", options, NULL)) >= 0)
1216                 switch(c) {
1217                 case 'h':
1218                         help();
1219                         return 0 /* done */;
1220
1221                 case ARG_VERSION:
1222                         puts(PACKAGE_STRING);
1223                         puts(SYSTEMD_FEATURES);
1224                         return 0 /* done */;
1225
1226                 case ARG_URL:
1227                         if (arg_url) {
1228                                 log_error("cannot currently set more than one --url");
1229                                 return -EINVAL;
1230                         }
1231
1232                         arg_url = optarg;
1233                         break;
1234
1235                 case ARG_GETTER:
1236                         if (arg_getter) {
1237                                 log_error("cannot currently use --getter more than once");
1238                                 return -EINVAL;
1239                         }
1240
1241                         arg_getter = optarg;
1242                         break;
1243
1244                 case ARG_LISTEN_RAW:
1245                         if (arg_listen_raw) {
1246                                 log_error("cannot currently use --listen-raw more than once");
1247                                 return -EINVAL;
1248                         }
1249
1250                         arg_listen_raw = optarg;
1251                         break;
1252
1253                 case ARG_LISTEN_HTTP:
1254                         if (arg_listen_http || http_socket >= 0) {
1255                                 log_error("cannot currently use --listen-http more than once");
1256                                 return -EINVAL;
1257                         }
1258
1259                         r = fd_fd(optarg);
1260                         if (r >= 0)
1261                                 http_socket = r;
1262                         else
1263                                 arg_listen_http = optarg;
1264                         break;
1265
1266                 case ARG_LISTEN_HTTPS:
1267                         if (arg_listen_https || https_socket >= 0) {
1268                                 log_error("cannot currently use --listen-https more than once");
1269                                 return -EINVAL;
1270                         }
1271
1272                         r = fd_fd(optarg);
1273                         if (r >= 0)
1274                                 https_socket = r;
1275                         else
1276                                 arg_listen_https = optarg;
1277
1278                         break;
1279
1280                 case ARG_KEY:
1281                         if (arg_key) {
1282                                 log_error("Key file specified twice");
1283                                 return -EINVAL;
1284                         }
1285
1286                         arg_key = strdup(optarg);
1287                         if (!arg_key)
1288                                 return log_oom();
1289
1290                         break;
1291
1292                 case ARG_CERT:
1293                         if (arg_cert) {
1294                                 log_error("Certificate file specified twice");
1295                                 return -EINVAL;
1296                         }
1297
1298                         arg_cert = strdup(optarg);
1299                         if (!arg_cert)
1300                                 return log_oom();
1301
1302                         break;
1303
1304                 case ARG_TRUST:
1305                         if (arg_trust || arg_trust_all) {
1306                                 log_error("Confusing trusted CA configuration");
1307                                 return -EINVAL;
1308                         }
1309
1310                         if (streq(optarg, "all"))
1311                                 arg_trust_all = true;
1312                         else {
1313 #ifdef HAVE_GNUTLS
1314                                 arg_trust = strdup(optarg);
1315                                 if (!arg_trust)
1316                                         return log_oom();
1317 #else
1318                                 log_error("Option --trust is not available.");
1319                                 return -EINVAL;
1320 #endif
1321                         }
1322
1323                         break;
1324
1325                 case 'o':
1326                         if (arg_output) {
1327                                 log_error("cannot use --output/-o more than once");
1328                                 return -EINVAL;
1329                         }
1330
1331                         arg_output = optarg;
1332                         break;
1333
1334                 case ARG_SPLIT_MODE:
1335                         arg_split_mode = journal_write_split_mode_from_string(optarg);
1336                         if (arg_split_mode == _JOURNAL_WRITE_SPLIT_INVALID) {
1337                                 log_error("Invalid split mode: %s", optarg);
1338                                 return -EINVAL;
1339                         }
1340                         break;
1341
1342                 case ARG_COMPRESS:
1343                         if (optarg) {
1344                                 r = parse_boolean(optarg);
1345                                 if (r < 0) {
1346                                         log_error("Failed to parse --compress= parameter.");
1347                                         return -EINVAL;
1348                                 }
1349
1350                                 arg_compress = !!r;
1351                         } else
1352                                 arg_compress = true;
1353
1354                         break;
1355
1356                 case ARG_SEAL:
1357                         if (optarg) {
1358                                 r = parse_boolean(optarg);
1359                                 if (r < 0) {
1360                                         log_error("Failed to parse --seal= parameter.");
1361                                         return -EINVAL;
1362                                 }
1363
1364                                 arg_seal = !!r;
1365                         } else
1366                                 arg_seal = true;
1367
1368                         break;
1369
1370                 case ARG_GNUTLS_LOG: {
1371 #ifdef HAVE_GNUTLS
1372                         const char *word, *state;
1373                         size_t size;
1374
1375                         FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
1376                                 char *cat;
1377
1378                                 cat = strndup(word, size);
1379                                 if (!cat)
1380                                         return log_oom();
1381
1382                                 if (strv_consume(&arg_gnutls_log, cat) < 0)
1383                                         return log_oom();
1384                         }
1385                         break;
1386 #else
1387                         log_error("Option --gnutls-log is not available.");
1388                         return -EINVAL;
1389 #endif
1390                 }
1391
1392                 case '?':
1393                         return -EINVAL;
1394
1395                 default:
1396                         assert_not_reached("Unknown option code.");
1397                 }
1398
1399         if (optind < argc)
1400                 arg_files = argv + optind;
1401
1402         type_a = arg_getter || !strv_isempty(arg_files);
1403         type_b = arg_url
1404                 || arg_listen_raw
1405                 || arg_listen_http || arg_listen_https
1406                 || sd_listen_fds(false) > 0;
1407         if (type_a && type_b) {
1408                 log_error("Cannot use file input or --getter with "
1409                           "--arg-listen-... or socket activation.");
1410                 return -EINVAL;
1411         }
1412         if (type_a) {
1413                 if (!arg_output) {
1414                         log_error("Option --output must be specified with file input or --getter.");
1415                         return -EINVAL;
1416                 }
1417
1418                 arg_split_mode = JOURNAL_WRITE_SPLIT_NONE;
1419         }
1420
1421         if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE
1422             && arg_output && is_dir(arg_output, true) > 0) {
1423                 log_error("For SplitMode=none, output must be a file.");
1424                 return -EINVAL;
1425         }
1426
1427         if (arg_split_mode == JOURNAL_WRITE_SPLIT_HOST
1428             && arg_output && is_dir(arg_output, true) <= 0) {
1429                 log_error("For SplitMode=host, output must be a directory.");
1430                 return -EINVAL;
1431         }
1432
1433         log_debug("Full config: SplitMode=%s Key=%s Cert=%s Trust=%s",
1434                   journal_write_split_mode_to_string(arg_split_mode),
1435                   strna(arg_key),
1436                   strna(arg_cert),
1437                   strna(arg_trust));
1438
1439         return 1 /* work to do */;
1440 }
1441
1442 static int load_certificates(char **key, char **cert, char **trust) {
1443         int r;
1444
1445         r = read_full_file(arg_key ?: PRIV_KEY_FILE, key, NULL);
1446         if (r < 0) {
1447                 log_error("Failed to read key from file '%s': %s",
1448                           arg_key ?: PRIV_KEY_FILE, strerror(-r));
1449                 return r;
1450         }
1451
1452         r = read_full_file(arg_cert ?: CERT_FILE, cert, NULL);
1453         if (r < 0) {
1454                 log_error("Failed to read certificate from file '%s': %s",
1455                           arg_cert ?: CERT_FILE, strerror(-r));
1456                 return r;
1457         }
1458
1459         if (arg_trust_all)
1460                 log_info("Certificate checking disabled.");
1461         else {
1462                 r = read_full_file(arg_trust ?: TRUST_FILE, trust, NULL);
1463                 if (r < 0) {
1464                         log_error("Failed to read CA certificate file '%s': %s",
1465                                   arg_trust ?: TRUST_FILE, strerror(-r));
1466                         return r;
1467                 }
1468         }
1469
1470         return 0;
1471 }
1472
1473 static int setup_gnutls_logger(char **categories) {
1474         if (!arg_listen_http && !arg_listen_https)
1475                 return 0;
1476
1477 #ifdef HAVE_GNUTLS
1478         {
1479                 char **cat;
1480                 int r;
1481
1482                 gnutls_global_set_log_function(log_func_gnutls);
1483
1484                 if (categories)
1485                         STRV_FOREACH(cat, categories) {
1486                                 r = log_enable_gnutls_category(*cat);
1487                                 if (r < 0)
1488                                         return r;
1489                         }
1490                 else
1491                         log_reset_gnutls_level();
1492         }
1493 #endif
1494
1495         return 0;
1496 }
1497
1498 int main(int argc, char **argv) {
1499         RemoteServer s = {};
1500         int r;
1501         _cleanup_free_ char *key = NULL, *cert = NULL, *trust = NULL;
1502
1503         log_show_color(true);
1504         log_parse_environment();
1505
1506         r = parse_config();
1507         if (r < 0)
1508                 return EXIT_FAILURE;
1509
1510         r = parse_argv(argc, argv);
1511         if (r <= 0)
1512                 return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
1513
1514         r = setup_gnutls_logger(arg_gnutls_log);
1515         if (r < 0)
1516                 return EXIT_FAILURE;
1517
1518         if (arg_listen_https || https_socket >= 0)
1519                 if (load_certificates(&key, &cert, &trust) < 0)
1520                         return EXIT_FAILURE;
1521
1522         if (remoteserver_init(&s, key, cert, trust) < 0)
1523                 return EXIT_FAILURE;
1524
1525         sd_event_set_watchdog(s.events, true);
1526
1527         log_debug("%s running as pid "PID_FMT,
1528                   program_invocation_short_name, getpid());
1529         sd_notify(false,
1530                   "READY=1\n"
1531                   "STATUS=Processing requests...");
1532
1533         while (s.active) {
1534                 r = sd_event_get_state(s.events);
1535                 if (r < 0)
1536                         break;
1537                 if (r == SD_EVENT_FINISHED)
1538                         break;
1539
1540                 r = sd_event_run(s.events, -1);
1541                 if (r < 0) {
1542                         log_error("Failed to run event loop: %s", strerror(-r));
1543                         break;
1544                 }
1545         }
1546
1547         sd_notifyf(false,
1548                    "STOPPING=1\n"
1549                    "STATUS=Shutting down after writing %" PRIu64 " entries...", s.event_count);
1550         log_info("Finishing after writing %" PRIu64 " entries", s.event_count);
1551
1552         server_destroy(&s);
1553
1554         free(arg_key);
1555         free(arg_cert);
1556         free(arg_trust);
1557
1558         return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
1559 }