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