diff --git a/src/config.c b/src/config.c index 9c6d3c5d..a95d16cc 100644 --- a/src/config.c +++ b/src/config.c @@ -51,6 +51,7 @@ const struct vpn_config invalid_cfg = { .no_ftm_push = -1, .pinentry = NULL, .realm = {'\0'}, + .tun = -1, .iface_name = {'\0'}, .sni = {'\0'}, .set_routes = -1, diff --git a/src/config.h b/src/config.h index eaf7f825..68466d3a 100644 --- a/src/config.h +++ b/src/config.h @@ -95,6 +95,7 @@ struct vpn_config { unsigned int otp_delay; int no_ftm_push; char *pinentry; + int tun; char iface_name[IF_NAMESIZE]; char realm[REALM_SIZE + 1]; diff --git a/src/http.c b/src/http.c index 6e02bc86..fc8e89db 100644 --- a/src/http.c +++ b/src/http.c @@ -832,7 +832,7 @@ static int parse_xml_config(struct tunnel *tunnel, const char *buffer) if (!gateway) log_warn("No gateway address, using interface for routing\n"); - if (tunnel->use_tun) { + if (tunnel->config->tun) { tunnel->ipv4.ip_addr.s_addr = inet_addr(gateway); tunnel->ipv4.peer_addr.s_addr = inet_addr("192.0.2.1"); } diff --git a/src/io.c b/src/io.c index 758afc69..5e4b3df4 100644 --- a/src/io.c +++ b/src/io.c @@ -1085,7 +1085,7 @@ static void *pppd_read(void *arg) log_debug("%s thread\n", __func__); - if (tunnel->use_tun) { + if (tunnel->config->tun) { switch (tunnel->tun_state) { case TUN_PPP_LCP: conf_request(tunnel); @@ -1122,7 +1122,7 @@ static void *pppd_read(void *arg) SEM_POST(&sem_pppd_ready); first_time = 0; } - if (tunnel->use_tun) { + if (tunnel->config->tun) { ssize_t pktsize = n + 2; struct ppp_packet *packet = NULL; @@ -1235,7 +1235,7 @@ static void *pppd_write(void *arg) // This waits until a packet has arrived from the gateway packet = pool_pop(&tunnel->ssl_to_pty_pool); - if (tunnel->use_tun) { + if (tunnel->config->tun) { void *pkt_type = pkt_data(packet); hdlc_bufsize = len = packet->len; @@ -1453,7 +1453,7 @@ static void *ssl_read(void *arg) set_tunnel_ips(tunnel, packet); - if (tunnel->use_tun) + if (tunnel->config->tun) tun_ifup(tunnel->tun_iface, tunnel->ipv4.ip_addr.s_addr, 0); strcpy(line, "["); diff --git a/src/main.c b/src/main.c index c1fba334..f2072bc2 100644 --- a/src/main.c +++ b/src/main.c @@ -80,7 +80,7 @@ " [--cookie=] [--cookie-on-stdin]\n" \ " [--otp=] [--otp-delay=] [--otp-prompt=]\n" \ " [--pinentry=] [--realm=]\n" \ -" [--ifname=] [--set-routes=<0|1>]\n" \ +" [--tun=<0|1>] [--ifname=] [--set-routes=<0|1>]\n" \ " [--half-internet-routes=<0|1>] [--set-dns=<0|1>]\n" \ PPPD_USAGE \ " " RESOLVCONF_USAGE "[--ca-file=]\n" \ @@ -123,6 +123,7 @@ PPPD_USAGE \ " --no-ftm-push Do not use FTM push if the server provides the option.\n" \ " --pinentry= Use the program to supply a secret instead of asking for it.\n" \ " --realm= Use specified authentication realm.\n" \ +" --tun=[01] Create a TUN device and use internal PPP code (experimental).\n" \ " --ifname= Bind to interface.\n" \ " --set-routes=[01] Set if openfortivpn should configure routes\n" \ " when tunnel is up.\n" \ @@ -290,6 +291,7 @@ int main(int argc, char *argv[]) {"otp-prompt", required_argument, NULL, 0}, {"otp-delay", required_argument, NULL, 0}, {"no-ftm-push", no_argument, &cli_cfg.no_ftm_push, 1}, + {"tun", required_argument, NULL, 0}, {"ifname", required_argument, NULL, 0}, {"set-routes", required_argument, NULL, 0}, {"sni", required_argument, NULL, 0}, @@ -514,6 +516,18 @@ int main(int argc, char *argv[]) cli_cfg.otp_prompt = strdup(optarg); break; } + if (strcmp(long_options[option_index].name, + "tun") == 0) { + int tun = strtob(optarg); + + if (tun < 0) { + log_warn("Bad tun option: \"%s\"\n", + optarg); + break; + } + cli_cfg.tun = tun; + break; + } if (strcmp(long_options[option_index].name, "ifname") == 0) { strncpy(cli_cfg.iface_name, optarg, IF_NAMESIZE - 1); @@ -677,6 +691,41 @@ int main(int argc, char *argv[]) merge_config(&cfg, &cli_cfg); set_syslog(cfg.use_syslog); + if (cfg.tun) { +#if HAVE_USR_SBIN_PPPD + if (cfg.pppd_use_peerdns) { + log_error("Option pppd_use_peerdns is not compatible with option tun\n"); + exit(EXIT_FAILURE); + } + if (cfg.pppd_plugin) { + log_error("Option pppd_plugin is not compatible with option tun\n"); + exit(EXIT_FAILURE); + } + if (cfg.pppd_ifname) { + log_error("Option pppd_ifname is not compatible with option tun\n"); + exit(EXIT_FAILURE); + } + if (cfg.pppd_ipparam) { + log_error("Option pppd_ipparam is not compatible with option tun\n"); + exit(EXIT_FAILURE); + } + if (cfg.pppd_call) { + log_error("Option pppd_call is not compatible with option tun\n"); + exit(EXIT_FAILURE); + } + if (cfg.pppd_plugin) { + log_error("Option pppd_plugin is not compatible with option tun\n"); + exit(EXIT_FAILURE); + } +#endif +#if HAVE_USR_SBIN_PPP + if (cfg.ppp_system) { + log_error("Option ppp_system is not compatible with option tun\n"); + exit(EXIT_FAILURE); + } +#endif + } + // Set default UA if (cfg.user_agent == NULL) cfg.user_agent = strdup("Mozilla/5.0 SV1"); diff --git a/src/tunnel.c b/src/tunnel.c index 569d6d9f..f1a485e9 100644 --- a/src/tunnel.c +++ b/src/tunnel.c @@ -1422,7 +1422,6 @@ int run_tunnel(struct vpn_config *config) goto err_tunnel; // Step 3: get configuration - tunnel.use_tun = 1; log_info("Retrieving configuration\n"); ret = auth_get_config(&tunnel); if (ret != 1) { @@ -1434,7 +1433,7 @@ int run_tunnel(struct vpn_config *config) // Step 4: run a pppd process log_info("Establishing the tunnel\n"); - if (tunnel.use_tun) + if (config->tun) ret = tun_setup(&tunnel); else ret = pppd_run(&tunnel); @@ -1467,7 +1466,7 @@ int run_tunnel(struct vpn_config *config) tunnel.state = STATE_DISCONNECTING; err_start_tunnel: - if (!tunnel.use_tun) { + if (!config->tun) { ret = pppd_terminate(&tunnel); log_info("Terminated %s.\n", PPP_DAEMON); } diff --git a/src/tunnel.h b/src/tunnel.h index bc900f80..6cca06d4 100644 --- a/src/tunnel.h +++ b/src/tunnel.h @@ -72,7 +72,6 @@ struct tunnel { pid_t pppd_pid; pid_t pppd_pty; - int use_tun; char tun_iface[ROUTE_IFACE_LEN]; char ppp_iface[ROUTE_IFACE_LEN];