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: