Attention is currently required from: plaisthos.

Hello plaisthos,

I'd like you to do a code review.
Please visit

    http://gerrit.openvpn.net/c/openvpn/+/1704?usp=email

to review the following change.


Change subject: route: Don't delete pre-existing host route to VPN server on 
disconnect
......................................................................

route: Don't delete pre-existing host route to VPN server on disconnect

When a host route to the VPN server already exists at connect time
(e.g. a manually configured static route), add_route3() returns true
for both "successfully added" and "already exists" but discards the
per-route RT_ADDED bit, since it operates on a local struct route_ipv4.
The caller in redirect_default_route_to_vpn() then sets RL_DID_LOCAL
unconditionally, and on disconnect undo_redirect_default_route_to_vpn()
asks del_route3() to delete it -- which forces RT_ADDED on a fresh struct,
bypassing delete_route()'s protective guard. The result: the pre-existing
route gets removed.

Change add_route3() to return RTA_SUCCESS / RTA_EEXIST / RTA_ERROR by
inspecting the local struct's RT_ADDED bit after add_route(). Only set
RL_DID_LOCAL on RTA_SUCCESS so a pre-existing route survives disconnect.
Apply the same fix to the DHCP/DNS bypass routes via a new
route_bypass.bypass_added bitmask so each entry is only deleted on undo
if we added it.

GitHub: #970

Change-Id: I21d782780b7f89b3061dd97500589a24415afc23
Signed-off-by: Lev Stipakov <[email protected]>
---
M src/openvpn/route.c
M src/openvpn/route.h
2 files changed, 39 insertions(+), 17 deletions(-)



  git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/04/1704/1

diff --git a/src/openvpn/route.c b/src/openvpn/route.c
index 81ce867..06e63e1 100644
--- a/src/openvpn/route.c
+++ b/src/openvpn/route.c
@@ -882,7 +882,10 @@
     return ret;
 }

-static bool
+/* Returns RTA_SUCCESS, RTA_EEXIST or RTA_ERROR. RTA_EEXIST means the
+ * route was already present in the system and was not added by us; the
+ * caller must not delete it on undo. */
+static int
 add_route3(in_addr_t network, in_addr_t netmask, in_addr_t gateway, const 
struct tuntap *tt,
            unsigned int flags, const struct route_gateway_info *rgi, const 
struct env_set *es,
            openvpn_net_ctx_t *ctx)
@@ -893,7 +896,11 @@
     r.network = network;
     r.netmask = netmask;
     r.gateway = gateway;
-    return add_route(&r, tt, flags, rgi, es, ctx);
+    if (!add_route(&r, tt, flags, rgi, es, ctx))
+    {
+        return RTA_ERROR;
+    }
+    return (r.flags & RT_ADDED) ? RTA_SUCCESS : RTA_EEXIST;
 }

 static void
@@ -915,14 +922,19 @@
                   unsigned int flags, const struct route_gateway_info *rgi,
                   const struct env_set *es, openvpn_net_ctx_t *ctx)
 {
-    int ret = true;
+    bool ret = true;
+    rb->bypass_added = 0;
     for (int i = 0; i < rb->n_bypass; ++i)
     {
         if (rb->bypass[i])
         {
-            ret = add_route3(rb->bypass[i], IPV4_NETMASK_HOST, gateway, tt, 
flags | ROUTE_REF_GW,
-                             rgi, es, ctx)
-                  && ret;
+            int status = add_route3(rb->bypass[i], IPV4_NETMASK_HOST, gateway, 
tt,
+                                    flags | ROUTE_REF_GW, rgi, es, ctx);
+            if (status == RTA_SUCCESS)
+            {
+                rb->bypass_added |= (1u << i);
+            }
+            ret = (status != RTA_ERROR) && ret;
         }
     }
     return ret;
@@ -933,15 +945,15 @@
                   unsigned int flags, const struct route_gateway_info *rgi,
                   const struct env_set *es, openvpn_net_ctx_t *ctx)
 {
-    int i;
-    for (i = 0; i < rb->n_bypass; ++i)
+    for (int i = 0; i < rb->n_bypass; ++i)
     {
-        if (rb->bypass[i])
+        if (rb->bypass[i] && (rb->bypass_added & (1u << i)))
         {
             del_route3(rb->bypass[i], IPV4_NETMASK_HOST, gateway, tt, flags | 
ROUTE_REF_GW, rgi, es,
                        ctx);
         }
     }
+    rb->bypass_added = 0;
 }
 
 static bool
@@ -996,12 +1008,16 @@
                 if ((rl->spec.flags & RTSA_REMOTE_HOST)
                     && rl->spec.remote_host != IPV4_INVALID_ADDR)
                 {
-                    ret = add_route3(rl->spec.remote_host, IPV4_NETMASK_HOST, 
rl->rgi.gateway.addr,
-                                     tt, flags | ROUTE_REF_GW, &rl->rgi, es, 
ctx);
-                    if (ret)
+                    int status = add_route3(rl->spec.remote_host, 
IPV4_NETMASK_HOST,
+                                            rl->rgi.gateway.addr, tt, flags | 
ROUTE_REF_GW,
+                                            &rl->rgi, es, ctx);
+                    /* only flag as ours-to-undo when we actually added it;
+                     * a pre-existing route (RTA_EEXIST) must survive 
disconnect */
+                    if (status == RTA_SUCCESS)
                     {
                         rl->iflags |= RL_DID_LOCAL;
                     }
+                    ret = (status != RTA_ERROR);
                 }
                 else
                 {
@@ -1020,13 +1036,15 @@
                 if (rl->flags & RG_DEF1)
                 {
                     /* add new default route (1st component) */
-                    ret = add_route3(0x00000000, 0x80000000, 
rl->spec.remote_endpoint, tt, flags,
-                                     &rl->rgi, es, ctx)
+                    ret = (add_route3(0x00000000, 0x80000000, 
rl->spec.remote_endpoint, tt, flags,
+                                      &rl->rgi, es, ctx)
+                           != RTA_ERROR)
                           && ret;

                     /* add new default route (2nd component) */
-                    ret = add_route3(0x80000000, 0x80000000, 
rl->spec.remote_endpoint, tt, flags,
-                                     &rl->rgi, es, ctx)
+                    ret = (add_route3(0x80000000, 0x80000000, 
rl->spec.remote_endpoint, tt, flags,
+                                      &rl->rgi, es, ctx)
+                           != RTA_ERROR)
                           && ret;
                 }
                 else
@@ -1040,7 +1058,8 @@
                     }

                     /* add new default route */
-                    ret = add_route3(0, 0, rl->spec.remote_endpoint, tt, 
flags, &rl->rgi, es, ctx)
+                    ret = (add_route3(0, 0, rl->spec.remote_endpoint, tt, 
flags, &rl->rgi, es, ctx)
+                           != RTA_ERROR)
                           && ret;
                 }
             }
diff --git a/src/openvpn/route.h b/src/openvpn/route.h
index 88107e9..23d2eed 100644
--- a/src/openvpn/route.h
+++ b/src/openvpn/route.h
@@ -54,6 +54,9 @@
 #define N_ROUTE_BYPASS 8
     int n_bypass;
     in_addr_t bypass[N_ROUTE_BYPASS];
+    /* bit i set when bypass[i] was actually added by us (so we may delete
+     * it on undo); cleared when the route already existed in the system. */
+    unsigned int bypass_added;
 };

 struct route_special_addr

--
To view, visit http://gerrit.openvpn.net/c/openvpn/+/1704?usp=email
To unsubscribe, or for help writing mail filters, visit 
http://gerrit.openvpn.net/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: openvpn
Gerrit-Branch: master
Gerrit-Change-Id: I21d782780b7f89b3061dd97500589a24415afc23
Gerrit-Change-Number: 1704
Gerrit-PatchSet: 1
Gerrit-Owner: stipa <[email protected]>
Gerrit-Reviewer: plaisthos <[email protected]>
Gerrit-CC: openvpn-devel <[email protected]>
Gerrit-Attention: plaisthos <[email protected]>
_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to