]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Introduce a rsync transfer timeout 147/head
authorJob Snijders <job@sobornost.net>
Thu, 22 Aug 2024 16:33:59 +0000 (16:33 +0000)
committerJob Snijders <job@sobornost.net>
Wed, 28 Aug 2024 13:35:09 +0000 (13:35 +0000)
Default set to 900 (same as rpki-client)

Fixes https://github.com/NICMx/FORT-validator/issues/74

docs/usage.md
examples/config.json
man/fort.8
src/config.c
src/config.h
src/rsync/rsync.c

index 9c3dfb3add16fa63f6c01265ba203a4958628cef..b751a08968c73e3e1210994283472e5fc1ed7530 100644 (file)
@@ -65,6 +65,7 @@ description: Guide to use arguments of FORT Validator.
        51. [`--rsync.priority`](#--rsyncpriority)
        53. [`--rsync.retry.count`](#--rsyncretrycount)
        54. [`--rsync.retry.interval`](#--rsyncretryinterval)
+       40. [`--rsync.transfer-timeout`](#--rsynctransfer-timeout)
        55. [`--configuration-file`](#--configuration-file)
        56. [`rsync.program`](#rsyncprogram)
        57. [`rsync.arguments-recursive`](#rsyncarguments-recursive)
@@ -103,6 +104,7 @@ description: Guide to use arguments of FORT Validator.
        [--rsync.priority=<unsigned integer>]
        [--rsync.retry.count=<unsigned integer>]
        [--rsync.retry.interval=<unsigned integer>]
+       [--rsync.transfer-timeout=<unsigned integer>]
        [--http.enabled=true|false]
        [--http.priority=<unsigned integer>]
        [--http.retry.count=<unsigned integer>]
@@ -931,6 +933,17 @@ Whenever is necessary to execute an RSYNC, the validator will try at least one t
 
 Period of time (in seconds) to wait between each retry to execute an RSYNC.
 
+### `--rsync.transfer-timeout`
+
+- **Type:** Integer
+- **Availability:** `argv` and JSON
+- **Default:** 900
+- **Range:** [0, [`UINT_MAX`](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html)]
+
+Maximum time in seconds that the rsync transfer can last.
+
+Once the connection is established with the server, the request will last a maximum of `rsync.transfer-timeout` seconds. A value of 0 means unlimited time.
+
 ### `--configuration-file`
 
 - **Type:** String (Path to file)
@@ -974,6 +987,7 @@ The configuration options are mostly the same as the ones from the `argv` interf
                        "<a href="#--rsyncretrycount">count</a>": 1,
                        "<a href="#--rsyncretryinterval">interval</a>": 4
                },
+               "<a href="#--rsynctransfer-timeout">transfer-timeout</a>": 0,
                "<a href="#rsyncprogram">program</a>": "rsync",
                "<a href="#rsyncarguments-recursive">arguments-recursive</a>": [
                        "-rtz",
index 0c9ca9f28a700c2b09926d4039cd72ec40cbc849..034fff5c092f0dc9b682fee848fa14dfde929af3 100644 (file)
@@ -56,6 +56,7 @@
       "count": 2,
       "interval": 5
     },
+    "transfer-timeout": 900,
     "program": "rsync",
     "arguments-recursive": [
       "--recursive",
index 3411106c0f5fc4c82fed7af3f5cafa498edfa23e..ce02be33935b01c68a87af4181ff9112323a946d 100644 (file)
@@ -1009,6 +1009,18 @@ By default, the value is \fI5\fR.
 .RE
 .P
 
+.B \-\-rsync.transfer\-timeout=\fIUNSIGNED_INTEGER\fR
+.RS 4
+Maximum time in seconds that the rsync process can last.
+.P
+Once the connection is established with the server, the request will last a
+maximum of \fBrsync.transfer-timeout\fR seconds. A value of \fI0\fR means
+unlimited time (default value).
+.P
+By default, it has a value of \fI900\fR.
+.RE
+.P
+
 .B \-\-output.roa=\fIFILE\fR
 .RS 4
 File where the ROAs will be printed in the configured format (see
index e010a9739f962ebf5d3d59ba11eb9a3c357dfa3c..7f2af628fc8d71eab24baf806d5d15a9d10e1c90 100644 (file)
@@ -86,6 +86,7 @@ struct rpki_config {
                        /* Interval (in seconds) between each retry */
                        unsigned int interval;
                } retry;
+               unsigned int transfer_timeout;
                char *program;
                struct {
                        struct string_array flat; /* Deprecated */
@@ -486,6 +487,14 @@ static const struct option_field options[] = {
                /* Unlimited */
                .max = 0,
                .deprecated = true,
+       }, {
+               .id = 3008,
+               .name = "rsync.transfer-timeout",
+               .type = &gt_uint,
+               .offset = offsetof(struct rpki_config, rsync.transfer_timeout),
+               .doc = "Maximum transfer time before killing the rsync process",
+               .min = 0,
+               .max = UINT_MAX,
        },
 
        /* HTTP requests parameters */
@@ -946,6 +955,7 @@ set_default_values(void)
        rpki_config.rsync.strategy = pstrdup("<deprecated>");
        rpki_config.rsync.retry.count = 1;
        rpki_config.rsync.retry.interval = 4;
+       rpki_config.rsync.transfer_timeout = 900;
        rpki_config.rsync.program = pstrdup("rsync");
        string_array_init(&rpki_config.rsync.args.flat,
            flat_rsync_args, ARRAY_LEN(flat_rsync_args));
@@ -1342,6 +1352,12 @@ config_get_rsync_retry_interval(void)
        return rpki_config.rsync.retry.interval;
 }
 
+long
+config_get_rsync_transfer_timeout(void)
+{
+       return rpki_config.rsync.transfer_timeout;
+}
+
 char *
 config_get_rsync_program(void)
 {
index 32dd17fd0b3a2ad490d5a87d307ac3c772020001..70c3c3989f577c2ea0a5a276946ff96cf54d4124 100644 (file)
@@ -44,6 +44,7 @@ bool config_get_rsync_enabled(void);
 unsigned int config_get_rsync_priority(void);
 unsigned int config_get_rsync_retry_count(void);
 unsigned int config_get_rsync_retry_interval(void);
+long config_get_rsync_transfer_timeout(void);
 char *config_get_rsync_program(void);
 struct string_array const *config_get_rsync_args(void);
 bool config_get_http_enabled(void);
index 2425a95bf6b507cd6d108318e71ff92739c3e90c..17c844eecf13e47de446f3769486fb18f6d13153 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <poll.h>
 #include <signal.h>
 #include <sys/wait.h>
 #include <syslog.h>
@@ -154,21 +155,44 @@ read_pipe(int fd_pipe[2][2], int type)
 {
        char buffer[4096];
        ssize_t count;
-       int error;
+       struct pollfd pfd[1];
+       int error, nready;
+
+       memset(&pfd, 0, sizeof(pfd));
+       pfd[0].fd = fd_pipe[type][0];
+       pfd[0].events = POLLIN;
 
        while (1) {
-               count = read(fd_pipe[type][0], buffer, sizeof(buffer));
-               if (count == -1) {
-                       error = errno;
-                       if (error == EINTR)
+               nready = poll(pfd, 1, 1000 * config_get_rsync_transfer_timeout());
+               if (nready == 0) {
+                       pr_val_err("rsync transfer timeout reached");
+                       close(fd_pipe[type][0]);
+                       return 1;
+               }
+               if (nready == -1) {
+                       if (errno == EINTR)
                                continue;
-                       close(fd_pipe[type][0]); /* Close read end */
-                       pr_val_err("rsync buffer read error: %s",
-                           strerror(error));
-                       return -error;
+                       pr_val_err("rsync bad poll");
+                       close(fd_pipe[type][0]);
+                       return 1;
+               }
+               if (pfd[0].revents & (POLLERR|POLLNVAL)) {
+                       pr_val_err("rsync bad fd: %i", pfd[0].fd);
+                       return 1;
+               } else if (pfd[0].revents & (POLLIN|POLLHUP)) {
+                       count = read(fd_pipe[type][0], buffer, sizeof(buffer));
+                       if (count == -1) {
+                               if (errno == EINTR)
+                                       continue;
+                               error = errno;
+                               close(fd_pipe[type][0]); /* Close read end */
+                               pr_val_err("rsync buffer read error: %s",
+                                   strerror(error));
+                               return -error;
+                       }
+                       if (count == 0)
+                               break;
                }
-               if (count == 0)
-                       break;
 
                log_buffer(buffer, count, type);
        }
@@ -276,7 +300,7 @@ rsync_download(char const *src, char const *dst, bool is_directory)
                /* This code is run by us. */
                error = read_pipes(fork_fds);
                if (error)
-                       kill(child_pid, SIGCHLD); /* Stop the child */
+                       kill(child_pid, SIGTERM); /* Stop the child */
 
                error = waitpid(child_pid, &child_status, 0);
                do {