]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Add '--daemon' argument to daemonize fort, fixes #25
authorpcarana <pc.moreno2099@gmail.com>
Fri, 30 Oct 2020 20:18:13 +0000 (14:18 -0600)
committerpcarana <pc.moreno2099@gmail.com>
Fri, 30 Oct 2020 20:18:13 +0000 (14:18 -0600)
+When the flag is enabled, any value set at '--log.output' and '--validation-log.output' is overwritten with 'syslog' (all enabled logs will be sent to syslog).
+Update the docs to include the new argument.

docs/usage.md
examples/config.json
man/fort.8
src/Makefile.am
src/config.c
src/daemon.c [new file with mode: 0644]
src/daemon.h [new file with mode: 0644]
src/log.c

index cfbaf0dc4118a9253c37900d0c91ee157e0c5069..e0b37f44fba4d43f4aea44ff1d44232a3b6afca4 100644 (file)
@@ -17,58 +17,59 @@ description: Guide to use arguments of FORT Validator.
        5. [`--tal`](#--tal)
        6. [`--local-repository`](#--local-repository)
        7. [`--work-offline`](#--work-offline)
-       8. [`--shuffle-uris`](#--shuffle-uris)
-       9. [`--maximum-certificate-depth`](#--maximum-certificate-depth)
-       10. [`--mode`](#--mode)
-       11. [`--server.address`](#--serveraddress)
-       12. [`--server.port`](#--serverport)
-       13. [`--server.backlog`](#--serverbacklog)
-       14. [`--server.interval.validation`](#--serverintervalvalidation)
-       15. [`--server.interval.refresh`](#--serverintervalrefresh)
-       16. [`--server.interval.retry`](#--serverintervalretry)
-       17. [`--server.interval.expire`](#--serverintervalexpire)
-       18. [`--slurm`](#--slurm)
-       19. [`--log.enabled`](#--logenabled)
-       20. [`--log.level`](#--loglevel)
-       21. [`--log.output`](#--logoutput)
-       22. [`--log.color-output`](#--logcolor-output)
-       23. [`--log.file-name-format`](#--logfile-name-format)
-       24. [`--log.facility`](#--logfacility)
-       25. [`--log.tag`](#--logtag)
-       26. [`--validation-log.enabled`](#--validation-logenabled)
-       27. [`--validation-log.level`](#--validation-loglevel)
-       28. [`--validation-log.output`](#--validation-logoutput)
-       29. [`--validation-log.color-output`](#--validation-logcolor-output)
-       30. [`--validation-log.file-name-format`](#--validation-logfile-name-format)
-       31. [`--validation-log.facility`](#--validation-logfacility)
-       32. [`--validation-log.tag`](#--validation-logtag)
-       33. [`--http.enabled`](#--httpenabled)
-       34. [`--http.priority`](#--httppriority)
-       35. [`--http.retry.count`](#--httpretrycount)
-       36. [`--http.retry.interval`](#--httpretryinterval)
-       37. [`--http.user-agent`](#--httpuser-agent)
-       38. [`--http.connect-timeout`](#--httpconnect-timeout)
-       39. [`--http.transfer-timeout`](#--httptransfer-timeout)
-       40. [`--http.idle-timeout`](#--httpidle-timeout)
-       41. [`--http.ca-path`](#--httpca-path)
-       42. [`--output.roa`](#--outputroa)
-       43. [`--output.bgpsec`](#--outputbgpsec)
-       44. [`--asn1-decode-max-stack`](#--asn1-decode-max-stack)
-       45. [`--stale-repository-period`](#--stale-repository-period)
-       46. [`--rsync.enabled`](#--rsyncenabled)
-       47. [`--rsync.priority`](#--rsyncpriority)
-       48. [`--rsync.strategy`](#--rsyncstrategy)
+       8. [`--daemon`](#--daemon)
+       9. [`--shuffle-uris`](#--shuffle-uris)
+       10. [`--maximum-certificate-depth`](#--maximum-certificate-depth)
+       11. [`--mode`](#--mode)
+       12. [`--server.address`](#--serveraddress)
+       13. [`--server.port`](#--serverport)
+       14. [`--server.backlog`](#--serverbacklog)
+       15. [`--server.interval.validation`](#--serverintervalvalidation)
+       16. [`--server.interval.refresh`](#--serverintervalrefresh)
+       17. [`--server.interval.retry`](#--serverintervalretry)
+       18. [`--server.interval.expire`](#--serverintervalexpire)
+       19. [`--slurm`](#--slurm)
+       20. [`--log.enabled`](#--logenabled)
+       21. [`--log.level`](#--loglevel)
+       22. [`--log.output`](#--logoutput)
+       23. [`--log.color-output`](#--logcolor-output)
+       24. [`--log.file-name-format`](#--logfile-name-format)
+       25. [`--log.facility`](#--logfacility)
+       26. [`--log.tag`](#--logtag)
+       27. [`--validation-log.enabled`](#--validation-logenabled)
+       28. [`--validation-log.level`](#--validation-loglevel)
+       29. [`--validation-log.output`](#--validation-logoutput)
+       30. [`--validation-log.color-output`](#--validation-logcolor-output)
+       31. [`--validation-log.file-name-format`](#--validation-logfile-name-format)
+       32. [`--validation-log.facility`](#--validation-logfacility)
+       33. [`--validation-log.tag`](#--validation-logtag)
+       34. [`--http.enabled`](#--httpenabled)
+       35. [`--http.priority`](#--httppriority)
+       36. [`--http.retry.count`](#--httpretrycount)
+       37. [`--http.retry.interval`](#--httpretryinterval)
+       38. [`--http.user-agent`](#--httpuser-agent)
+       39. [`--http.connect-timeout`](#--httpconnect-timeout)
+       40. [`--http.transfer-timeout`](#--httptransfer-timeout)
+       41. [`--http.idle-timeout`](#--httpidle-timeout)
+       42. [`--http.ca-path`](#--httpca-path)
+       43. [`--output.roa`](#--outputroa)
+       44. [`--output.bgpsec`](#--outputbgpsec)
+       45. [`--asn1-decode-max-stack`](#--asn1-decode-max-stack)
+       46. [`--stale-repository-period`](#--stale-repository-period)
+       47. [`--rsync.enabled`](#--rsyncenabled)
+       48. [`--rsync.priority`](#--rsyncpriority)
+       49. [`--rsync.strategy`](#--rsyncstrategy)
                1. [`strict`](#strict)
                2. [`root`](#root)
                3. [`root-except-ta`](#root-except-ta)
-       49. [`--rsync.retry.count`](#--rsyncretrycount)
-       50. [`--rsync.retry.interval`](#--rsyncretryinterval)
-       51. [`--configuration-file`](#--configuration-file)
-       52. [`rsync.program`](#rsyncprogram)
-       53. [`rsync.arguments-recursive`](#rsyncarguments-recursive)
-       54. [`rsync.arguments-flat`](#rsyncarguments-flat)
-       55. [`incidences`](#incidences)
-       56. [`init-locations`](#init-locations)
+       50. [`--rsync.retry.count`](#--rsyncretrycount)
+       51. [`--rsync.retry.interval`](#--rsyncretryinterval)
+       52. [`--configuration-file`](#--configuration-file)
+       53. [`rsync.program`](#rsyncprogram)
+       54. [`rsync.arguments-recursive`](#rsyncarguments-recursive)
+       55. [`rsync.arguments-flat`](#rsyncarguments-flat)
+       56. [`incidences`](#incidences)
+       57. [`init-locations`](#init-locations)
 3. [Deprecated arguments](#deprecated-arguments)
        1. [`--sync-strategy`](#--sync-strategy)
        2. [`--rrdp.enabled`](#--rrdpenabled)
@@ -89,6 +90,7 @@ description: Guide to use arguments of FORT Validator.
         [--local-repository=<directory>]
         [--sync-strategy=off|strict|root|root-except-ta]
         [--work-offline]
+        [--daemon]
         [--shuffle-uris]
         [--maximum-certificate-depth=<unsigned integer>]
         [--asn1-decode-max-stack=<unsigned integer>]
@@ -274,6 +276,15 @@ If this flag is activated, Fort will disable all outgoing requests (currently do
 
 Otherwise, Fort will perform outgoing requests whenever this is needed. If a specific protocol needs to be deactivated, use [`--rsync.enabled`](#--rsyncenabled) or [`--http.enabled`](#--httpenabled).
 
+### `--daemon`
+
+- **Type:** None
+- **Availability:** `argv` and JSON
+
+If this flag is activated, Fort will run as a daemon. The process is detached from the calling terminal and sent to the background.
+
+All the enabled logs will be sent to syslog, so the configured values of [`--log.output`](#--logoutput) and [`--validation-log.output`](#--validation-logoutput) will be ignored.
+
 ### `--shuffle-uris`
 
 - **Type:** None
@@ -868,6 +879,7 @@ The configuration options are mostly the same as the ones from the `argv` interf
        "<a href="#--maximum-certificate-depth">maximum-certificate-depth</a>": 32,
        "<a href="#--slurm">slurm</a>": "/tmp/fort/test.slurm",
        "<a href="#--mode">mode</a>": "server",
+       "<a href="#--daemon">daemon</a>": false,
 
        "server": {
                "<a href="#--serveraddress">address</a>": "127.0.0.1",
index 71d9fdb2b7fc8ecb68816f1f41976907b791c497..9951dc0f97055a0a5887f939caac9e98ae75f7de 100644 (file)
@@ -5,6 +5,7 @@
   "shuffle-uris": false,
   "maximum-certificate-depth": 32,
   "mode": "server",
+  "daemon": false,
   "server": {
     "address": "127.0.0.1",
     "port": "8323",
index 266b86973562274b03f0f1e4df93aa890fbabb94..fe941cd99323ecc1148ebc6ab31f03080626ab5b 100644 (file)
@@ -303,6 +303,16 @@ By default, the path is \fI/tmp/fort/repository\fR.
 .RE
 .P
 
+.B \-\-daemon
+.RS 4
+If this flag is activated, Fort will run as a daemon. The process is detached
+from the calling terminal and sent to the background.
+.P
+All the enabled logs will be sent to syslog, so the configured values of
+\fB--log.output\fR and \fB--validation-log.output\fR will be ignored.
+.RE
+.P
+
 .B \-\-sync-strategy=(\fIoff\fR|\fIstrict\fR|\fIroot\fR|\fIroot-except-ta\fR)
 .RS 4
 This argument \fBwill be DEPRECATED\fR. Use \fB--rsync.strategy\fR or
@@ -1208,6 +1218,7 @@ to a specific value:
   "shuffle-uris": true,
   "maximum-certificate-depth": 32,
   "mode": "server",
+  "daemon": false,
   "slurm": "/tmp/fort/test.slurm",
   "server": {
     "address": "127.0.0.1",
index a6ab0da5fd6450d40f8a7d358863538e83012b5b..c4ee73a47547e8e5bdf6e390dcf94fb5081d92fd 100644 (file)
@@ -13,6 +13,7 @@ fort_SOURCES += cert_stack.h cert_stack.c
 fort_SOURCES += clients.c clients.h
 fort_SOURCES += common.c common.h
 fort_SOURCES += config.h config.c
+fort_SOURCES += daemon.h daemon.c
 fort_SOURCES += debug.h debug.c
 fort_SOURCES += delete_dir_daemon.h delete_dir_daemon.c
 fort_SOURCES += extension.h extension.c
index 4130035e3fc65593b0eade104da74abb4863de77..d77935b344af854b50577d46e5545684456cd4af 100644 (file)
@@ -10,6 +10,7 @@
 
 #include "common.h"
 #include "configure_ac.h"
+#include "daemon.h"
 #include "file.h"
 #include "init.h"
 #include "json_handler.h"
@@ -61,6 +62,10 @@ struct rpki_config {
         * 'true' uses only local files located at local-repository.
         */
        bool work_offline;
+       /*
+        * Run fort as a daemon.
+        */
+       bool daemon;
 
        struct {
                /** The bound listening address of the RTR server. */
@@ -319,6 +324,12 @@ static const struct option_field options[] = {
                .type = &gt_work_offline,
                .offset = offsetof(struct rpki_config, work_offline),
                .doc = "Disable all outgoing requests (rsync, http (implies RRDP)) and work only with local repository files.",
+       }, {
+               .id = 1006,
+               .name = "daemon",
+               .type = &gt_bool,
+               .offset = offsetof(struct rpki_config, daemon),
+               .doc = "Run fort as a daemon.",
        },
 
        /* Server fields */
@@ -941,6 +952,7 @@ set_default_values(void)
        rpki_config.maximum_certificate_depth = 32;
        rpki_config.mode = SERVER;
        rpki_config.work_offline = false;
+       rpki_config.daemon = false;
 
        rpki_config.rsync.enabled = true;
        rpki_config.rsync.priority = 50;
@@ -1197,6 +1209,15 @@ handle_flags_config(int argc, char **argv)
                exit(error);
        }
 
+       if (rpki_config.daemon) {
+               pr_op_warn("Executing as daemon, all logs will be sent to syslog.");
+               /* Send all logs to syslog */
+               rpki_config.log.output = SYSLOG;
+               rpki_config.validation_log.output = SYSLOG;
+               error = daemonize(log_start);
+               goto end;
+       }
+
        log_start();
 end:
        if (error) {
diff --git a/src/daemon.c b/src/daemon.c
new file mode 100644 (file)
index 0000000..9688e10
--- /dev/null
@@ -0,0 +1,91 @@
+#include "daemon.h"
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "log.h"
+
+/*
+ * Daemonize fort execution. The function "daemon()" from unistd header isn't
+ * utilized since isn't standardized (too bad).
+ *
+ * The logs must be sent to syslog before this call, the @log_cb is called to
+ * initialize logging after the first fork() call.
+ *
+ * This function exits on any error once the first fork is successfully done.
+ */
+int
+daemonize(daemon_log_cb log_cb)
+{
+       char *pwd;
+       pid_t pid;
+       long int fds;
+
+       /* Already a daemon, just return */
+       if (getppid() == 1)
+               return 0;
+
+       /* Get the working dir, the daemon will use (and free) it later */
+       pwd = getcwd(NULL, 0);
+       if (pwd == NULL)
+               return pr_enomem();
+
+       pid = fork();
+       if (pid < 0)
+               return pr_op_errno(errno, "Couldn't fork to daemonize");
+
+       /* Terminate parent */
+       if (pid > 0)
+               exit(0);
+
+       /* Activate logs */
+       log_cb();
+
+       /* Child goes on from here */
+       if (setsid() < 0) {
+               pr_op_errno(errno,
+                   "Couldn't create new session, ending execution");
+               exit(errno);
+       }
+
+       /*
+        * Ignore SIGHUP. SIGCHLD isn't ignored since we still do a fork to
+        * execute rsync; when that's not the case then:
+        *   signal(SIGCHLD, SIG_IGN);
+        */
+       signal(SIGHUP, SIG_IGN);
+
+       /* Assure this is not a session leader */
+       pid = fork();
+       if (pid < 0) {
+               pr_op_errno(errno,
+                   "Couldn't fork again to daemonize, ending execution");
+               exit(errno);
+       }
+
+       /* Terminate parent */
+       if (pid > 0)
+               exit(0);
+
+       /* Close all descriptors, getdtablesize() isn't portable */
+       fds = sysconf(_SC_OPEN_MAX);
+       while (fds >= 0) {
+               close(fds);
+               fds--;
+       }
+
+       /* No privileges revoked to create files/dirs */
+       umask(0);
+
+       if (chdir(pwd) < 0) {
+               pr_op_errno(errno,
+                   "Couldn't chdir() of daemon, ending execution");
+               exit(errno);
+       }
+
+       free(pwd);
+       return 0;
+}
diff --git a/src/daemon.h b/src/daemon.h
new file mode 100644 (file)
index 0000000..94e7967
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef SRC_DAEMON_H_
+#define SRC_DAEMON_H_
+
+typedef void (*daemon_log_cb)(void);
+int daemonize(daemon_log_cb);
+
+#endif /* SRC_DAEMON_H_ */
index 5f56159c80a354bef20f20c869858481b6160dab..f5d8c7a94ab987944b524d16fb82a25ef259c5b4 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -101,8 +101,6 @@ log_start(void)
                val_syslog_enabled = false;
        }
 
-
-
        if (op_global_log_enabled) {
                switch (config_get_op_log_output()) {
                case SYSLOG:
@@ -128,8 +126,6 @@ log_start(void)
                else
                        op_syslog_enabled = false;
        }
-
-
 }
 
 void