Browse code

Added new 'autolocal' redirect-gateway flag. When enabled, the OpenVPN 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

james authored on 2009/05/24 18:13:58
Showing 6 changed files
... ...
@@ -79,7 +79,7 @@ typedef unsigned long ptr_type;
79 79
  * the full --push/--pull list.  If you increase it, do so
80 80
  * on both server and client.
81 81
  */
82
-#define TLS_CHANNEL_BUF_SIZE 1024
82
+#define TLS_CHANNEL_BUF_SIZE 2048
83 83
 
84 84
 /*
85 85
  * A sort of pseudo-filename for data provided inline within
... ...
@@ -88,14 +88,13 @@
88 88
 #define D_BACKTRACK          LOGLEV(3, 36, 0)        /* show replay backtracks */
89 89
 #define D_AUTH               LOGLEV(3, 37, 0)        /* show user/pass auth info */
90 90
 #define D_MULTI_LOW          LOGLEV(3, 38, 0)        /* show point-to-multipoint low-freq debug info */
91
-#define D_MULTI_DROPPED      LOGLEV(3, 39, 0)        /* show point-to-multipoint packet drops */
92
-#define D_PLUGIN             LOGLEV(3, 40, 0)        /* show plugin calls */
93
-#define D_MANAGEMENT         LOGLEV(3, 41, 0)        /* show --management info */
94
-#define D_SCHED_EXIT         LOGLEV(3, 42, 0)        /* show arming of scheduled exit */
95
-#define D_ROUTE_QUOTA        LOGLEV(3, 43, 0)        /* show route quota exceeded messages */
96
-#define D_OSBUF              LOGLEV(3, 44, 0)        /* show socket/tun/tap buffer sizes */
97
-#define D_PS_PROXY           LOGLEV(3, 45, 0)        /* messages related to --port-share option */
98
-#define D_PF_INFO            LOGLEV(3, 46, 0)        /* packet filter informational messages */
91
+#define D_PLUGIN             LOGLEV(3, 39, 0)        /* show plugin calls */
92
+#define D_MANAGEMENT         LOGLEV(3, 40, 0)        /* show --management info */
93
+#define D_SCHED_EXIT         LOGLEV(3, 41, 0)        /* show arming of scheduled exit */
94
+#define D_ROUTE_QUOTA        LOGLEV(3, 42, 0)        /* show route quota exceeded messages */
95
+#define D_OSBUF              LOGLEV(3, 43, 0)        /* show socket/tun/tap buffer sizes */
96
+#define D_PS_PROXY           LOGLEV(3, 44, 0)        /* messages related to --port-share option */
97
+#define D_PF_INFO            LOGLEV(3, 45, 0)        /* packet filter informational messages */
99 98
 
100 99
 #define D_SHOW_PARMS         LOGLEV(4, 50, 0)        /* show all parameters on program initiation */
101 100
 #define D_SHOW_OCC           LOGLEV(4, 51, 0)        /* show options compatibility string */
... ...
@@ -104,6 +103,7 @@
104 104
 #define D_MBUF               LOGLEV(4, 54, 0)        /* mbuf.[ch] routines */
105 105
 #define D_PACKET_TRUNC_ERR   LOGLEV(4, 55, 0)        /* PACKET_TRUNCATION_CHECK */
106 106
 #define D_PF_DROPPED         LOGLEV(4, 56, 0)        /* packet filter dropped a packet */
107
+#define D_MULTI_DROPPED      LOGLEV(4, 57, 0)        /* show point-to-multipoint packet drops */
107 108
 
108 109
 #define D_LOG_RW             LOGLEV(5, 0,  0)        /* Print 'R' or 'W' to stdout for read/write */
109 110
 
... ...
@@ -4404,6 +4404,8 @@ add_option (struct options *options,
4404 4404
 	    options->routes->flags |= RG_REROUTE_GW;
4405 4405
 	  if (streq (p[j], "local"))
4406 4406
 	    options->routes->flags |= RG_LOCAL;
4407
+	  else if (streq (p[j], "autolocal"))
4408
+	    options->routes->flags |= RG_AUTO_LOCAL;
4407 4409
 	  else if (streq (p[j], "def1"))
4408 4410
 	    options->routes->flags |= RG_DEF1;
4409 4411
 	  else if (streq (p[j], "bypass-dhcp"))
... ...
@@ -50,7 +50,7 @@ print_bypass_addresses (const struct route_bypass *rb)
50 50
   int i;
51 51
   for (i = 0; i < rb->n_bypass; ++i)
52 52
     {
53
-      msg (D_ROUTE_DEBUG, "ROUTE DEBUG: bypass_host_route[%d]=%s",
53
+      msg (D_ROUTE, "ROUTE: bypass_host_route[%d]=%s",
54 54
 	   i,
55 55
 	   print_in_addr_t (rb->bypass[i], 0, &gc));
56 56
     }
... ...
@@ -379,7 +379,7 @@ init_route_list (struct route_list *rl,
379 379
     }
380 380
   else
381 381
     {
382
-      dmsg (D_ROUTE_DEBUG, "ROUTE DEBUG: default_gateway=UNDEF");
382
+      dmsg (D_ROUTE, "ROUTE: default_gateway=UNDEF");
383 383
     }
384 384
 
385 385
   if (rl->flags & RG_ENABLE)
... ...
@@ -531,14 +531,31 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u
531 531
 	}
532 532
       else
533 533
 	{
534
-	  /* route remote host to original default gateway */
535
-	  if (!(rl->flags & RG_LOCAL))
536
-	    add_route3 (rl->spec.remote_host,
537
-			~0,
538
-			rl->spec.net_gateway,
539
-			tt,
540
-			flags,
541
-			es);
534
+	  bool local = BOOL_CAST(rl->flags & RG_LOCAL);
535
+	  if (rl->flags & RG_AUTO_LOCAL) {
536
+	    const int tla = test_local_addr (rl->spec.remote_host);
537
+	    if (tla == TLA_NONLOCAL)
538
+	      {
539
+		dmsg (D_ROUTE, "ROUTE remote_host is NOT LOCAL");
540
+		local = false;
541
+	      }
542
+	    else if (tla == TLA_LOCAL)
543
+	      {
544
+		dmsg (D_ROUTE, "ROUTE remote_host is LOCAL");
545
+		local = true;
546
+	      }
547
+	  }
548
+	  if (!local)
549
+	    {
550
+	      /* route remote host to original default gateway */
551
+	      add_route3 (rl->spec.remote_host,
552
+			  ~0,
553
+			  rl->spec.net_gateway,
554
+			  tt,
555
+			  flags,
556
+			  es);
557
+	      rl->did_local = true;
558
+	    }
542 559
 
543 560
 	  /* route DHCP/DNS server traffic through original default gateway */
544 561
 	  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 *
595 595
   if (rl->did_redirect_default_gateway)
596 596
     {
597 597
       /* delete remote host route */
598
-      if (!(rl->flags & RG_LOCAL))
599
-	del_route3 (rl->spec.remote_host,
600
-		    ~0,
601
-		    rl->spec.net_gateway,
602
-		    tt,
603
-		    flags,
604
-		    es);
598
+      if (rl->did_local)
599
+	{
600
+	  del_route3 (rl->spec.remote_host,
601
+		      ~0,
602
+		      rl->spec.net_gateway,
603
+		      tt,
604
+		      flags,
605
+		      es);
606
+	  rl->did_local = false;
607
+	}
605 608
 
606 609
       /* delete special DHCP/DNS bypass route */
607 610
       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
2080 2080
 #if defined(WIN32)
2081 2081
 
2082 2082
 static void
2083
-add_host_route_if_nonlocal (struct route_bypass *rb, const in_addr_t addr, const IP_ADAPTER_INFO *dgi)
2083
+add_host_route_if_nonlocal (struct route_bypass *rb, const in_addr_t addr)
2084 2084
 {
2085
-  if (!is_ip_in_adapter_subnet (dgi, addr, NULL) && addr != 0 && addr != ~0)
2085
+  if (test_local_addr(addr) == TLA_NONLOCAL && addr != 0 && addr != ~0)
2086 2086
     add_bypass_address (rb, addr);
2087 2087
 }
2088 2088
 
2089 2089
 static void
2090
-add_host_route_array (struct route_bypass *rb, const IP_ADAPTER_INFO *dgi, const IP_ADDR_STRING *iplist)
2090
+add_host_route_array (struct route_bypass *rb, const IP_ADDR_STRING *iplist)
2091 2091
 {
2092 2092
   while (iplist)
2093 2093
     {
... ...
@@ -2095,7 +2115,7 @@ add_host_route_array (struct route_bypass *rb, const IP_ADAPTER_INFO *dgi, const
2095 2095
       const in_addr_t ip = getaddr (GETADDR_HOST_ORDER, iplist->IpAddress.String, 0, &succeed, NULL);
2096 2096
       if (succeed)
2097 2097
 	{
2098
-	  add_host_route_if_nonlocal (rb, ip, dgi);
2098
+	  add_host_route_if_nonlocal (rb, ip);
2099 2099
 	}
2100 2100
       iplist = iplist->Next;
2101 2101
     }
... ...
@@ -2123,11 +2143,11 @@ get_bypass_addresses (struct route_bypass *rb, const unsigned int flags)
2123 2123
 
2124 2124
       /* Bypass DHCP server address */
2125 2125
       if ((flags & RG_BYPASS_DHCP) && dgi && dgi->DhcpEnabled)
2126
-	add_host_route_array (rb, dgi, &dgi->DhcpServer);
2126
+	add_host_route_array (rb, &dgi->DhcpServer);
2127 2127
 
2128 2128
       /* Bypass DNS server addresses */
2129 2129
       if ((flags & RG_BYPASS_DNS) && pai)
2130
-	add_host_route_array (rb, dgi, &pai->DnsServerList);
2130
+	add_host_route_array (rb, &pai->DnsServerList);
2131 2131
     }
2132 2132
 
2133 2133
   gc_free (&gc);
... ...
@@ -2290,3 +2310,54 @@ get_default_gateway_mac_addr (unsigned char *macaddr)
2290 2290
 
2291 2291
 #endif
2292 2292
 #endif /* AUTO_USERID */
2293
+
2294
+/*
2295
+ * Test if addr is reachable via a local interface (return ILA_LOCAL),
2296
+ * or if it needs to be routed via the default gateway (return
2297
+ * ILA_NONLOCAL).  If the target platform doesn't implement this
2298
+ * function, return ILA_NOT_IMPLEMENTED.
2299
+ *
2300
+ * Used by redirect-gateway autolocal feature
2301
+ */
2302
+
2303
+#if defined(WIN32)
2304
+
2305
+int
2306
+test_local_addr (const in_addr_t addr)
2307
+{
2308
+  struct gc_arena gc = gc_new ();
2309
+  const in_addr_t nonlocal_netmask = 0x80000000L; /* routes with netmask <= to this are considered non-local */
2310
+  bool ret = TLA_NONLOCAL;
2311
+
2312
+  /* get full routing table */
2313
+  const MIB_IPFORWARDTABLE *rt = get_windows_routing_table (&gc);
2314
+  if (rt)
2315
+    {
2316
+      int i;
2317
+      for (i = 0; i < rt->dwNumEntries; ++i)
2318
+	{
2319
+	  const MIB_IPFORWARDROW *row = &rt->table[i];
2320
+	  const in_addr_t net = ntohl (row->dwForwardDest);
2321
+	  const in_addr_t mask = ntohl (row->dwForwardMask);
2322
+	  if (mask > nonlocal_netmask && (addr & mask) == net)
2323
+	    {
2324
+	      ret = TLA_LOCAL;
2325
+	      break;
2326
+	    }
2327
+	}
2328
+    }
2329
+
2330
+  gc_free (&gc);
2331
+  return ret;
2332
+}
2333
+
2334
+#else
2335
+
2336
+
2337
+int
2338
+test_local_addr (const in_addr_t addr)
2339
+{
2340
+  return TLA_NOT_IMPLEMENTED;
2341
+}
2342
+
2343
+#endif
... ...
@@ -83,6 +83,7 @@ struct route_option {
83 83
 #define RG_BYPASS_DHCP    (1<<3)
84 84
 #define RG_BYPASS_DNS     (1<<4)
85 85
 #define RG_REROUTE_GW     (1<<5)
86
+#define RG_AUTO_LOCAL     (1<<6)
86 87
 
87 88
 struct route_option_list {
88 89
   int n;
... ...
@@ -105,6 +106,7 @@ struct route_list {
105 105
   struct route_special_addr spec;
106 106
   unsigned int flags;
107 107
   bool did_redirect_default_gateway;
108
+  bool did_local;
108 109
   int n;
109 110
   struct route routes[MAX_ROUTES];
110 111
 };
... ...
@@ -159,6 +161,17 @@ bool is_special_addr (const char *addr_str);
159 159
 
160 160
 bool get_default_gateway (in_addr_t *ip, in_addr_t *netmask);
161 161
 
162
+/*
163
+ * Test if addr is reachable via a local interface (return ILA_LOCAL),
164
+ * or if it needs to be routed via the default gateway (return
165
+ * ILA_NONLOCAL).  If the current platform doesn't implement this
166
+ * function, return ILA_NOT_IMPLEMENTED.
167
+ */
168
+#define TLA_NOT_IMPLEMENTED 0
169
+#define TLA_NONLOCAL        1
170
+#define TLA_LOCAL           2
171
+int test_local_addr (const in_addr_t addr);
172
+
162 173
 #if AUTO_USERID
163 174
 bool get_default_gateway_mac_addr (unsigned char *macaddr);
164 175
 #endif
... ...
@@ -1,5 +1,5 @@
1 1
 dnl define the OpenVPN version
2
-define(PRODUCT_VERSION,[2.1_rc16])
2
+define(PRODUCT_VERSION,[2.1_rc16b])
3 3
 dnl define the TAP version
4 4
 define(PRODUCT_TAP_ID,[tap0901])
5 5
 define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])