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