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