aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--options.c10
-rw-r--r--route.c138
-rw-r--r--route.h1
3 files changed, 80 insertions, 69 deletions
diff --git a/options.c b/options.c
index cd73d92..ab75f6a 100644
--- a/options.c
+++ b/options.c
@@ -182,7 +182,7 @@ static const char usage_message[] =
" by server EXCEPT for routes.\n"
"--allow-pull-fqdn : Allow client to pull DNS names from server for\n"
" --ifconfig, --route, and --route-gateway.\n"
- "--redirect-gateway [flags]: (Experimental) Automatically execute routing\n"
+ "--redirect-gateway [flags]: Automatically execute routing\n"
" commands to redirect all outgoing IP traffic through the\n"
" VPN. Add 'local' flag if both " PACKAGE_NAME " servers are directly\n"
" connected via a common subnet, such as with WiFi.\n"
@@ -190,6 +190,8 @@ static const char usage_message[] =
" and 128.0.0.0/1 rather than 0.0.0.0/0. Add 'bypass-dhcp'\n"
" flag to add a direct route to DHCP server, bypassing tunnel.\n"
" Add 'bypass-dns' flag to similarly bypass tunnel for DNS.\n"
+ "--redirect-private [flags]: Like --redirect-gateway, but omit actually changing\n"
+ " the default gateway. Useful when pushing private subnets.\n"
"--setenv name value : Set a custom environmental variable to pass to script.\n"
"--setenv FORWARD_COMPATIBLE 1 : Relax config file syntax checking to allow\n"
" directives for future OpenVPN versions to be ignored.\n"
@@ -4391,13 +4393,15 @@ add_option (struct options *options,
VERIFY_PERMISSION (OPT_P_GENERAL);
options->allow_pull_fqdn = true;
}
- else if (streq (p[0], "redirect-gateway"))
+ else if (streq (p[0], "redirect-gateway") || streq (p[0], "redirect-private"))
{
int j;
VERIFY_PERMISSION (OPT_P_ROUTE);
rol_check_alloc (options);
for (j = 1; j < MAX_PARMS && p[j] != NULL; ++j)
{
+ if (streq (p[0], "redirect-gateway"))
+ options->routes->flags |= RG_REROUTE_GW;
if (streq (p[j], "local"))
options->routes->flags |= RG_LOCAL;
else if (streq (p[j], "def1"))
@@ -4408,7 +4412,7 @@ add_option (struct options *options,
options->routes->flags |= RG_BYPASS_DNS;
else
{
- msg (msglevel, "unknown --redirect-gateway flag: %s", p[j]);
+ msg (msglevel, "unknown --%s flag: %s", p[0], p[j]);
goto err;
}
}
diff --git a/route.c b/route.c
index d31b023..68b0fa3 100644
--- a/route.c
+++ b/route.c
@@ -543,18 +543,83 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u
/* route DHCP/DNS server traffic through original default gateway */
add_bypass_routes (&rl->spec.bypass, rl->spec.net_gateway, tt, flags, es);
+ if (rl->flags & RG_REROUTE_GW)
+ {
+ if (rl->flags & RG_DEF1)
+ {
+ /* add new default route (1st component) */
+ add_route3 (0x00000000,
+ 0x80000000,
+ rl->spec.remote_endpoint,
+ tt,
+ flags,
+ es);
+
+ /* add new default route (2nd component) */
+ add_route3 (0x80000000,
+ 0x80000000,
+ rl->spec.remote_endpoint,
+ tt,
+ flags,
+ es);
+ }
+ else
+ {
+ /* delete default route */
+ del_route3 (0,
+ 0,
+ rl->spec.net_gateway,
+ tt,
+ flags,
+ es);
+
+ /* add new default route */
+ add_route3 (0,
+ 0,
+ rl->spec.remote_endpoint,
+ tt,
+ flags,
+ es);
+ }
+ }
+
+ /* set a flag so we can undo later */
+ rl->did_redirect_default_gateway = true;
+ }
+ }
+}
+
+static void
+undo_redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
+{
+ if (rl->did_redirect_default_gateway)
+ {
+ /* delete remote host route */
+ if (!(rl->flags & RG_LOCAL))
+ del_route3 (rl->spec.remote_host,
+ ~0,
+ rl->spec.net_gateway,
+ tt,
+ flags,
+ es);
+
+ /* delete special DHCP/DNS bypass route */
+ del_bypass_routes (&rl->spec.bypass, rl->spec.net_gateway, tt, flags, es);
+
+ if (rl->flags & RG_REROUTE_GW)
+ {
if (rl->flags & RG_DEF1)
{
- /* add new default route (1st component) */
- add_route3 (0x00000000,
+ /* delete default route (1st component) */
+ del_route3 (0x00000000,
0x80000000,
rl->spec.remote_endpoint,
tt,
flags,
es);
- /* add new default route (2nd component) */
- add_route3 (0x80000000,
+ /* delete default route (2nd component) */
+ del_route3 (0x80000000,
0x80000000,
rl->spec.remote_endpoint,
tt,
@@ -566,78 +631,19 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u
/* delete default route */
del_route3 (0,
0,
- rl->spec.net_gateway,
+ rl->spec.remote_endpoint,
tt,
flags,
es);
- /* add new default route */
+ /* restore original default route */
add_route3 (0,
0,
- rl->spec.remote_endpoint,
+ rl->spec.net_gateway,
tt,
flags,
es);
}
-
- /* set a flag so we can undo later */
- rl->did_redirect_default_gateway = true;
- }
- }
-}
-
-static void
-undo_redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
-{
- if (rl->did_redirect_default_gateway)
- {
- /* delete remote host route */
- if (!(rl->flags & RG_LOCAL))
- del_route3 (rl->spec.remote_host,
- ~0,
- rl->spec.net_gateway,
- tt,
- flags,
- es);
-
- /* delete special DHCP/DNS bypass route */
- del_bypass_routes (&rl->spec.bypass, rl->spec.net_gateway, tt, flags, es);
-
- if (rl->flags & RG_DEF1)
- {
- /* delete default route (1st component) */
- del_route3 (0x00000000,
- 0x80000000,
- rl->spec.remote_endpoint,
- tt,
- flags,
- es);
-
- /* delete default route (2nd component) */
- del_route3 (0x80000000,
- 0x80000000,
- rl->spec.remote_endpoint,
- tt,
- flags,
- es);
- }
- else
- {
- /* delete default route */
- del_route3 (0,
- 0,
- rl->spec.remote_endpoint,
- tt,
- flags,
- es);
-
- /* restore original default route */
- add_route3 (0,
- 0,
- rl->spec.net_gateway,
- tt,
- flags,
- es);
}
rl->did_redirect_default_gateway = false;
diff --git a/route.h b/route.h
index 4b3a35c..27ac623 100644
--- a/route.h
+++ b/route.h
@@ -82,6 +82,7 @@ struct route_option {
#define RG_DEF1 (1<<2)
#define RG_BYPASS_DHCP (1<<3)
#define RG_BYPASS_DNS (1<<4)
+#define RG_REROUTE_GW (1<<5)
struct route_option_list {
int n;