]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Added new 'autolocal' redirect-gateway flag. When enabled, the OpenVPN
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Sun, 24 May 2009 09:13:58 +0000 (09:13 +0000)
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Sun, 24 May 2009 09:13:58 +0000 (09:13 +0000)
client will examine the routing table and determine whether (a) the
OpenVPN server is reachable via a locally connected interface, or (b)
traffic to the server must be forwarded through the default router.
Only add a special bypass route for the OpenVPN server if (b) is true.
If (a) is true, behave as if the 'local' flag is specified, and do not
add a bypass route.

The new 'autolocal' flag depends on the non-portable test_local_addr()
function in route.c, which is currently only implemented for Windows.
The 'autolocal' flag will act as a no-op on platforms that have not
yet defined a test_local_addr() function.

Increased TLS_CHANNEL_BUF_SIZE to 2048 from 1024 (this will allow for
more option content to be pushed from server to client).

Raised D_MULTI_DROPPED debug level to 4 from 3.

Version 2.1_rc16b.

git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@4446 e7ae566f-a301-0410-adde-c780ea21d3b5

common.h
errlevel.h
options.c
route.c
route.h
version.m4

index bc38699f95adef88543433653df8436de64cd026..69cae4ca087ca62b4bdb481fab03eeac8f90a080 100644 (file)
--- a/common.h
+++ b/common.h
@@ -79,7 +79,7 @@ typedef unsigned long ptr_type;
  * the full --push/--pull list.  If you increase it, do so
  * on both server and client.
  */
-#define TLS_CHANNEL_BUF_SIZE 1024
+#define TLS_CHANNEL_BUF_SIZE 2048
 
 /*
  * A sort of pseudo-filename for data provided inline within
index 1abe21d87def4b723f5a354351ac265a3d2279d1..ed645160c447ec7454961cf544fd2e88d31ab5e9 100644 (file)
 #define D_BACKTRACK          LOGLEV(3, 36, 0)        /* show replay backtracks */
 #define D_AUTH               LOGLEV(3, 37, 0)        /* show user/pass auth info */
 #define D_MULTI_LOW          LOGLEV(3, 38, 0)        /* show point-to-multipoint low-freq debug info */
-#define D_MULTI_DROPPED      LOGLEV(3, 39, 0)        /* show point-to-multipoint packet drops */
-#define D_PLUGIN             LOGLEV(3, 40, 0)        /* show plugin calls */
-#define D_MANAGEMENT         LOGLEV(3, 41, 0)        /* show --management info */
-#define D_SCHED_EXIT         LOGLEV(3, 42, 0)        /* show arming of scheduled exit */
-#define D_ROUTE_QUOTA        LOGLEV(3, 43, 0)        /* show route quota exceeded messages */
-#define D_OSBUF              LOGLEV(3, 44, 0)        /* show socket/tun/tap buffer sizes */
-#define D_PS_PROXY           LOGLEV(3, 45, 0)        /* messages related to --port-share option */
-#define D_PF_INFO            LOGLEV(3, 46, 0)        /* packet filter informational messages */
+#define D_PLUGIN             LOGLEV(3, 39, 0)        /* show plugin calls */
+#define D_MANAGEMENT         LOGLEV(3, 40, 0)        /* show --management info */
+#define D_SCHED_EXIT         LOGLEV(3, 41, 0)        /* show arming of scheduled exit */
+#define D_ROUTE_QUOTA        LOGLEV(3, 42, 0)        /* show route quota exceeded messages */
+#define D_OSBUF              LOGLEV(3, 43, 0)        /* show socket/tun/tap buffer sizes */
+#define D_PS_PROXY           LOGLEV(3, 44, 0)        /* messages related to --port-share option */
+#define D_PF_INFO            LOGLEV(3, 45, 0)        /* packet filter informational messages */
 
 #define D_SHOW_PARMS         LOGLEV(4, 50, 0)        /* show all parameters on program initiation */
 #define D_SHOW_OCC           LOGLEV(4, 51, 0)        /* show options compatibility string */
 #define D_MBUF               LOGLEV(4, 54, 0)        /* mbuf.[ch] routines */
 #define D_PACKET_TRUNC_ERR   LOGLEV(4, 55, 0)        /* PACKET_TRUNCATION_CHECK */
 #define D_PF_DROPPED         LOGLEV(4, 56, 0)        /* packet filter dropped a packet */
+#define D_MULTI_DROPPED      LOGLEV(4, 57, 0)        /* show point-to-multipoint packet drops */
 
 #define D_LOG_RW             LOGLEV(5, 0,  0)        /* Print 'R' or 'W' to stdout for read/write */
 
index ab75f6a032d3a628a6f8b3e6408acdfd03eb093e..ddf9f35e240bd9b70891f5d14578e56a5a91787c 100644 (file)
--- a/options.c
+++ b/options.c
@@ -4404,6 +4404,8 @@ add_option (struct options *options,
            options->routes->flags |= RG_REROUTE_GW;
          if (streq (p[j], "local"))
            options->routes->flags |= RG_LOCAL;
+         else if (streq (p[j], "autolocal"))
+           options->routes->flags |= RG_AUTO_LOCAL;
          else if (streq (p[j], "def1"))
            options->routes->flags |= RG_DEF1;
          else if (streq (p[j], "bypass-dhcp"))
diff --git a/route.c b/route.c
index 68b0fa3e287d0e1f34d2bf68cd911c4468f21c0b..8eccbc100d80a815ecf3f601fcd3615b8acd211a 100644 (file)
--- a/route.c
+++ b/route.c
@@ -50,7 +50,7 @@ print_bypass_addresses (const struct route_bypass *rb)
   int i;
   for (i = 0; i < rb->n_bypass; ++i)
     {
-      msg (D_ROUTE_DEBUG, "ROUTE DEBUG: bypass_host_route[%d]=%s",
+      msg (D_ROUTE, "ROUTE: bypass_host_route[%d]=%s",
           i,
           print_in_addr_t (rb->bypass[i], 0, &gc));
     }
@@ -379,7 +379,7 @@ init_route_list (struct route_list *rl,
     }
   else
     {
-      dmsg (D_ROUTE_DEBUG, "ROUTE DEBUG: default_gateway=UNDEF");
+      dmsg (D_ROUTE, "ROUTE: default_gateway=UNDEF");
     }
 
   if (rl->flags & RG_ENABLE)
@@ -531,14 +531,31 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u
        }
       else
        {
-         /* route remote host to original default gateway */
-         if (!(rl->flags & RG_LOCAL))
-           add_route3 (rl->spec.remote_host,
-                       ~0,
-                       rl->spec.net_gateway,
-                       tt,
-                       flags,
-                       es);
+         bool local = BOOL_CAST(rl->flags & RG_LOCAL);
+         if (rl->flags & RG_AUTO_LOCAL) {
+           const int tla = test_local_addr (rl->spec.remote_host);
+           if (tla == TLA_NONLOCAL)
+             {
+               dmsg (D_ROUTE, "ROUTE remote_host is NOT LOCAL");
+               local = false;
+             }
+           else if (tla == TLA_LOCAL)
+             {
+               dmsg (D_ROUTE, "ROUTE remote_host is LOCAL");
+               local = true;
+             }
+         }
+         if (!local)
+           {
+             /* route remote host to original default gateway */
+             add_route3 (rl->spec.remote_host,
+                         ~0,
+                         rl->spec.net_gateway,
+                         tt,
+                         flags,
+                         es);
+             rl->did_local = true;
+           }
 
          /* route DHCP/DNS server traffic through original default gateway */
          add_bypass_routes (&rl->spec.bypass, rl->spec.net_gateway, tt, flags, es);
@@ -595,13 +612,16 @@ undo_redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *
   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);
+      if (rl->did_local)
+       {
+         del_route3 (rl->spec.remote_host,
+                     ~0,
+                     rl->spec.net_gateway,
+                     tt,
+                     flags,
+                     es);
+         rl->did_local = false;
+       }
 
       /* delete special DHCP/DNS bypass route */
       del_bypass_routes (&rl->spec.bypass, rl->spec.net_gateway, tt, flags, es);
@@ -2080,14 +2100,14 @@ netmask_to_netbits (const in_addr_t network, const in_addr_t netmask, int *netbi
 #if defined(WIN32)
 
 static void
-add_host_route_if_nonlocal (struct route_bypass *rb, const in_addr_t addr, const IP_ADAPTER_INFO *dgi)
+add_host_route_if_nonlocal (struct route_bypass *rb, const in_addr_t addr)
 {
-  if (!is_ip_in_adapter_subnet (dgi, addr, NULL) && addr != 0 && addr != ~0)
+  if (test_local_addr(addr) == TLA_NONLOCAL && addr != 0 && addr != ~0)
     add_bypass_address (rb, addr);
 }
 
 static void
-add_host_route_array (struct route_bypass *rb, const IP_ADAPTER_INFO *dgi, const IP_ADDR_STRING *iplist)
+add_host_route_array (struct route_bypass *rb, const IP_ADDR_STRING *iplist)
 {
   while (iplist)
     {
@@ -2095,7 +2115,7 @@ add_host_route_array (struct route_bypass *rb, const IP_ADAPTER_INFO *dgi, const
       const in_addr_t ip = getaddr (GETADDR_HOST_ORDER, iplist->IpAddress.String, 0, &succeed, NULL);
       if (succeed)
        {
-         add_host_route_if_nonlocal (rb, ip, dgi);
+         add_host_route_if_nonlocal (rb, ip);
        }
       iplist = iplist->Next;
     }
@@ -2123,11 +2143,11 @@ get_bypass_addresses (struct route_bypass *rb, const unsigned int flags)
 
       /* Bypass DHCP server address */
       if ((flags & RG_BYPASS_DHCP) && dgi && dgi->DhcpEnabled)
-       add_host_route_array (rb, dgi, &dgi->DhcpServer);
+       add_host_route_array (rb, &dgi->DhcpServer);
 
       /* Bypass DNS server addresses */
       if ((flags & RG_BYPASS_DNS) && pai)
-       add_host_route_array (rb, dgi, &pai->DnsServerList);
+       add_host_route_array (rb, &pai->DnsServerList);
     }
 
   gc_free (&gc);
@@ -2290,3 +2310,54 @@ get_default_gateway_mac_addr (unsigned char *macaddr)
 
 #endif
 #endif /* AUTO_USERID */
+
+/*
+ * Test if addr is reachable via a local interface (return ILA_LOCAL),
+ * or if it needs to be routed via the default gateway (return
+ * ILA_NONLOCAL).  If the target platform doesn't implement this
+ * function, return ILA_NOT_IMPLEMENTED.
+ *
+ * Used by redirect-gateway autolocal feature
+ */
+
+#if defined(WIN32)
+
+int
+test_local_addr (const in_addr_t addr)
+{
+  struct gc_arena gc = gc_new ();
+  const in_addr_t nonlocal_netmask = 0x80000000L; /* routes with netmask <= to this are considered non-local */
+  bool ret = TLA_NONLOCAL;
+
+  /* get full routing table */
+  const MIB_IPFORWARDTABLE *rt = get_windows_routing_table (&gc);
+  if (rt)
+    {
+      int i;
+      for (i = 0; i < rt->dwNumEntries; ++i)
+       {
+         const MIB_IPFORWARDROW *row = &rt->table[i];
+         const in_addr_t net = ntohl (row->dwForwardDest);
+         const in_addr_t mask = ntohl (row->dwForwardMask);
+         if (mask > nonlocal_netmask && (addr & mask) == net)
+           {
+             ret = TLA_LOCAL;
+             break;
+           }
+       }
+    }
+
+  gc_free (&gc);
+  return ret;
+}
+
+#else
+
+
+int
+test_local_addr (const in_addr_t addr)
+{
+  return TLA_NOT_IMPLEMENTED;
+}
+
+#endif
diff --git a/route.h b/route.h
index 27ac6238c2f106f9f4af8b29bdfb90726c4049d3..a2654a2092b58ac1c76119e48db803bf37d8009d 100644 (file)
--- a/route.h
+++ b/route.h
@@ -83,6 +83,7 @@ struct route_option {
 #define RG_BYPASS_DHCP    (1<<3)
 #define RG_BYPASS_DNS     (1<<4)
 #define RG_REROUTE_GW     (1<<5)
+#define RG_AUTO_LOCAL     (1<<6)
 
 struct route_option_list {
   int n;
@@ -105,6 +106,7 @@ struct route_list {
   struct route_special_addr spec;
   unsigned int flags;
   bool did_redirect_default_gateway;
+  bool did_local;
   int n;
   struct route routes[MAX_ROUTES];
 };
@@ -159,6 +161,17 @@ bool is_special_addr (const char *addr_str);
 
 bool get_default_gateway (in_addr_t *ip, in_addr_t *netmask);
 
+/*
+ * Test if addr is reachable via a local interface (return ILA_LOCAL),
+ * or if it needs to be routed via the default gateway (return
+ * ILA_NONLOCAL).  If the current platform doesn't implement this
+ * function, return ILA_NOT_IMPLEMENTED.
+ */
+#define TLA_NOT_IMPLEMENTED 0
+#define TLA_NONLOCAL        1
+#define TLA_LOCAL           2
+int test_local_addr (const in_addr_t addr);
+
 #if AUTO_USERID
 bool get_default_gateway_mac_addr (unsigned char *macaddr);
 #endif
index e98e33050a4b995f8c289146077232b3d69adf2c..6cf35d592ce2656f8e83a248a5c2fcdbe2205a86 100644 (file)
@@ -1,5 +1,5 @@
 dnl define the OpenVPN version
-define(PRODUCT_VERSION,[2.1_rc16])
+define(PRODUCT_VERSION,[2.1_rc16b])
 dnl define the TAP version
 define(PRODUCT_TAP_ID,[tap0901])
 define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])