From a926b3453f272ea7935156aedbcf8c40400449fe Mon Sep 17 00:00:00 2001 From: Martin Hecht Date: Tue, 20 Feb 2018 14:48:03 +0100 Subject: [PATCH] added --persistent option for automatic reconnects (#190) squashed the following individual commits during merge: call run_tunnel from a single place added --loop option for automatic reconnects catch too large loop values and clean up merge artifacts in man page make lint test pass change the term "loop" to "persistent" wrap long lines to make lint happy --- doc/openfortivpn.1.in | 7 +++++++ src/config.c | 9 +++++++++ src/config.h | 2 ++ src/io.c | 9 +++++++++ src/io.h | 2 ++ src/main.c | 27 ++++++++++++++++++++++++--- 6 files changed, 53 insertions(+), 3 deletions(-) diff --git a/doc/openfortivpn.1.in b/doc/openfortivpn.1.in index d918cfaf..fd68702c 100644 --- a/doc/openfortivpn.1.in +++ b/doc/openfortivpn.1.in @@ -26,6 +26,7 @@ openfortivpn \- Client for PPP+SSL VPN tunnel services [\fB\-\-pppd-plugin=\fI\fR] [\fB\-\-pppd-ipparam=\fI\fR] [\fB\-\-pppd-ifname=\fI\fR] +[\fB\-\-persistent\fR] [\fB\-c\fR \fI\fR] [\fB\-v|\-q\fR] .br @@ -128,6 +129,10 @@ for further details \fB\-\-pppd-ifname=\fI\fR Set the ppp interface name. Only if supported by pppd. Patched versions of pppd implement this option but may not be available on your platform. +\fB\-\-persistent\=\fIfR +Runs the vpn persistently in an endless loop and tries to reconnect forever. +The reconnect interval may be specified in seconds, where 0 means +no reconnect is done (this is the default). .TP \fB\-v\fR Increase verbosity. Can be used multiple times to be even more verbose. @@ -233,3 +238,5 @@ pppd-use-peerdns = 1 insecure-ssl = 0 .br cipher-list = HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4 +.br +persistent = 0 diff --git a/src/config.c b/src/config.c index 54e86854..451b678a 100644 --- a/src/config.c +++ b/src/config.c @@ -200,6 +200,15 @@ int load_config(struct vpn_config *cfg, const char *filename) continue; } cfg->half_internet_routes = half_internet_routes; + } else if (strcmp(key, "persistent") == 0) { + long int persistent = strtol(val, NULL, 0); + if (persistent < 0) { + log_warn("Bad value for persistent in config file:" \ + " \"%s\".\n", + val); + continue; + } + cfg->persistent = persistent; } else if (strcmp(key, "pppd-use-peerdns") == 0) { int pppd_use_peerdns = strtob(val); if (pppd_use_peerdns < 0) { diff --git a/src/config.h b/src/config.h index 05d0c3f3..26bd45f0 100644 --- a/src/config.h +++ b/src/config.h @@ -69,6 +69,8 @@ struct vpn_config { int use_syslog; int half_internet_routes; + unsigned int persistent; + char *pppd_log; char *pppd_plugin; char *pppd_ipparam; diff --git a/src/io.c b/src/io.c index a65e2fdd..65dd94d6 100644 --- a/src/io.c +++ b/src/io.c @@ -109,6 +109,14 @@ static void destroy_ssl_locks(void) } #endif +// global variable to pass signal out of its handler +volatile sig_atomic_t sig_received = 0; + +int get_sig_received(void) +{ + return (int)sig_received; +} + /* * Adds a new packet to a pool. * @@ -559,6 +567,7 @@ static void *if_config(void *arg) static void sig_handler(int signo) { + sig_received = signo; if (signo == SIGINT || signo == SIGTERM) SEM_POST(&sem_stop_io); } diff --git a/src/io.h b/src/io.h index b18d0a0d..f6a7f0db 100644 --- a/src/io.h +++ b/src/io.h @@ -56,4 +56,6 @@ struct tunnel; int io_loop(struct tunnel *tunnel); +int get_sig_received(void); + #endif diff --git a/src/main.c b/src/main.c index b3cd7b6e..d6fe9315 100644 --- a/src/main.c +++ b/src/main.c @@ -35,7 +35,7 @@ " [--pppd-plugin=] [--ca-file=]\n" \ " [--user-cert=] [--user-key=]\n" \ " [--trusted-cert=] [--use-syslog]\n" \ -" [-c ] [-v|-q]\n" \ +" [--persistent=] [-c ] [-v|-q]\n" \ " openfortivpn --help\n" \ " openfortivpn --version\n" \ "\n" @@ -93,6 +93,8 @@ " --pppd-ifname= Set the pppd interface name, if supported by pppd.\n" \ " --pppd-ipparam= Provides an extra parameter to the ip-up, ip-pre-up\n" \ " and ip-down scripts. See man (8) pppd\n" \ +" --persistent= Run the vpn persistently in a loop and try to re-\n" \ +" connect every seconds when dropping out\n" \ " -v Increase verbosity. Can be used multiple times\n" \ " to be even more verbose.\n" \ " -q Decrease verbosity. Can be used multiple times\n" \ @@ -181,6 +183,7 @@ int main(int argc, char **argv) {"no-dns", no_argument, &cfg.set_dns, 0}, {"pppd-no-peerdns", no_argument, &cfg.pppd_use_peerdns, 0}, {"use-syslog", no_argument, &cfg.use_syslog, 1}, + {"persistent", required_argument, 0, 0}, {"ca-file", required_argument, 0, 0}, {"user-cert", required_argument, 0, 0}, {"user-key", required_argument, 0, 0}, @@ -301,6 +304,17 @@ int main(int argc, char **argv) cfg.half_internet_routes = half_internet_routes; break; } + if (strcmp(long_options[option_index].name, + "persistent") == 0) { + long int persistent = strtol(optarg, NULL, 0); + if ((persistent < 0) || (persistent >= UINT_MAX)) { + log_warn("Bad persistent option: " \ + "\"%s\"\n", optarg); + break; + } + cfg.persistent = persistent; + break; + } if (strcmp(long_options[option_index].name, "set-dns") == 0) { int set_dns = strtob(optarg); @@ -425,8 +439,15 @@ int main(int argc, char **argv) log_warn("This process was not spawned with root " "privileges, this will probably not work.\n"); - if (run_tunnel(&cfg) == 0) - ret = EXIT_SUCCESS; + do { + if (run_tunnel(&cfg) != 0) { + ret = EXIT_FAILURE; + } else + ret = EXIT_SUCCESS; + if ((cfg.persistent > 0) && (get_sig_received() == 0)) + sleep(cfg.persistent); + } while ((get_sig_received() == 0) && (cfg.persistent !=0)); + goto exit; user_error: