From: pcarana Date: Fri, 30 Oct 2020 20:18:13 +0000 (-0600) Subject: Add '--daemon' argument to daemonize fort, fixes #25 X-Git-Tag: v1.5.0~15 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=98c112826f5253e7a604205067e5862e02a049da;p=thirdparty%2FFORT-validator.git Add '--daemon' argument to daemonize fort, fixes #25 +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. --- diff --git a/docs/usage.md b/docs/usage.md index cfbaf0dc..e0b37f44 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -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=] [--sync-strategy=off|strict|root|root-except-ta] [--work-offline] + [--daemon] [--shuffle-uris] [--maximum-certificate-depth=] [--asn1-decode-max-stack=] @@ -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 "maximum-certificate-depth": 32, "slurm": "/tmp/fort/test.slurm", "mode": "server", + "daemon": false, "server": { "address": "127.0.0.1", diff --git a/examples/config.json b/examples/config.json index 71d9fdb2..9951dc0f 100644 --- a/examples/config.json +++ b/examples/config.json @@ -5,6 +5,7 @@ "shuffle-uris": false, "maximum-certificate-depth": 32, "mode": "server", + "daemon": false, "server": { "address": "127.0.0.1", "port": "8323", diff --git a/man/fort.8 b/man/fort.8 index 266b8697..fe941cd9 100644 --- a/man/fort.8 +++ b/man/fort.8 @@ -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", diff --git a/src/Makefile.am b/src/Makefile.am index a6ab0da5..c4ee73a4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 diff --git a/src/config.c b/src/config.c index 4130035e..d77935b3 100644 --- a/src/config.c +++ b/src/config.c @@ -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 = >_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 = >_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 index 00000000..9688e103 --- /dev/null +++ b/src/daemon.c @@ -0,0 +1,91 @@ +#include "daemon.h" + +#include +#include +#include +#include +#include +#include +#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 index 00000000..94e79671 --- /dev/null +++ b/src/daemon.h @@ -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_ */ diff --git a/src/log.c b/src/log.c index 5f56159c..f5d8c7a9 100644 --- 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