kore.c (20766B)
1 /*
2 * Copyright (c) 2013-2022 Joris Vink <joris@coders.se>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <sys/un.h>
20
21 #include <sys/socket.h>
22 #include <sys/resource.h>
23
24 #include <libgen.h>
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <netdb.h>
28 #include <signal.h>
29
30 #include "kore.h"
31 #include "hooks.h"
32
33 #if !defined(KORE_NO_HTTP)
34 #include "http.h"
35 #endif
36
37 #if defined(KORE_USE_CURL)
38 #include "curl.h"
39 #endif
40
41 #if defined(KORE_USE_PGSQL)
42 #include "pgsql.h"
43 #endif
44
45 #if defined(KORE_USE_PYTHON)
46 #include "python_api.h"
47 #endif
48
49 #if defined(KORE_USE_LUA)
50 #include "lua_api.h"
51 #endif
52
53 #if defined(KORE_USE_ACME)
54 #include "acme.h"
55 #endif
56
57 volatile sig_atomic_t sig_recv;
58 struct kore_server_list kore_servers;
59 u_int8_t nlisteners;
60 int kore_argc = 0;
61 pid_t kore_pid = -1;
62 u_int16_t cpu_count = 1;
63 int kore_quiet = 0;
64 int skip_runas = 0;
65 int skip_chroot = 0;
66 u_int8_t worker_count = 0;
67 char **kore_argv = NULL;
68 int kore_mem_guard = 0;
69 int kore_foreground = 1;
70 char *kore_progname = NULL;
71 u_int32_t kore_socket_backlog = 5000;
72 int kore_quit = KORE_QUIT_NONE;
73 char *kore_pidfile = KORE_PIDFILE_DEFAULT;
74
75 struct kore_privsep worker_privsep;
76
77 extern char **environ;
78 extern char *__progname;
79 static size_t proctitle_maxlen = 0;
80
81 static void usage(void);
82 static void version(void);
83
84 static void kore_write_kore_pid(void);
85 static void kore_proctitle_setup(void);
86 static void kore_server_shutdown(void);
87 static void kore_server_start(int, char *[]);
88 static void kore_call_parent_configure(int, char **);
89
90 #if !defined(KORE_SINGLE_BINARY)
91 static const char *rarg0 = NULL;
92 #endif
93
94 static const char *parent_config_hook = KORE_CONFIG_HOOK;
95 static const char *parent_teardown_hook = KORE_TEARDOWN_HOOK;
96
97 #if defined(KORE_SINGLE_BINARY)
98 static const char *parent_daemonized_hook = KORE_DAEMONIZED_HOOK;
99 #endif
100
101 static void
102 usage(void)
103 {
104 if (kore_runtime_count() > 0) {
105 printf("Usage: %s [options] [app | script]\n", __progname);
106 } else {
107 printf("Usage: %s [options]\n", __progname);
108 }
109
110 printf("\n");
111 printf("Command-line options:\n");
112 #if !defined(KORE_SINGLE_BINARY)
113 printf("\t-c\tThe configuration file to load when starting.\n");
114 #endif
115 printf("\t-f\tDo not daemonize, everything runs in the foreground.\n");
116 printf("\t-h\tThis help text.\n");
117 printf("\t-n\tDo not do the chroot privsep step.\n");
118 printf("\t-q\tQuiet mode, only logs errors.\n");
119 printf("\t-r\tDo not do the privsep user swapping step.\n");
120 printf("\t-v\tDisplay %s build information.\n", __progname);
121
122 printf("\n");
123 printf("Environment options:\n");
124 printf(" env KORE_MEM_GUARD=1\n");
125 printf(" Enables memory pool guards and other protections.\n");
126 printf("\n");
127 printf(" Enabling this will include guard pages for each\n");
128 printf(" pool entry allocations and mark pool entries as\n");
129 printf(" PROT_NONE when unused.\n");
130 printf("\n");
131 printf(" This catches bugs and prevents memory vulnerabilities\n");
132 printf(" but with performance and memory pressure costs.\n");
133
134 printf("\n");
135
136 exit(1);
137 }
138
139 static void
140 version(void)
141 {
142 printf("%s ", kore_version);
143 #if defined(KORE_NO_HTTP)
144 printf("no-http ");
145 #endif
146 #if defined(KORE_USE_CURL)
147 printf("curl-%s ", LIBCURL_VERSION);
148 #endif
149 #if defined(KORE_USE_PGSQL)
150 printf("pgsql ");
151 #endif
152 #if defined(KORE_USE_TASKS)
153 printf("tasks ");
154 #endif
155 #if defined(KORE_USE_PYTHON)
156 printf("python-%s ", PY_VERSION);
157 #endif
158 #if defined(KORE_USE_LUA)
159 printf("lua-%s.%s.%s ",
160 LUA_VERSION_MAJOR, LUA_VERSION_MINOR, LUA_VERSION_RELEASE);
161 #endif
162 #if defined(KORE_USE_ACME)
163 printf("acme ");
164 #endif
165 #if defined(KORE_DEBUG)
166 printf("debug ");
167 #endif
168 if (!kore_tls_supported())
169 printf("notls ");
170
171 printf("\n");
172 exit(0);
173 }
174
175 int
176 main(int argc, char *argv[])
177 {
178 #if !defined(KORE_SINGLE_BINARY)
179 struct stat st;
180 #endif
181 struct kore_runtime_call *rcall;
182
183 kore_argc = argc;
184 kore_argv = argv;
185
186 #if !defined(KORE_SINGLE_BINARY)
187 kore_default_getopt(argc, argv);
188 #endif
189
190 kore_mem_init();
191 kore_msg_init();
192 kore_log_init();
193 kore_tls_init();
194
195 kore_progname = kore_strdup(argv[0]);
196 kore_proctitle_setup();
197
198 #if !defined(KORE_SINGLE_BINARY)
199 argc -= optind;
200 argv += optind;
201 #endif
202
203 #if !defined(KORE_SINGLE_BINARY)
204 if (kore_runtime_count() > 0) {
205 if (argc > 0) {
206 rarg0 = argv[0];
207 argc--;
208 argv++;
209 }
210
211 if (rarg0) {
212 if (lstat(rarg0, &st) == -1) {
213 if (errno == ENOENT)
214 rarg0 = NULL;
215 else
216 fatal("stat(%s): %s", rarg0, errno_s);
217 }
218 }
219 }
220 #endif
221
222 kore_pid = getpid();
223 nlisteners = 0;
224 LIST_INIT(&kore_servers);
225
226 kore_platform_init();
227 #if !defined(KORE_NO_HTTP)
228 http_parent_init();
229 #if defined(KORE_USE_CURL)
230 kore_curl_sysinit();
231 #endif
232 #if defined(KORE_USE_PGSQL)
233 kore_pgsql_sys_init();
234 #endif
235 kore_auth_init();
236 kore_validator_init();
237 kore_filemap_init();
238 #endif
239 #if defined(KORE_USE_ACME)
240 kore_acme_init();
241 #endif
242 kore_domain_init();
243 kore_module_init();
244
245 #if !defined(KORE_SINGLE_BINARY)
246 if (kore_runtime_count() == 0 && config_file == NULL)
247 usage();
248 #endif
249 kore_module_load(NULL, NULL, KORE_MODULE_NATIVE);
250
251 #if defined(KORE_USE_PYTHON)
252 kore_python_init();
253 #endif
254
255 #if defined(KORE_USE_LUA)
256 kore_lua_init();
257 #endif
258
259 #if !defined(KORE_SINGLE_BINARY)
260 if (kore_runtime_count() > 0 && rarg0 != NULL)
261 kore_runtime_resolve(rarg0, &st);
262 #endif
263
264 #if defined(KORE_SINGLE_BINARY)
265 kore_call_parent_configure(argc, argv);
266 #else
267 if (kore_runtime_count() > 0 && rarg0 != NULL)
268 kore_call_parent_configure(argc, argv);
269 #endif
270
271 kore_parse_config();
272
273 #if !defined(KORE_SINGLE_BINARY)
274 free(config_file);
275 #endif
276
277 #if !defined(KORE_NO_HTTP)
278 if (http_body_disk_offload > 0) {
279 if (mkdir(http_body_disk_path, 0700) == -1 && errno != EEXIST) {
280 printf("can't create http_body_disk_path '%s': %s\n",
281 http_body_disk_path, errno_s);
282 return (KORE_RESULT_ERROR);
283 }
284 }
285 #endif
286
287 kore_signal_setup();
288 kore_server_start(argc, argv);
289 kore_server_shutdown();
290
291 rcall = kore_runtime_getcall(parent_teardown_hook);
292 if (rcall != NULL) {
293 kore_runtime_execute(rcall);
294 kore_free(rcall);
295 }
296
297 if (unlink(kore_pidfile) == -1 && errno != ENOENT)
298 kore_log(LOG_NOTICE, "failed to remove pidfile (%s)", errno_s);
299
300 kore_server_cleanup();
301
302 if (!kore_quiet)
303 kore_log(LOG_INFO, "goodbye");
304
305 #if defined(KORE_USE_PYTHON)
306 kore_python_cleanup();
307 #endif
308
309 #if defined(KORE_USE_LUA)
310 kore_lua_cleanup();
311 #endif
312
313 kore_mem_cleanup();
314
315 return (kore_quit);
316 }
317
318 void
319 kore_default_getopt(int argc, char **argv)
320 {
321 int ch;
322
323 #if !defined(KORE_SINGLE_BINARY)
324 while ((ch = getopt(argc, argv, "c:dfhnqrv")) != -1) {
325 #else
326 while ((ch = getopt(argc, argv, "dfhnqrv")) != -1) {
327 #endif
328 switch (ch) {
329 #if !defined(KORE_SINGLE_BINARY)
330 case 'c':
331 free(config_file);
332 if ((config_file = strdup(optarg)) == NULL)
333 fatal("strdup");
334 break;
335 #endif
336 case 'd':
337 kore_foreground = 0;
338 break;
339 case 'f':
340 printf("note: -f is the default now, "
341 "use -d to daemonize\n");
342 break;
343 case 'h':
344 usage();
345 break;
346 case 'n':
347 skip_chroot = 1;
348 break;
349 case 'q':
350 kore_quiet = 1;
351 break;
352 case 'r':
353 skip_runas = 1;
354 break;
355 case 'v':
356 version();
357 break;
358 default:
359 usage();
360 }
361 }
362 }
363
364 int
365 kore_server_bind(struct kore_server *srv, const char *ip, const char *port,
366 const char *ccb)
367 {
368 int r;
369 struct listener *l;
370 struct addrinfo hints, *results;
371
372 memset(&hints, 0, sizeof(hints));
373 hints.ai_family = AF_UNSPEC;
374 hints.ai_socktype = SOCK_STREAM;
375 hints.ai_protocol = IPPROTO_TCP;
376 hints.ai_flags = 0;
377
378 r = getaddrinfo(ip, port, &hints, &results);
379 if (r != 0)
380 fatal("getaddrinfo(%s): %s", ip, gai_strerror(r));
381
382 l = kore_listener_create(srv);
383 l->host = kore_strdup(ip);
384 l->port = kore_strdup(port);
385
386 if (!kore_listener_init(l, results->ai_family, ccb)) {
387 freeaddrinfo(results);
388 return (KORE_RESULT_ERROR);
389 }
390
391 if (bind(l->fd, results->ai_addr, results->ai_addrlen) == -1) {
392 kore_listener_free(l);
393 freeaddrinfo(results);
394 kore_log(LOG_ERR, "bind(): %s", errno_s);
395 return (KORE_RESULT_ERROR);
396 }
397
398 freeaddrinfo(results);
399
400 if (listen(l->fd, kore_socket_backlog) == -1) {
401 kore_listener_free(l);
402 kore_log(LOG_ERR, "listen(): %s", errno_s);
403 return (KORE_RESULT_ERROR);
404 }
405
406 return (KORE_RESULT_OK);
407 }
408
409 int
410 kore_server_bind_unix(struct kore_server *srv, const char *path,
411 const char *ccb)
412 {
413 struct listener *l;
414 int len;
415 struct sockaddr_un sun;
416 socklen_t socklen;
417
418 memset(&sun, 0, sizeof(sun));
419 sun.sun_family = AF_UNIX;
420
421 len = snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", path);
422 if (len == -1 || (size_t)len >= sizeof(sun.sun_path)) {
423 kore_log(LOG_ERR, "unix socket path '%s' too long", path);
424 return (KORE_RESULT_ERROR);
425 }
426
427 #if defined(__linux__)
428 if (sun.sun_path[0] == '@')
429 sun.sun_path[0] = '\0';
430 socklen = sizeof(sun.sun_family) + len;
431 #else
432 socklen = sizeof(sun);
433 #endif
434
435 l = kore_listener_create(srv);
436 l->host = kore_strdup(path);
437
438 if (!kore_listener_init(l, AF_UNIX, ccb))
439 return (KORE_RESULT_ERROR);
440
441 if (sun.sun_path[0] != '\0') {
442 if (unlink(sun.sun_path) == -1 && errno != ENOENT) {
443 kore_log(LOG_ERR, "unlink: %s: %s",
444 sun.sun_path, errno_s);
445 kore_listener_free(l);
446 return (KORE_RESULT_ERROR);
447 }
448 }
449
450 if (bind(l->fd, (struct sockaddr *)&sun, socklen) == -1) {
451 kore_log(LOG_ERR, "bind: %s", errno_s);
452 kore_listener_free(l);
453 return (KORE_RESULT_ERROR);
454 }
455
456 if (listen(l->fd, kore_socket_backlog) == -1) {
457 kore_log(LOG_ERR, "listen(): %s", errno_s);
458 kore_listener_free(l);
459 return (KORE_RESULT_ERROR);
460 }
461
462 return (KORE_RESULT_OK);
463 }
464
465 struct kore_server *
466 kore_server_create(const char *name)
467 {
468 struct kore_server *srv;
469
470 srv = kore_calloc(1, sizeof(struct kore_server));
471 srv->name = kore_strdup(name);
472
473 if (kore_tls_supported())
474 srv->tls = 1;
475 else
476 srv->tls = 0;
477
478 TAILQ_INIT(&srv->domains);
479 LIST_INIT(&srv->listeners);
480
481 LIST_INSERT_HEAD(&kore_servers, srv, list);
482
483 return (srv);
484 }
485
486 void
487 kore_server_finalize(struct kore_server *srv)
488 {
489 struct listener *l;
490 const char *proto;
491
492 if (kore_quiet)
493 return;
494
495 LIST_FOREACH(l, &srv->listeners, list) {
496 if (srv->tls)
497 proto = "https";
498 else
499 proto = "http";
500
501 if (l->family == AF_UNIX) {
502 kore_log(LOG_INFO, "%s serving %s on %s",
503 srv->name, proto, l->host);
504 } else {
505 kore_log(LOG_INFO, "%s serving %s on %s:%s",
506 srv->name, proto, l->host, l->port);
507 }
508 }
509 }
510
511 struct listener *
512 kore_listener_create(struct kore_server *server)
513 {
514 struct listener *l;
515
516 l = kore_calloc(1, sizeof(struct listener));
517
518 nlisteners++;
519 LIST_INSERT_HEAD(&server->listeners, l, list);
520
521 l->server = server;
522
523 l->fd = -1;
524 l->evt.type = KORE_TYPE_LISTENER;
525 l->evt.handle = kore_listener_accept;
526
527 return (l);
528 }
529
530 struct kore_server *
531 kore_server_lookup(const char *name)
532 {
533 struct kore_server *srv;
534
535 LIST_FOREACH(srv, &kore_servers, list) {
536 if (!strcmp(srv->name, name))
537 return (srv);
538 }
539
540 return (NULL);
541 }
542
543 int
544 kore_listener_init(struct listener *l, int family, const char *ccb)
545 {
546 switch (family) {
547 case AF_INET:
548 case AF_INET6:
549 case AF_UNIX:
550 break;
551 default:
552 fatal("unknown address family %d", family);
553 }
554
555 l->family = family;
556
557 if ((l->fd = socket(family, SOCK_STREAM, 0)) == -1) {
558 kore_listener_free(l);
559 kore_log(LOG_ERR, "socket(): %s", errno_s);
560 return (KORE_RESULT_ERROR);
561 }
562
563 if (fcntl(l->fd, F_SETFD, FD_CLOEXEC) == -1) {
564 kore_listener_free(l);
565 kore_log(LOG_ERR, "fcntl(): %s", errno_s);
566 return (KORE_RESULT_ERROR);
567 }
568
569 if (!kore_connection_nonblock(l->fd, family != AF_UNIX)) {
570 kore_listener_free(l);
571 kore_log(LOG_ERR, "kore_connection_nonblock(): %s", errno_s);
572 return (KORE_RESULT_ERROR);
573 }
574
575 if (!kore_sockopt(l->fd, SOL_SOCKET, SO_REUSEADDR)) {
576 kore_listener_free(l);
577 return (KORE_RESULT_ERROR);
578 }
579
580 if (ccb != NULL) {
581 if ((l->connect = kore_runtime_getcall(ccb)) == NULL) {
582 kore_log(LOG_ERR, "no such callback: '%s'", ccb);
583 kore_listener_free(l);
584 return (KORE_RESULT_ERROR);
585 }
586 } else {
587 l->connect = NULL;
588 }
589
590 return (KORE_RESULT_OK);
591 }
592
593 void
594 kore_server_free(struct kore_server *srv)
595 {
596 struct listener *l;
597 struct kore_domain *dom;
598
599 LIST_REMOVE(srv, list);
600
601 while ((dom = TAILQ_FIRST(&srv->domains)) != NULL)
602 kore_domain_free(dom);
603
604 while ((l = LIST_FIRST(&srv->listeners)) != NULL)
605 kore_listener_free(l);
606
607 kore_free(srv->name);
608 kore_free(srv);
609 }
610
611 void
612 kore_listener_free(struct listener *l)
613 {
614 int rm;
615
616 LIST_REMOVE(l, list);
617
618 if (l->fd != -1)
619 close(l->fd);
620
621 rm = 0;
622
623 #if defined(__linux__)
624 if (worker == NULL && l->family == AF_UNIX && l->host[0] != '@')
625 rm++;
626 #else
627 if (worker == NULL && l->family == AF_UNIX)
628 rm++;
629 #endif
630 if (rm) {
631 if (unlink(l->host) == -1) {
632 kore_log(LOG_NOTICE,
633 "failed to remove unix socket %s (%s)", l->host,
634 errno_s);
635 }
636 }
637
638 kore_free(l->host);
639 kore_free(l->port);
640
641 kore_free(l);
642 }
643
644 void
645 kore_listener_accept(void *arg, int error)
646 {
647 struct connection *c;
648 struct listener *l = arg;
649 u_int32_t accepted;
650
651 if (error)
652 fatal("error on listening socket");
653
654 if (!(l->evt.flags & KORE_EVENT_READ))
655 return;
656
657 accepted = 0;
658
659 while (worker_active_connections < worker_max_connections) {
660 if (worker_accept_threshold != 0 &&
661 accepted >= worker_accept_threshold) {
662 kore_worker_make_busy();
663 break;
664 }
665
666 if (!kore_connection_accept(l, &c))
667 break;
668
669 if (c == NULL)
670 break;
671
672 accepted++;
673 kore_platform_event_all(c->fd, c);
674 }
675 }
676
677 int
678 kore_sockopt(int fd, int what, int opt)
679 {
680 int on;
681
682 on = 1;
683 if (setsockopt(fd, what, opt, (const char *)&on, sizeof(on)) == -1) {
684 kore_log(LOG_ERR, "setsockopt(): %s", errno_s);
685 return (KORE_RESULT_ERROR);
686 }
687
688 return (KORE_RESULT_OK);
689 }
690
691 void
692 kore_signal_setup(void)
693 {
694 kore_signal_trap(SIGHUP);
695 kore_signal_trap(SIGQUIT);
696 kore_signal_trap(SIGTERM);
697 kore_signal_trap(SIGUSR1);
698 kore_signal_trap(SIGCHLD);
699
700 if (kore_foreground)
701 kore_signal_trap(SIGINT);
702 else
703 (void)signal(SIGINT, SIG_IGN);
704
705 (void)signal(SIGPIPE, SIG_IGN);
706 }
707
708 void
709 kore_signal_trap(int sig)
710 {
711 struct sigaction sa;
712
713 sig_recv = 0;
714 memset(&sa, 0, sizeof(sa));
715 sa.sa_handler = kore_signal;
716
717 if (sigfillset(&sa.sa_mask) == -1)
718 fatal("sigfillset: %s", errno_s);
719
720 if (sigaction(sig, &sa, NULL) == -1)
721 fatal("sigaction: %s", errno_s);
722 }
723
724 void
725 kore_server_closeall(void)
726 {
727 struct listener *l;
728 struct kore_server *srv;
729
730 LIST_FOREACH(srv, &kore_servers, list) {
731 LIST_FOREACH(l, &srv->listeners, list)
732 l->fd = -1;
733 }
734 }
735
736 void
737 kore_server_cleanup(void)
738 {
739 struct kore_server *srv;
740
741 while ((srv = LIST_FIRST(&kore_servers)) != NULL)
742 kore_server_free(srv);
743 }
744
745 void
746 kore_signal(int sig)
747 {
748 sig_recv = sig;
749 }
750
751 void
752 kore_shutdown(void)
753 {
754 if (worker != NULL) {
755 kore_msg_send(KORE_MSG_PARENT, KORE_MSG_SHUTDOWN, NULL, 0);
756 return;
757 }
758
759 fatal("kore_shutdown: called from parent");
760 }
761
762 void
763 kore_proctitle(const char *title)
764 {
765 int len;
766
767 kore_argv[1] = NULL;
768
769 len = snprintf(kore_argv[0], proctitle_maxlen, "%s %s",
770 basename(kore_progname), title);
771 if (len == -1 || (size_t)len >= proctitle_maxlen)
772 fatal("proctitle '%s' too large", title);
773
774 memset(kore_argv[0] + len, 0, proctitle_maxlen - len);
775 }
776
777 void
778 kore_hooks_set(const char *config, const char *teardown, const char *daemonized)
779 {
780 parent_config_hook = config;
781 parent_teardown_hook = teardown;
782
783 #if defined(KORE_SINGLE_BINARY)
784 parent_daemonized_hook = daemonized;
785 #endif
786 }
787
788 static void
789 kore_proctitle_setup(void)
790 {
791 int i;
792 char *p;
793
794 proctitle_maxlen = 0;
795
796 for (i = 0; environ[i] != NULL; i++) {
797 if ((p = strdup(environ[i])) == NULL)
798 fatal("strdup");
799 proctitle_maxlen += strlen(environ[i]) + 1;
800 environ[i] = p;
801 }
802
803 for (i = 0; kore_argv[i] != NULL; i++)
804 proctitle_maxlen += strlen(kore_argv[i]) + 1;
805 }
806
807 static void
808 kore_server_start(int argc, char *argv[])
809 {
810 u_int32_t tmp;
811 struct kore_server *srv;
812 u_int64_t netwait;
813 int last_sig;
814 #if !defined(KORE_NO_HTTP)
815 int alog;
816 struct kore_domain *dom;
817 #endif
818 #if defined(KORE_SINGLE_BINARY)
819 struct kore_runtime_call *rcall;
820 #endif
821
822 if (!kore_quiet) {
823 kore_log(LOG_INFO, "%s %s starting, built=%s",
824 __progname, kore_version, kore_build_date);
825 kore_log(LOG_INFO, "memory pool protections: %s",
826 kore_mem_guard ? "enabled" : "disabled");
827 kore_log(LOG_INFO, "built-ins: "
828 #if defined(__linux__)
829 "seccomp "
830 #endif
831 #if defined(KORE_USE_PGSQL)
832 "pgsql "
833 #endif
834 #if defined(KORE_USE_TASKS)
835 "tasks "
836 #endif
837 #if defined(KORE_USE_JSONRPC)
838 "jsonrpc "
839 #endif
840 #if defined(KORE_USE_PYTHON)
841 "python "
842 #endif
843 #if defined(KORE_USE_ACME)
844 "acme "
845 #endif
846 #if defined(KORE_USE_CURL)
847 "curl "
848 #endif
849 #if defined(KORE_USE_LUA)
850 "lua "
851 #endif
852 );
853 }
854
855 kore_tls_log_version();
856
857 if (kore_foreground == 0) {
858 if (daemon(1, 0) == -1)
859 fatal("cannot daemon(): %s", errno_s);
860 #if defined(KORE_SINGLE_BINARY)
861 rcall = kore_runtime_getcall(parent_daemonized_hook);
862 if (rcall != NULL) {
863 kore_runtime_execute(rcall);
864 kore_free(rcall);
865 }
866 #endif
867 }
868
869 kore_pid = getpid();
870 kore_write_kore_pid();
871
872 #if !defined(KORE_SINGLE_BINARY)
873 if (kore_runtime_count() == 0 || rarg0 == NULL)
874 kore_call_parent_configure(argc, argv);
875 #endif
876
877 #if defined(KORE_USE_PYTHON)
878 kore_python_routes_resolve();
879 #endif
880
881 /* Check if keymgr will be active. */
882 if (kore_tls_supported()) {
883 LIST_FOREACH(srv, &kore_servers, list) {
884 if (srv->tls) {
885 kore_keymgr_active = 1;
886 break;
887 }
888 }
889 } else {
890 kore_keymgr_active = 0;
891 }
892
893 kore_platform_proctitle("[parent]");
894
895 if (!kore_worker_init()) {
896 kore_log(LOG_ERR, "last worker log lines:");
897 kore_log(LOG_ERR, "=====================================");
898 net_init();
899 kore_connection_init();
900 kore_platform_event_init();
901 kore_msg_parent_init();
902 kore_platform_event_wait(10);
903 kore_worker_dispatch_signal(SIGQUIT);
904 kore_log(LOG_ERR, "=====================================");
905 return;
906 }
907
908 /* Set worker_max_connections for kore_connection_init(). */
909 tmp = worker_max_connections;
910 worker_max_connections = worker_count;
911
912 net_init();
913 kore_connection_init();
914 kore_platform_event_init();
915 kore_msg_parent_init();
916
917 worker_max_connections = tmp;
918
919 kore_timer_init();
920
921 #if !defined(KORE_NO_HTTP)
922 alog = 0;
923
924 LIST_FOREACH(srv, &kore_servers, list) {
925 TAILQ_FOREACH(dom, &srv->domains, list) {
926 if (dom->accesslog != -1)
927 alog = 1;
928 }
929 }
930
931 if (alog) {
932 kore_timer_add(kore_accesslog_run, 100, NULL, 0);
933 kore_log(LOG_INFO, "accesslog vacuum is enabled");
934 }
935 #endif
936
937 #if defined(KORE_USE_PYTHON)
938 kore_msg_unregister(KORE_PYTHON_SEND_OBJ);
939 #endif
940
941 while (kore_quit == KORE_QUIT_NONE) {
942 last_sig = sig_recv;
943
944 if (last_sig != 0) {
945 switch (last_sig) {
946 case SIGHUP:
947 kore_worker_dispatch_signal(last_sig);
948 kore_module_reload(0);
949 break;
950 case SIGINT:
951 case SIGQUIT:
952 case SIGTERM:
953 kore_quit = KORE_QUIT_NORMAL;
954 kore_worker_dispatch_signal(last_sig);
955 continue;
956 case SIGUSR1:
957 kore_worker_dispatch_signal(last_sig);
958 break;
959 case SIGCHLD:
960 kore_worker_reap();
961 break;
962 default:
963 break;
964 }
965
966 if (sig_recv == last_sig)
967 sig_recv = 0;
968 else
969 continue;
970 }
971
972 netwait = kore_timer_next_run(kore_time_ms());
973 kore_platform_event_wait(netwait);
974 kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT);
975 kore_timer_run(kore_time_ms());
976 kore_worker_reap();
977 }
978
979 kore_worker_dispatch_signal(SIGQUIT);
980 }
981
982 static void
983 kore_server_shutdown(void)
984 {
985 if (!kore_quiet)
986 kore_log(LOG_INFO, "server shutting down");
987
988 kore_worker_shutdown();
989
990 #if !defined(KORE_NO_HTTP)
991 kore_accesslog_gather(NULL, kore_time_ms(), 1);
992 #endif
993
994 kore_platform_event_cleanup();
995 kore_connection_cleanup();
996 kore_domain_cleanup();
997 kore_tls_cleanup();
998 net_cleanup();
999 }
1000
1001 static void
1002 kore_write_kore_pid(void)
1003 {
1004 FILE *fp;
1005
1006 if ((fp = fopen(kore_pidfile, "w+")) == NULL) {
1007 printf("warning: couldn't write pid to %s (%s)\n",
1008 kore_pidfile, errno_s);
1009 } else {
1010 fprintf(fp, "%d\n", kore_pid);
1011 fclose(fp);
1012 }
1013 }
1014
1015 static void
1016 kore_call_parent_configure(int argc, char **argv)
1017 {
1018 struct kore_runtime_call *rcall;
1019
1020 rcall = kore_runtime_getcall(parent_config_hook);
1021 if (rcall != NULL) {
1022 kore_runtime_configure(rcall, argc, argv);
1023 kore_free(rcall);
1024 }
1025 }