Browse code

Merge remote branch SVN 2.1 into the git tree

Hopefully the last SVN merge we need to do, as these merges are getting
more and more difficult. Most of the files had minor changes, but due to
the CRLF unification patch (commit 6b2883a637fe73492) we got an increased
number of conflicts. In addition inclusion of IPv6 support makes the
creates a lot of merge issues in route.c and socket.c

This merge also reverts commit 7c18c6353904f8c6e7 which merged
add_bypass_address() into add_host_route_if_nonlocal(). However the SVN
tree began to use add_bypass_address() another place, where at first glance
it did not be appropriate to use add_host_route_if_nonlocal().

This merge has gone through a 'make check' without any errors, but have
not been tested more thoroughly yet.

Conflicts:
ChangeLog
INSTALL
INSTALL-win32.txt
Makefile.am
acinclude.m4
base64.c
buffer.c
buffer.h
common.h
configure.ac
contrib/pull-resolv-conf/client.down
contrib/pull-resolv-conf/client.up
crypto.c
cryptoapi.c
easy-rsa/2.0/Makefile
easy-rsa/2.0/README
easy-rsa/2.0/build-ca
easy-rsa/2.0/build-dh
easy-rsa/2.0/build-inter
easy-rsa/2.0/build-key
easy-rsa/2.0/build-key-pass
easy-rsa/2.0/build-key-pkcs12
easy-rsa/2.0/build-key-server
easy-rsa/2.0/build-req
easy-rsa/2.0/build-req-pass
easy-rsa/2.0/clean-all
easy-rsa/2.0/inherit-inter
easy-rsa/2.0/list-crl
easy-rsa/2.0/pkitool
easy-rsa/2.0/revoke-full
easy-rsa/2.0/sign-req
easy-rsa/2.0/vars
easy-rsa/2.0/whichopensslcnf
easy-rsa/Windows/build-ca-pass.bat
easy-rsa/Windows/build-key-pass.bat
easy-rsa/Windows/build-key-server-pass.bat
easy-rsa/Windows/init-config.bat
easy-rsa/Windows/vars.bat.sample
error.c
error.h
forward.c
helper.c
httpdigest.c
httpdigest.h
ieproxy.c
init.c
init.h
install-win32/Makefile.am
install-win32/makeopenvpn
install-win32/openssl/openssl097.patch
install-win32/openssl/openssl098.patch
install-win32/openvpn.nsi
list.c
list.h
manage.c
manage.h
management/management-notes.txt
mbuf.c
mbuf.h
misc.c
misc.h
mroute.c
mroute.h
msvc/autodefs.h.in
msvc/config.py
msvc/msvc.mak
mtcp.c
mudp.c
multi.c
multi.h
occ.c
openvpn-plugin.h
openvpn.8
openvpn.h
options.c
options.h
otime.c
otime.h
perf.c
pf.c
ping.c
pkcs11.c
plugin.c
plugin.h
plugin/auth-pam/README
plugin/auth-pam/auth-pam.c
pool.c
pool.h
proto.h
proxy.c
ps.c
push.c
reliable.c
route.c
route.h
sample-config-files/firewall.sh
sample-scripts/bridge-start
sample-scripts/bridge-stop
sample-scripts/openvpn.init
sample-scripts/verify-cn
schedule.c
schedule.h
service-win32/openvpnserv.c
sig.c
socket.c
socket.h
socks.c
socks.h
ssl.c
ssl.h
status.c
syshead.h
tap-win32/SOURCES.in
tap-win32/common.h
tap-win32/proto.h
tap-win32/tapdrvr.c
tap-win32/types.h
tun.c
tun.h
version.m4
win/autodefs.h.in
win/build.py
win/build_all.py
win/build_ddk.py
win/build_exe.py
win/config.py
win/config_all.py
win/config_tap.py
win/config_ti.py
win/js.py
win/make_dist.py
win/msvc.mak.in
win/settings.in
win/show.py
win/sign.py
win/tap_span.py
win/wb.py
win32.c
win32.h

Signed-off-by: David Sommerseth <davids@redhat.com>
Reviewed-by: Gert Doering <gert@greenie.muc.de>
Reviewed-by: James Yonan <james@openvpn.net>
Reviewed-by: Adriaan de Jong <dejong@fox-it.com>

David Sommerseth authored on 2011/07/25 08:44:27
Showing 18 changed files
... ...
@@ -41,7 +41,11 @@
41 41
 
42 42
 static char base64_chars[] = 
43 43
     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
44
-
44
+/*
45
+ * base64 encode input data of length size to malloced
46
+ * buffer which is returned as *str.  Returns string
47
+ * length of *str.
48
+ */
45 49
 int 
46 50
 base64_encode(const void *data, int size, char **str)
47 51
 {
... ...
@@ -115,7 +119,11 @@ token_decode(const char *token)
115 115
 	return DECODE_ERROR;
116 116
     return (marker << 24) | val;
117 117
 }
118
-
118
+/*
119
+ * Decode base64 str, outputting data to buffer
120
+ * at data of length size.  Return length of
121
+ * decoded data written or -1 on error or overflow.
122
+ */
119 123
 int
120 124
 base64_decode(const char *str, void *data, int size)
121 125
 {
... ...
@@ -1006,7 +1006,7 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
1006 1006
   if (!c->options.passtos)
1007 1007
     flags &= ~PIPV4_PASSTOS;
1008 1008
 #endif
1009
-  if (!c->options.route_gateway_via_dhcp || !route_list_default_gateway_needed (c->c1.route_list))
1009
+  if (!c->options.route_gateway_via_dhcp || !route_list_vpn_gateway_needed (c->c1.route_list))
1010 1010
     flags &= ~PIPV4_EXTRACT_DHCP_ROUTER;
1011 1011
 
1012 1012
   if (buf->len > 0)
... ...
@@ -1047,7 +1047,7 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
1047 1047
 		{
1048 1048
 		  const in_addr_t dhcp_router = dhcp_extract_router_msg (&ipbuf);
1049 1049
 		  if (dhcp_router)
1050
-		    route_list_add_default_gateway (c->c1.route_list, c->c2.es, dhcp_router);
1050
+		    route_list_add_vpn_gateway (c->c1.route_list, c->c2.es, dhcp_router);
1051 1051
 		}
1052 1052
 	    }
1053 1053
 	}
... ...
@@ -199,6 +199,90 @@ management_callback_http_proxy_fallback_cmd (void *arg, const char *server, cons
199 199
 
200 200
 #endif
201 201
 
202
+#if MANAGEMENT_QUERY_REMOTE
203
+
204
+static bool
205
+management_callback_remote_cmd (void *arg, const char **p)
206
+{
207
+  struct context *c = (struct context *) arg;
208
+  struct connection_entry *ce = &c->options.ce;
209
+  int ret = false;
210
+  if (p[1] && ((ce->flags>>CE_MAN_QUERY_REMOTE_SHIFT)&CE_MAN_QUERY_REMOTE_MASK) == CE_MAN_QUERY_REMOTE_QUERY)
211
+    {
212
+      int flags = 0;
213
+      if (!strcmp(p[1], "ACCEPT"))
214
+	{
215
+	  flags = CE_MAN_QUERY_REMOTE_ACCEPT;
216
+	  ret = true;
217
+	}
218
+      else if (!strcmp(p[1], "SKIP"))
219
+	{
220
+	  flags = CE_MAN_QUERY_REMOTE_SKIP;
221
+	  ret = true;
222
+	}
223
+      else if (!strcmp(p[1], "MOD") && p[2] && p[3])
224
+	{
225
+	  const int port = atoi(p[3]);
226
+	  if (strlen(p[2]) < RH_HOST_LEN && legal_ipv4_port(port))
227
+	    {
228
+	      struct remote_host_store *rhs = c->options.rh_store;
229
+	      if (!rhs)
230
+		{
231
+		  ALLOC_OBJ_CLEAR_GC (rhs, struct remote_host_store, &c->options.gc);
232
+		  c->options.rh_store = rhs;
233
+		}
234
+	      strncpynt(rhs->host, p[2], RH_HOST_LEN);
235
+	      ce->remote = rhs->host;
236
+	      ce->remote_port = port;
237
+	      flags = CE_MAN_QUERY_REMOTE_MOD;
238
+	      ret = true;
239
+	    }
240
+	}
241
+      if (ret)
242
+	{
243
+	  ce->flags &= ~(CE_MAN_QUERY_REMOTE_MASK<<CE_MAN_QUERY_REMOTE_SHIFT);
244
+	  ce->flags |= ((flags&CE_MAN_QUERY_REMOTE_MASK)<<CE_MAN_QUERY_REMOTE_SHIFT);
245
+	}
246
+    }
247
+  return ret;
248
+}
249
+
250
+static bool
251
+ce_management_query_remote (struct context *c, const char *remote_ip_hint)
252
+{
253
+  struct gc_arena gc = gc_new ();
254
+  volatile struct connection_entry *ce = &c->options.ce;
255
+  int ret = true;
256
+  update_time();
257
+  if (management)
258
+    {
259
+      struct buffer out = alloc_buf_gc (256, &gc);
260
+      buf_printf (&out, ">REMOTE:%s,%d,%s", np(ce->remote), ce->remote_port, proto2ascii(ce->proto, false));
261
+      management_notify_generic(management, BSTR (&out));
262
+      ce->flags &= ~(CE_MAN_QUERY_REMOTE_MASK<<CE_MAN_QUERY_REMOTE_SHIFT);
263
+      ce->flags |= (CE_MAN_QUERY_REMOTE_QUERY<<CE_MAN_QUERY_REMOTE_SHIFT);
264
+      while (((ce->flags>>CE_MAN_QUERY_REMOTE_SHIFT) & CE_MAN_QUERY_REMOTE_MASK) == CE_MAN_QUERY_REMOTE_QUERY)
265
+	{
266
+	  management_event_loop_n_seconds (management, 1);
267
+	  if (IS_SIG (c))
268
+	    {
269
+	      ret = false;
270
+	      break;
271
+	    }
272
+	}
273
+    }
274
+  {
275
+    const int flags = ((ce->flags>>CE_MAN_QUERY_REMOTE_SHIFT) & CE_MAN_QUERY_REMOTE_MASK);
276
+    if (flags == CE_MAN_QUERY_REMOTE_ACCEPT && remote_ip_hint)
277
+      ce->remote = remote_ip_hint;
278
+    ret = (flags != CE_MAN_QUERY_REMOTE_SKIP);
279
+  }
280
+  gc_free (&gc);
281
+  return ret;
282
+}
283
+
284
+#endif
285
+
202 286
 /*
203 287
  * Initialize and possibly randomize connection list.
204 288
  */
... ...
@@ -313,6 +397,15 @@ next_connection_entry (struct context *c)
313 313
 
314 314
 	c->options.ce = *ce;
315 315
 
316
+#if MANAGEMENT_QUERY_REMOTE
317
+	if (ce_defined && management && management_query_remote_enabled(management))
318
+	  {
319
+	    /* allow management interface to override connection entry details */
320
+	    ce_defined = ce_management_query_remote(c, remote_ip_hint);
321
+	    if (IS_SIG (c))
322
+	      break;
323
+	  } else
324
+#endif
316 325
 	if (remote_ip_hint)
317 326
 	  c->options.ce.remote = remote_ip_hint;
318 327
 
... ...
@@ -343,7 +436,13 @@ init_query_passwords (struct context *c)
343 343
 #if P2MP
344 344
   /* Auth user/pass input */
345 345
   if (c->options.auth_user_pass_file)
346
-    auth_user_pass_setup (c->options.auth_user_pass_file);
346
+    {
347
+#ifdef ENABLE_CLIENT_CR
348
+      auth_user_pass_setup (c->options.auth_user_pass_file, &c->options.sc_info);
349
+#else
350
+      auth_user_pass_setup (c->options.auth_user_pass_file, NULL);
351
+#endif
352
+    }
347 353
 #endif
348 354
 }
349 355
 
... ...
@@ -598,21 +697,9 @@ init_static (void)
598 598
 
599 599
 #ifdef TEST_GET_DEFAULT_GATEWAY
600 600
   {
601
-    struct gc_arena gc = gc_new ();
602
-    in_addr_t addr;
603
-    char macaddr[6];
604
-
605
-    if (get_default_gateway(&addr, NULL))
606
-      msg (M_INFO, "GW %s", print_in_addr_t(addr, 0, &gc));
607
-    else
608
-      msg (M_INFO, "GDG ERROR");
609
-
610
-    if (get_default_gateway_mac_addr(macaddr))
611
-      msg (M_INFO, "MAC %s", format_hex_ex (macaddr, 6, 0, 1, ":", &gc));
612
-    else
613
-      msg (M_INFO, "GDGMA ERROR");
614
-
615
-    gc_free (&gc);
601
+    struct route_gateway_info rgi;
602
+    get_default_gateway(&rgi);
603
+    print_default_gateway(M_INFO, &rgi);
616 604
     return false;
617 605
   }
618 606
 #endif
... ...
@@ -1241,7 +1328,7 @@ do_route (const struct options *options,
1241 1241
   if (!options->route_noexec && ( route_list || route_ipv6_list ) )
1242 1242
     {
1243 1243
       add_routes (route_list, route_ipv6_list, tt, ROUTE_OPTION_FLAGS (options), es);
1244
-      setenv_int (es, "redirect_gateway", route_list->did_redirect_default_gateway);
1244
+      setenv_int (es, "redirect_gateway", route_did_redirect_default_gateway(route_list));
1245 1245
     }
1246 1246
 #ifdef ENABLE_MANAGEMENT
1247 1247
   if (management)
... ...
@@ -2154,6 +2241,10 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
2154 2154
   to.x509_track = options->x509_track;
2155 2155
 #endif
2156 2156
 
2157
+#ifdef ENABLE_CLIENT_CR
2158
+  to.sci = &options->sc_info;
2159
+#endif
2160
+
2157 2161
   /* TLS handshake authentication (--tls-auth) */
2158 2162
   if (options->tls_auth_file)
2159 2163
     {
... ...
@@ -3046,6 +3137,9 @@ init_management_callback_p2p (struct context *c)
3046 3046
 #if HTTP_PROXY_FALLBACK
3047 3047
       cb.http_proxy_fallback_cmd = management_callback_http_proxy_fallback_cmd;
3048 3048
 #endif
3049
+#if MANAGEMENT_QUERY_REMOTE
3050
+      cb.remote_cmd = management_callback_remote_cmd;
3051
+#endif
3049 3052
       management_set_callback (management, &cb);
3050 3053
     }
3051 3054
 #endif
... ...
@@ -86,6 +86,9 @@ man_help ()
86 86
   msg (M_CLIENT, "                         where action is reply string.");
87 87
   msg (M_CLIENT, "net                    : (Windows only) Show network info and routing table.");
88 88
   msg (M_CLIENT, "password type p        : Enter password p for a queried OpenVPN password.");
89
+#if MANAGEMENT_QUERY_REMOTE
90
+  msg (M_CLIENT, "remote type [host port] : Override remote directive, type=ACCEPT|MOD|SKIP.");
91
+#endif
89 92
   msg (M_CLIENT, "pid                    : Show process ID of the current OpenVPN process.");
90 93
 #ifdef ENABLE_PKCS11
91 94
   msg (M_CLIENT, "pkcs11-id-count        : Get number of available PKCS#11 identities.");
... ...
@@ -606,25 +609,19 @@ man_up_finalize (struct management *man)
606 606
 {
607 607
   switch (man->connection.up_query_mode)
608 608
     {
609
-    case UP_QUERY_DISABLED:
610
-      man->connection.up_query.defined = false;
611
-      break;
612 609
     case UP_QUERY_USER_PASS:
613
-      if (strlen (man->connection.up_query.username) && strlen (man->connection.up_query.password))
614
-	man->connection.up_query.defined = true;
615
-      break;
610
+      if (!strlen (man->connection.up_query.username))
611
+	break;
612
+      /* fall through */
616 613
     case UP_QUERY_PASS:
617
-      if (strlen (man->connection.up_query.password))
618
-	man->connection.up_query.defined = true;
619
-      break;
620 614
     case UP_QUERY_NEED_OK:
621
-      if (strlen (man->connection.up_query.password))
622
-	man->connection.up_query.defined = true;
623
-      break;
624 615
     case UP_QUERY_NEED_STR:
625 616
       if (strlen (man->connection.up_query.password))
626 617
 	man->connection.up_query.defined = true;
627 618
       break;
619
+    case UP_QUERY_DISABLED:
620
+      man->connection.up_query.defined = false;
621
+      break;
628 622
     default:
629 623
       ASSERT (0);
630 624
     }
... ...
@@ -665,16 +662,17 @@ man_query_user_pass (struct management *man,
665 665
 static void
666 666
 man_query_username (struct management *man, const char *type, const char *string)
667 667
 {
668
-  const bool needed = (man->connection.up_query_mode == UP_QUERY_USER_PASS && man->connection.up_query_type);
668
+  const bool needed = ((man->connection.up_query_mode == UP_QUERY_USER_PASS
669
+			) && man->connection.up_query_type);
669 670
   man_query_user_pass (man, type, string, needed, "username", man->connection.up_query.username, USER_PASS_LEN);
670 671
 }
671 672
 
672 673
 static void
673 674
 man_query_password (struct management *man, const char *type, const char *string)
674 675
 {
675
-  const bool needed = ((man->connection.up_query_mode == UP_QUERY_USER_PASS
676
-			|| man->connection.up_query_mode == UP_QUERY_PASS)
677
-		       && man->connection.up_query_type);
676
+  const bool needed = ((man->connection.up_query_mode == UP_QUERY_PASS
677
+			|| man->connection.up_query_mode == UP_QUERY_USER_PASS
678
+			) && man->connection.up_query_type);
678 679
   if (!string[0]) /* allow blank passwords to be passed through using the blank_up tag */
679 680
     string = blank_up;
680 681
   man_query_user_pass (man, type, string, needed, "password", man->connection.up_query.password, USER_PASS_LEN);
... ...
@@ -1090,6 +1088,31 @@ man_http_proxy_fallback (struct management *man, const char *server, const char
1090 1090
 
1091 1091
 #endif
1092 1092
 
1093
+#if MANAGEMENT_QUERY_REMOTE
1094
+
1095
+static void
1096
+man_remote (struct management *man, const char **p)
1097
+{
1098
+  if (man->persist.callback.remote_cmd)
1099
+    {
1100
+      const bool status = (*man->persist.callback.remote_cmd)(man->persist.callback.arg, p);
1101
+      if (status)
1102
+	{
1103
+	  msg (M_CLIENT, "SUCCESS: remote command succeeded");
1104
+	}
1105
+      else
1106
+	{
1107
+	  msg (M_CLIENT, "ERROR: remote command failed");
1108
+	}
1109
+    }
1110
+  else
1111
+    {
1112
+      msg (M_CLIENT, "ERROR: The remote command is not supported by the current daemon mode");
1113
+    }
1114
+}
1115
+
1116
+#endif
1117
+
1093 1118
 static void
1094 1119
 man_dispatch_command (struct management *man, struct status_output *so, const char **p, const int nparms)
1095 1120
 {
... ...
@@ -1319,6 +1342,13 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch
1319 1319
       man_http_proxy_fallback (man, NULL, NULL, NULL);
1320 1320
     }
1321 1321
 #endif
1322
+#if MANAGEMENT_QUERY_REMOTE
1323
+  else if (streq (p[0], "remote"))
1324
+    {
1325
+      if (man_need (man, p, 1, MN_AT_LEAST))
1326
+	man_remote (man, p);
1327
+    }
1328
+#endif
1322 1329
 #if 1
1323 1330
   else if (streq (p[0], "test"))
1324 1331
     {
... ...
@@ -2339,6 +2369,12 @@ management_notify(struct management *man, const char *severity, const char *type
2339 2339
   msg (M_CLIENT, ">NOTIFY:%s,%s,%s", severity, type, text);
2340 2340
 }
2341 2341
 
2342
+void
2343
+management_notify_generic (struct management *man, const char *str)
2344
+{
2345
+  msg (M_CLIENT, "%s", str);
2346
+}
2347
+
2342 2348
 #ifdef MANAGEMENT_DEF_AUTH
2343 2349
 
2344 2350
 static bool
... ...
@@ -2843,7 +2879,8 @@ bool
2843 2843
 management_query_user_pass (struct management *man,
2844 2844
 			    struct user_pass *up,
2845 2845
 			    const char *type,
2846
-			    const unsigned int flags)
2846
+			    const unsigned int flags,
2847
+			    const char *static_challenge)
2847 2848
 {
2848 2849
   struct gc_arena gc = gc_new ();
2849 2850
   bool ret = false;
... ...
@@ -2856,7 +2893,9 @@ management_query_user_pass (struct management *man,
2856 2856
       const char *alert_type = NULL;
2857 2857
       const char *prefix = NULL;
2858 2858
       unsigned int up_query_mode = 0;
2859
-
2859
+#ifdef ENABLE_CLIENT_CR
2860
+      const char *sc = NULL;
2861
+#endif
2860 2862
       ret = true;
2861 2863
       man->persist.standalone_disabled = false; /* This is so M_CLIENT messages will be correctly passed through msg() */
2862 2864
       man->persist.special_state_msg = NULL;
... ...
@@ -2886,6 +2925,10 @@ management_query_user_pass (struct management *man,
2886 2886
 	  up_query_mode = UP_QUERY_USER_PASS;
2887 2887
 	  prefix = "PASSWORD";
2888 2888
 	  alert_type = "username/password";
2889
+#ifdef ENABLE_CLIENT_CR
2890
+	  if (static_challenge)
2891
+	    sc = static_challenge;
2892
+#endif
2889 2893
 	}
2890 2894
       buf_printf (&alert_msg, ">%s:Need '%s' %s",
2891 2895
 		  prefix,
... ...
@@ -2895,6 +2938,13 @@ management_query_user_pass (struct management *man,
2895 2895
       if (flags & (GET_USER_PASS_NEED_OK | GET_USER_PASS_NEED_STR))
2896 2896
 	buf_printf (&alert_msg, " MSG:%s", up->username);
2897 2897
 
2898
+#ifdef ENABLE_CLIENT_CR
2899
+      if (sc)
2900
+	buf_printf (&alert_msg, " SC:%d,%s",
2901
+		    BOOL_CAST(flags & GET_USER_PASS_STATIC_CHALLENGE_ECHO),
2902
+		    sc);
2903
+#endif
2904
+
2898 2905
       man_wait_for_client_connection (man, &signal_received, 0, MWCC_PASSWORD_WAIT);
2899 2906
       if (signal_received)
2900 2907
 	ret = false;
... ...
@@ -2908,7 +2958,7 @@ management_query_user_pass (struct management *man,
2908 2908
 	  man->connection.up_query_mode = up_query_mode;
2909 2909
 	  man->connection.up_query_type = type;
2910 2910
 
2911
-	  /* run command processing event loop until we get our username/password */
2911
+	  /* run command processing event loop until we get our username/password/response */
2912 2912
 	  do
2913 2913
 	    {
2914 2914
 	      man_standalone_event_loop (man, &signal_received, 0);
... ...
@@ -174,6 +174,9 @@ struct management_callback
174 174
 #if HTTP_PROXY_FALLBACK
175 175
   bool (*http_proxy_fallback_cmd) (void *arg, const char *server, const char *port, const char *flags);
176 176
 #endif
177
+#if MANAGEMENT_QUERY_REMOTE
178
+  bool (*remote_cmd) (void *arg, const char **p);
179
+#endif
177 180
 };
178 181
 
179 182
 /*
... ...
@@ -333,6 +336,9 @@ struct management *management_init (void);
333 333
 # define MF_EXTERNAL_KEY    (1<<9)
334 334
 #endif
335 335
 #define MF_UP_DOWN          (1<<10)
336
+#if MANAGEMENT_QUERY_REMOTE
337
+#define MF_QUERY_REMOTE     (1<<11)
338
+#endif
336 339
 
337 340
 bool management_open (struct management *man,
338 341
 		      const char *addr,
... ...
@@ -365,7 +371,11 @@ void management_set_callback (struct management *man,
365 365
 
366 366
 void management_clear_callback (struct management *man);
367 367
 
368
-bool management_query_user_pass (struct management *man, struct user_pass *up, const char *type, const unsigned int flags);
368
+bool management_query_user_pass (struct management *man,
369
+				 struct user_pass *up,
370
+				 const char *type,
371
+				 const unsigned int flags,
372
+				 const char *static_challenge);
369 373
 
370 374
 bool management_should_daemonize (struct management *man);
371 375
 bool management_would_hold (struct management *man);
... ...
@@ -377,6 +387,8 @@ void management_up_down(struct management *man, const char *updown, const struct
377 377
 
378 378
 void management_notify(struct management *man, const char *severity, const char *type, const char *text);
379 379
 
380
+void management_notify_generic (struct management *man, const char *str);
381
+
380 382
 #ifdef MANAGEMENT_DEF_AUTH
381 383
 void management_notify_client_needing_auth (struct management *management,
382 384
 					    const unsigned int auth_id,
... ...
@@ -415,6 +427,14 @@ management_query_user_pass_enabled (const struct management *man)
415 415
   return BOOL_CAST(man->settings.flags & MF_QUERY_PASSWORDS);
416 416
 }
417 417
 
418
+#if MANAGEMENT_QUERY_REMOTE
419
+static inline bool
420
+management_query_remote_enabled (const struct management *man)
421
+{
422
+  return BOOL_CAST(man->settings.flags & MF_QUERY_REMOTE);
423
+}
424
+#endif
425
+
418 426
 #ifdef MANAGEMENT_PF
419 427
 static inline bool
420 428
 management_enable_pf (const struct management *man)
... ...
@@ -687,6 +687,38 @@ the 10.0.0.0/8 netblock is allowed: 10.10.0.1.  Also, the client
687 687
 may not interact with external IP addresses using an "unknown"
688 688
 protocol (i.e. one that is not IPv4 or ARP).
689 689
 
690
+COMMAND -- remote  (OpenVPN AS 2.1.5/OpenVPN 2.3 or higher)
691
+--------------------------------------------
692
+
693
+Provide remote host/port in response to a >REMOTE notification
694
+(client only).  Requires that the --management-query-remote
695
+directive is used.
696
+
697
+  remote ACTION [HOST PORT]
698
+
699
+The "remote" command should only be given in response to a >REMOTE
700
+notification.  For example, the following >REMOTE notification
701
+indicates that the client config file would ordinarily connect
702
+to vpn.example.com port 1194 (UDP):
703
+
704
+  >REMOTE:vpn.example.com,1194,udp
705
+
706
+Now, suppose we want to override the host and port, connecting
707
+instead to vpn.otherexample.com port 1234.  After receiving
708
+the above notification, use this command:
709
+
710
+  remote MOD vpn.otherexample.com 1234
711
+
712
+To accept the same host and port as the client would ordinarily
713
+have connected to, use this command:
714
+
715
+  remote ACCEPT
716
+
717
+To skip the current connection entry and advance to the next one,
718
+use this command:
719
+
720
+  remote SKIP
721
+
690 722
 OUTPUT FORMAT
691 723
 -------------
692 724
 
... ...
@@ -836,3 +868,113 @@ mappings, when not in single quotations:
836 836
          interpret it as enclosing a parameter.
837 837
 \[SPACE] Pass a literal space or tab character, don't
838 838
          interpret it as a parameter delimiter.
839
+
840
+Challenge/Response Protocol
841
+---------------------------
842
+
843
+The OpenVPN Challenge/Response Protocol allows an OpenVPN server to
844
+generate challenge questions that are shown to the user, and to see
845
+the user's responses to those challenges.  Based on the responses, the
846
+server can allow or deny access.
847
+
848
+In this way, the OpenVPN Challenge/Response Protocol can be used
849
+to implement multi-factor authentication.  Two different
850
+variations on the challenge/response protocol are supported: the
851
+"Dynamic" and "Static" protocols.
852
+
853
+The basic idea of Challenge/Response is that the user must enter an
854
+additional piece of information, in addition to the username and
855
+password, to successfully authenticate.  Normally, this information
856
+is used to prove that the user posesses a certain key-like device
857
+such as cryptographic token or a particular mobile phone.
858
+
859
+Dynamic protocol:
860
+
861
+The OpenVPN dynamic challenge/response protocol works by returning
862
+a specially formatted error message after initial successful
863
+authentication.  This error message contains the challenge question,
864
+and is formatted as such:
865
+
866
+  CRV1:<flags>:<state_id>:<username_base64>:<challenge_text>
867
+
868
+flags: a series of optional, comma-separated flags:
869
+ E : echo the response when the user types it
870
+ R : a response is required
871
+
872
+state_id: an opaque string that should be returned to the server
873
+ along with the response.
874
+
875
+username_base64 : the username formatted as base64
876
+
877
+challenge_text : the challenge text to be shown to the user
878
+
879
+Example challenge:
880
+
881
+  CRV1:R,E:Om01u7Fh4LrGBS7uh0SWmzwabUiGiW6l:Y3Ix:Please enter token PIN
882
+
883
+After showing the challenge_text and getting a response from the user
884
+(if R flag is specified), the client should submit the following
885
+auth creds back to the OpenVPN server:
886
+
887
+Username: [username decoded from username_base64]
888
+Password: CRV1::<state_id>::<response_text>
889
+
890
+Where state_id is taken from the challenge request and response_text
891
+is what the user entered in response to the challenge_text.
892
+If the R flag is not present, response_text may be the empty
893
+string.
894
+
895
+Example response (suppose the user enters "8675309" for the token PIN):
896
+
897
+  Username: cr1 ("Y3Ix" base64 decoded)
898
+  Password: CRV1::Om01u7Fh4LrGBS7uh0SWmzwabUiGiW6l::8675309
899
+
900
+Static protocol:
901
+
902
+The static protocol differs from the dynamic protocol in that the
903
+challenge question and response field is given to the user in the
904
+initial username/password dialog, and the username, password, and
905
+response are delivered back to the server in a single transaction.
906
+
907
+The "static-challenge" directive is used to give the challenge text
908
+to OpenVPN and indicate whether or not the response should be echoed.
909
+
910
+When the "static-challenge" directive is used, the management
911
+interface will respond as such when credentials are needed:
912
+
913
+  >PASSWORD:Need 'Auth' username/password SC:<ECHO>,<TEXT>
914
+
915
+  ECHO: "1" if response should be echoed, "0" to not echo
916
+  TEXT: challenge text that should be shown to the user to
917
+      facilitate their response
918
+
919
+For example:
920
+
921
+  >PASSWORD:Need 'Auth' username/password SC:1,Please enter token PIN
922
+
923
+The above notification indicates that OpenVPN needs a --auth-user-pass
924
+password plus a response to a static challenge ("Please enter token PIN").
925
+The "1" after the "SC:" indicates that the response should be echoed.
926
+
927
+The management interface client in this case should add the static
928
+challenge text to the auth dialog followed by a field for the user to
929
+enter a response.  Then the client should pack the password and response
930
+together into an encoded password:
931
+
932
+  username "Auth" foo
933
+  password "Auth" "SCRV1:<BASE64_PASSWORD>:<BASE64_RESPONSE>"
934
+
935
+For example, if the user entered "bar" as the password and 8675309
936
+as the PIN, the following management interface commands should be
937
+issued:
938
+
939
+  username "Auth" foo
940
+  password "Auth" "SCRV1:Zm9v:ODY3NTMwOQ=="
941
+
942
+Client-side support for challenge/response protocol:
943
+
944
+Currently, the Access Server client and standalone OpenVPN
945
+client support both static and dynamic challenge/response
946
+protocols.  However, any OpenVPN client UI that drives OpenVPN
947
+via the management interface needs to add explicit support
948
+for the challenge/response protocol.
... ...
@@ -1403,10 +1403,16 @@ get_user_pass_cr (struct user_pass *up,
1403 1403
 	  && ((auth_file && streq (auth_file, "management")) || (from_stdin && (flags & GET_USER_PASS_MANAGEMENT)))
1404 1404
 	  && management_query_user_pass_enabled (management))
1405 1405
 	{
1406
+	  const char *sc = NULL;
1407
+
1406 1408
 	  if (flags & GET_USER_PASS_PREVIOUS_CREDS_FAILED)
1407 1409
 	    management_auth_failure (management, prefix, "previous auth credentials failed");
1408 1410
 
1409
-	  if (!management_query_user_pass (management, up, prefix, flags))
1411
+#ifdef ENABLE_CLIENT_CR
1412
+	  if (auth_challenge && (flags & GET_USER_PASS_STATIC_CHALLENGE))
1413
+	    sc = auth_challenge;
1414
+#endif
1415
+	  if (!management_query_user_pass (management, up, prefix, flags, sc))
1410 1416
 	    {
1411 1417
 	      if ((flags & GET_USER_PASS_NOFATAL) != 0)
1412 1418
 		return false;
... ...
@@ -1438,7 +1444,7 @@ get_user_pass_cr (struct user_pass *up,
1438 1438
       else if (from_stdin)
1439 1439
 	{
1440 1440
 #ifdef ENABLE_CLIENT_CR
1441
-	  if (auth_challenge)
1441
+	  if (auth_challenge && (flags & GET_USER_PASS_DYNAMIC_CHALLENGE))
1442 1442
 	    {
1443 1443
 	      struct auth_challenge_info *ac = get_auth_challenge (auth_challenge, &gc);
1444 1444
 	      if (ac)
... ...
@@ -1447,7 +1453,7 @@ get_user_pass_cr (struct user_pass *up,
1447 1447
 		  struct buffer packed_resp;
1448 1448
 
1449 1449
 		  buf_set_write (&packed_resp, (uint8_t*)up->password, USER_PASS_LEN);
1450
-		  msg (M_INFO, "CHALLENGE: %s", ac->challenge_text);
1450
+		  msg (M_INFO|M_NOPREFIX, "CHALLENGE: %s", ac->challenge_text);
1451 1451
 		  if (!get_console_input ("Response:", BOOL_CAST(ac->flags&CR_ECHO), response, USER_PASS_LEN))
1452 1452
 		    msg (M_FATAL, "ERROR: could not read challenge response from stdin");
1453 1453
 		  strncpynt (up->username, ac->user, USER_PASS_LEN);
... ...
@@ -1477,6 +1483,28 @@ get_user_pass_cr (struct user_pass *up,
1477 1477
 
1478 1478
 	      if (!get_console_input (BSTR (&pass_prompt), false, up->password, USER_PASS_LEN))
1479 1479
 		msg (M_FATAL, "ERROR: could not not read %s password from stdin", prefix);
1480
+
1481
+#ifdef ENABLE_CLIENT_CR
1482
+	      if (auth_challenge && (flags & GET_USER_PASS_STATIC_CHALLENGE))
1483
+		{
1484
+		  char *response = (char *) gc_malloc (USER_PASS_LEN, false, &gc);
1485
+		  struct buffer packed_resp;
1486
+		  char *pw64=NULL, *resp64=NULL;
1487
+
1488
+		  msg (M_INFO|M_NOPREFIX, "CHALLENGE: %s", auth_challenge);
1489
+		  if (!get_console_input ("Response:", BOOL_CAST(flags & GET_USER_PASS_STATIC_CHALLENGE_ECHO), response, USER_PASS_LEN))
1490
+		    msg (M_FATAL, "ERROR: could not read static challenge response from stdin");
1491
+		  if (base64_encode(up->password, strlen(up->password), &pw64) == -1
1492
+		      || base64_encode(response, strlen(response), &resp64) == -1)
1493
+		    msg (M_FATAL, "ERROR: could not base64-encode password/static_response");
1494
+		  buf_set_write (&packed_resp, (uint8_t*)up->password, USER_PASS_LEN);
1495
+		  buf_printf (&packed_resp, "SCRV1:%s:%s", pw64, resp64);
1496
+		  string_clear(pw64);
1497
+		  free(pw64);
1498
+		  string_clear(resp64);
1499
+		  free(resp64);
1500
+		}
1501
+#endif
1480 1502
 	    }
1481 1503
 	}
1482 1504
       else
... ...
@@ -1544,42 +1572,8 @@ get_user_pass_cr (struct user_pass *up,
1544 1544
 #ifdef ENABLE_CLIENT_CR
1545 1545
 
1546 1546
 /*
1547
- * Parse a challenge message returned along with AUTH_FAILED.
1548
- * The message is formatted as such:
1549
- *
1550
- *  CRV1:<flags>:<state_id>:<username_base64>:<challenge_text>
1551
- *
1552
- * flags: a series of optional, comma-separated flags:
1553
- *  E : echo the response when the user types it
1554
- *  R : a response is required
1555
- *
1556
- * state_id: an opaque string that should be returned to the server
1557
- *  along with the response.
1558
- *
1559
- * username_base64 : the username formatted as base64
1560
- *
1561
- * challenge_text : the challenge text to be shown to the user
1562
- *
1563
- * Example challenge:
1564
- *
1565
- *   CRV1:R,E:Om01u7Fh4LrGBS7uh0SWmzwabUiGiW6l:Y3Ix:Please enter token PIN
1566
- *
1567
- * After showing the challenge_text and getting a response from the user
1568
- * (if R flag is specified), the client should submit the following
1569
- * auth creds back to the OpenVPN server:
1570
- *
1571
- * Username: [username decoded from username_base64]
1572
- * Password: CRV1::<state_id>::<response_text>
1573
- *
1574
- * Where state_id is taken from the challenge request and response_text
1575
- * is what the user entered in response to the challenge_text.
1576
- * If the R flag is not present, response_text may be the empty
1577
- * string.
1578
- *
1579
- * Example response (suppose the user enters "8675309" for the token PIN):
1580
- *
1581
- *   Username: cr1 ("Y3Ix" base64 decoded)
1582
- *   Password: CRV1::Om01u7Fh4LrGBS7uh0SWmzwabUiGiW6l::8675309
1547
+ * See management/management-notes.txt for more info on the
1548
+ * the dynamic challenge/response protocol implemented here.
1583 1549
  */
1584 1550
 struct auth_challenge_info *
1585 1551
 get_auth_challenge (const char *auth_challenge, struct gc_arena *gc)
... ...
@@ -278,8 +278,19 @@ struct auth_challenge_info {
278 278
 
279 279
 struct auth_challenge_info *get_auth_challenge (const char *auth_challenge, struct gc_arena *gc);
280 280
 
281
+/*
282
+ * Challenge response info on client as pushed by server.
283
+ */
284
+struct static_challenge_info {
285
+# define SC_ECHO     (1<<0) /* echo response when typed by user */
286
+  unsigned int flags;
287
+
288
+  const char *challenge_text;
289
+};
290
+
281 291
 #else
282 292
 struct auth_challenge_info {};
293
+struct static_challenge_info {};
283 294
 #endif
284 295
 
285 296
 bool get_console_input (const char *prompt, const bool echo, char *input, const int capacity);
... ...
@@ -295,6 +306,10 @@ bool get_console_input (const char *prompt, const bool echo, char *input, const
295 295
 #define GET_USER_PASS_NEED_STR      (1<<5)
296 296
 #define GET_USER_PASS_PREVIOUS_CREDS_FAILED (1<<6)
297 297
 
298
+#define GET_USER_PASS_DYNAMIC_CHALLENGE      (1<<7) /* CRV1 protocol  -- dynamic challenge */
299
+#define GET_USER_PASS_STATIC_CHALLENGE       (1<<8) /* SCRV1 protocol -- static challenge */
300
+#define GET_USER_PASS_STATIC_CHALLENGE_ECHO  (1<<9) /* SCRV1 protocol -- echo response */
301
+
298 302
 bool get_user_pass_cr (struct user_pass *up,
299 303
 		       const char *auth_file,
300 304
 		       const char *prefix,
... ...
@@ -150,11 +150,6 @@ multi_tcp_instance_specific_init (struct multi_context *m, struct multi_instance
150 150
   ASSERT (mi->context.c2.link_socket);
151 151
   ASSERT (mi->context.c2.link_socket->info.lsa);
152 152
   ASSERT (mi->context.c2.link_socket->mode == LS_MODE_TCP_ACCEPT_FROM);
153
-  ASSERT (mi->context.c2.link_socket->info.lsa->actual.dest.addr.sa.sa_family == AF_INET
154
-#ifdef USE_PF_INET6
155
-	  || mi->context.c2.link_socket->info.lsa->actual.dest.addr.sa.sa_family == AF_INET6
156
-#endif
157
-	  );
158 153
   if (!mroute_extract_openvpn_sockaddr (&mi->real, &mi->context.c2.link_socket->info.lsa->actual.dest, true))
159 154
     {
160 155
       msg (D_MULTI_ERRORS, "MULTI TCP: TCP client address is undefined");
... ...
@@ -1114,8 +1114,8 @@ addresses in packets.
1114 1114
 .\"*********************************************************
1115 1115
 .TP
1116 1116
 .B \-\-redirect-gateway flags...
1117
-(Experimental) Automatically execute routing commands to cause all outgoing IP traffic
1118
-to be redirected over the VPN.
1117
+Automatically execute routing commands to cause all outgoing IP traffic
1118
+to be redirected over the VPN.  This is a client-side option.
1119 1119
 
1120 1120
 This option performs three steps:
1121 1121
 
... ...
@@ -1154,6 +1154,11 @@ flag will cause step
1154 1154
 .B 1
1155 1155
 above to be omitted.
1156 1156
 
1157
+.B autolocal \-\-
1158
+Try to automatically determine whether to enable
1159
+.B local
1160
+flag above.
1161
+
1157 1162
 .B def1 \-\-
1158 1163
 Use this flag to override
1159 1164
 the default gateway by using 0.0.0.0/1 and 128.0.0.0/1
... ...
@@ -1172,12 +1177,10 @@ bypasses the tunnel
1172 1172
 (Available on Windows clients, may not be available
1173 1173
 on non-Windows clients).
1174 1174
 
1175
-Using the def1 flag is highly recommended.
1176
-.\"*********************************************************
1177
-.TP
1178
-.B \-\-redirect-private [flags]
1179
-Like \-\-redirect-gateway, but omit actually changing the default
1180
-gateway.  Useful when pushing private subnets.
1175
+.B block-local \-\-
1176
+Block access to local LAN when the tunnel is active, except for
1177
+the LAN gateway itself.  This is accomplished by routing the local
1178
+LAN (except for the LAN gateway address) into the tunnel.
1181 1179
 .\"*********************************************************
1182 1180
 .TP
1183 1181
 .B \-\-link-mtu n
... ...
@@ -1185,6 +1188,12 @@ Sets an upper bound on the size of UDP packets which are sent
1185 1185
 between OpenVPN peers.  It's best not to set this parameter unless
1186 1186
 you know what you're doing.
1187 1187
 .\"*********************************************************
1188
+.\"*********************************************************
1189
+.TP
1190
+.B \-\-redirect-private [flags]
1191
+Like \-\-redirect-gateway, but omit actually changing the default
1192
+gateway.  Useful when pushing private subnets.
1193
+.\"*********************************************************
1188 1194
 .TP
1189 1195
 .B \-\-tun-mtu n
1190 1196
 Take the TUN device MTU to be
... ...
@@ -2406,6 +2415,12 @@ for inputs which ordinarily would have been queried from the
2406 2406
 console.
2407 2407
 .\"*********************************************************
2408 2408
 .TP
2409
+.B \-\-management-query-remote
2410
+Allow management interface to override
2411
+.B \-\-remote
2412
+directives (client-only).
2413
+.\"*********************************************************
2414
+.TP
2409 2415
 .B \-\-management-forget-disconnect
2410 2416
 Make OpenVPN forget passwords when management session
2411 2417
 disconnects.
... ...
@@ -3425,6 +3440,21 @@ Note that while this option cannot be pushed, it can be controlled
3425 3425
 from the management interface.
3426 3426
 .\"*********************************************************
3427 3427
 .TP
3428
+.B \-\-static\-challenge t e
3429
+Enable static challenge/response protocol using challenge text
3430
+.B t,
3431
+with
3432
+echo flag given by
3433
+.B e
3434
+(0|1).
3435
+
3436
+The echo flag indicates whether or not the user's response
3437
+to the challenge should be echoed.
3438
+
3439
+See management\-notes.txt in the OpenVPN distribution for a
3440
+description of the OpenVPN challenge/response protocol.
3441
+.\"*********************************************************
3442
+.TP
3428 3443
 .B \-\-server-poll-timeout n
3429 3444
 when polling possible remote servers to connect to
3430 3445
 in a round-robin fashion, spend no more than
... ...
@@ -5532,6 +5562,7 @@ script being run.  It can be one of the following:
5532 5532
 .B client-connect, client-disconnect, 
5533 5533
 or
5534 5534
 .B learn-address.
5535
+Set prior to execution of any script.
5535 5536
 .\"*********************************************************
5536 5537
 .TP
5537 5538
 .B signal
... ...
@@ -358,6 +358,9 @@ static const char usage_message[] =
358 358
   "                      ip/port rather than listen as a TCP server.\n"
359 359
   "--management-query-passwords : Query management channel for private key\n"
360 360
   "                  and auth-user-pass passwords.\n"
361
+#if MANAGEMENT_QUERY_REMOTE
362
+  "--management-query-remote : Query management channel for --remote directive.\n"
363
+#endif
361 364
   "--management-hold : Start " PACKAGE_NAME " in a hibernating state, until a client\n"
362 365
   "                    of the management interface explicitly starts it.\n"
363 366
   "--management-signal : Issue SIGUSR1 when management disconnect event occurs.\n"
... ...
@@ -469,6 +472,8 @@ static const char usage_message[] =
469 469
   "                  when connecting to a '--mode server' remote host.\n"
470 470
   "--auth-retry t  : How to handle auth failures.  Set t to\n"
471 471
   "                  none (default), interact, or nointeract.\n"
472
+  "--static-challenge t e : Enable static challenge/response protocol using\n"
473
+  "                  challenge text t, with e indicating echo flag (0|1)\n"
472 474
   "--server-poll-timeout n : when polling possible remote servers to connect to\n"
473 475
   "                  in a round-robin fashion, spend no more than n seconds\n"
474 476
   "                  waiting for a response before trying the next server.\n"
... ...
@@ -701,6 +706,9 @@ static const char usage_message[] =
701 701
   "--show-pkcs11-ids provider [cert_private] : Show PKCS#11 available ids.\n" 
702 702
   "                                            --verb option can be added *BEFORE* this.\n"
703 703
 #endif				/* ENABLE_PKCS11 */
704
+  "\n"
705
+  "General Standalone Options:\n"
706
+  "--show-gateway : Show info about default gateway.\n"
704 707
  ;
705 708
 
706 709
 #endif /* !ENABLE_SMALL */
... ...
@@ -3845,6 +3853,14 @@ add_option (struct options *options,
3845 3845
 
3846 3846
       read_config_file (options, p[1], level, file, line, msglevel, permission_mask, option_types_found, es);
3847 3847
     }
3848
+  else if (streq (p[0], "show-gateway"))
3849
+    {
3850
+      struct route_gateway_info rgi;
3851
+      VERIFY_PERMISSION (OPT_P_GENERAL);
3852
+      get_default_gateway(&rgi);
3853
+      print_default_gateway(M_INFO, &rgi);
3854
+      openvpn_exit (OPENVPN_EXIT_STATUS_GOOD); /* exit point */
3855
+    }
3848 3856
 #if 0
3849 3857
   else if (streq (p[0], "foreign-option") && p[1])
3850 3858
     {
... ...
@@ -3928,6 +3944,13 @@ add_option (struct options *options,
3928 3928
       VERIFY_PERMISSION (OPT_P_GENERAL);
3929 3929
       options->management_flags |= MF_QUERY_PASSWORDS;
3930 3930
     }
3931
+#if MANAGEMENT_QUERY_REMOTE
3932
+  else if (streq (p[0], "management-query-remote"))
3933
+    {
3934
+      VERIFY_PERMISSION (OPT_P_GENERAL);
3935
+      options->management_flags |= MF_QUERY_REMOTE;
3936
+    }
3937
+#endif
3931 3938
   else if (streq (p[0], "management-hold"))
3932 3939
     {
3933 3940
       VERIFY_PERMISSION (OPT_P_GENERAL);
... ...
@@ -5031,6 +5054,8 @@ add_option (struct options *options,
5031 5031
 	    options->routes->flags |= RG_BYPASS_DHCP;
5032 5032
 	  else if (streq (p[j], "bypass-dns"))
5033 5033
 	    options->routes->flags |= RG_BYPASS_DNS;
5034
+	  else if (streq (p[j], "block-local"))
5035
+	    options->routes->flags |= RG_BLOCK_LOCAL;
5034 5036
 	  else
5035 5037
 	    {
5036 5038
 	      msg (msglevel, "unknown --%s flag: %s", p[0], p[j]);
... ...
@@ -5611,6 +5636,15 @@ add_option (struct options *options,
5611 5611
       VERIFY_PERMISSION (OPT_P_GENERAL);
5612 5612
       auth_retry_set (msglevel, p[1]);
5613 5613
     }
5614
+#ifdef ENABLE_CLIENT_CR
5615
+  else if (streq (p[0], "static-challenge") && p[1] && p[2])
5616
+    {
5617
+      VERIFY_PERMISSION (OPT_P_GENERAL);
5618
+      options->sc_info.challenge_text = p[1];
5619
+      if (atoi(p[2]))
5620
+	options->sc_info.flags |= SC_ECHO;
5621
+    }
5622
+#endif
5614 5623
 #endif
5615 5624
 #ifdef WIN32
5616 5625
   else if (streq (p[0], "win-sys") && p[1])
... ...
@@ -110,7 +110,15 @@ struct connection_entry
110 110
 # define CE_HTTP_PROXY_FALLBACK (1<<1)
111 111
   time_t ce_http_proxy_fallback_timestamp; /* time when fallback http_proxy_options was last updated */
112 112
 #endif
113
-
113
+#if MANAGEMENT_QUERY_REMOTE
114
+# define CE_MAN_QUERY_REMOTE_UNDEF  0
115
+# define CE_MAN_QUERY_REMOTE_QUERY  1
116
+# define CE_MAN_QUERY_REMOTE_ACCEPT 2
117
+# define CE_MAN_QUERY_REMOTE_MOD    3
118
+# define CE_MAN_QUERY_REMOTE_SKIP   4
119
+# define CE_MAN_QUERY_REMOTE_MASK   (0x07)
120
+# define CE_MAN_QUERY_REMOTE_SHIFT  (2)
121
+#endif
114 122
   unsigned int flags;
115 123
 };
116 124
 
... ...
@@ -150,6 +158,14 @@ struct hpo_store
150 150
 };
151 151
 #endif
152 152
 
153
+#if MANAGEMENT_QUERY_REMOTE
154
+struct remote_host_store
155
+{
156
+# define RH_HOST_LEN 80
157
+  char host[RH_HOST_LEN];
158
+};
159
+#endif
160
+
153 161
 /* Command line options */
154 162
 struct options
155 163
 {
... ...
@@ -202,6 +218,10 @@ struct options
202 202
   struct hpo_store *hpo_store; /* used to store dynamic proxy info given by management interface */
203 203
 #endif
204 204
 
205
+#if MANAGEMENT_QUERY_REMOTE
206
+  struct remote_host_store *rh_store;
207
+#endif
208
+
205 209
   bool remote_random;
206 210
   const char *ipchange;
207 211
   const char *dev;
... ...
@@ -457,6 +477,9 @@ struct options
457 457
 
458 458
   int scheduled_exit_interval;
459 459
 
460
+#ifdef ENABLE_CLIENT_CR
461
+  struct static_challenge_info sc_info;
462
+#endif
460 463
 #endif
461 464
 
462 465
 #ifdef USE_CRYPTO
... ...
@@ -39,7 +39,8 @@
39 39
 
40 40
 #include "memdbg.h"
41 41
 
42
-static void delete_route (const struct route *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);
42
+static void delete_route (struct route *r, const struct tuntap *tt, unsigned int flags, const struct route_gateway_info *rgi, const struct env_set *es);
43
+
43 44
 static void get_bypass_addresses (struct route_bypass *rb, const unsigned int flags);
44 45
 
45 46
 #ifdef ENABLE_DEBUG
... ...
@@ -60,6 +61,26 @@ print_bypass_addresses (const struct route_bypass *rb)
60 60
 
61 61
 #endif
62 62
 
63
+static bool
64
+add_bypass_address (struct route_bypass *rb, const in_addr_t a)
65
+{
66
+  int i;
67
+  for (i = 0; i < rb->n_bypass; ++i)
68
+    {
69
+      if (a == rb->bypass[i]) /* avoid duplicates */
70
+	return true;
71
+    }
72
+  if (rb->n_bypass < N_ROUTE_BYPASS)
73
+    {
74
+      rb->bypass[rb->n_bypass++] = a;
75
+      return true;
76
+    }
77
+  else
78
+    {
79
+      return false;
80
+    }
81
+}
82
+
63 83
 struct route_option_list *
64 84
 new_route_option_list (const int max_routes, struct gc_arena *a)
65 85
 {
... ...
@@ -123,7 +144,7 @@ route_string (const struct route *r, struct gc_arena *gc)
123 123
 	      print_in_addr_t (r->netmask, 0, gc),
124 124
 	      print_in_addr_t (r->gateway, 0, gc)
125 125
 	      );
126
-  if (r->metric_defined)
126
+  if (r->flags & RT_METRIC_DEFINED)
127 127
     buf_printf (&out, " metric %d", r->metric);
128 128
   return BSTR (&out);
129 129
 }
... ...
@@ -152,7 +173,7 @@ setenv_route_addr (struct env_set *es, const char *key, const in_addr_t addr, in
152 152
 }
153 153
 
154 154
 static bool
155
-get_special_addr (const struct route_special_addr *spec,
155
+get_special_addr (const struct route_list *rl,
156 156
 		  const char *string,
157 157
 		  in_addr_t *out,
158 158
 		  bool *status)
... ...
@@ -161,10 +182,10 @@ get_special_addr (const struct route_special_addr *spec,
161 161
     *status = true;
162 162
   if (!strcmp (string, "vpn_gateway"))
163 163
     {
164
-      if (spec)
164
+      if (rl)
165 165
 	{
166
-	  if (spec->remote_endpoint_defined)
167
-	    *out = spec->remote_endpoint;
166
+	  if (rl->spec.flags & RTSA_REMOTE_ENDPOINT)
167
+	    *out = rl->spec.remote_endpoint;
168 168
 	  else
169 169
 	    {
170 170
 	      msg (M_INFO, PACKAGE_NAME " ROUTE: vpn_gateway undefined");
... ...
@@ -176,10 +197,10 @@ get_special_addr (const struct route_special_addr *spec,
176 176
     }
177 177
   else if (!strcmp (string, "net_gateway"))
178 178
     {
179
-      if (spec)
179
+      if (rl)
180 180
 	{
181
-	  if (spec->net_gateway_defined)
182
-	    *out = spec->net_gateway;
181
+	  if (rl->rgi.flags & RGI_ADDR_DEFINED)
182
+	    *out = rl->rgi.gateway.addr;
183 183
 	  else
184 184
 	    {
185 185
 	      msg (M_INFO, PACKAGE_NAME " ROUTE: net_gateway undefined -- unable to get default gateway from system");
... ...
@@ -191,10 +212,10 @@ get_special_addr (const struct route_special_addr *spec,
191 191
     }
192 192
   else if (!strcmp (string, "remote_host"))
193 193
     {
194
-      if (spec)
194
+      if (rl)
195 195
 	{
196
-	  if (spec->remote_host_defined)
197
-	    *out = spec->remote_host;
196
+	  if (rl->spec.flags & RTSA_REMOTE_HOST)
197
+	    *out = rl->spec.remote_host;
198 198
 	  else
199 199
 	    {
200 200
 	      msg (M_INFO, PACKAGE_NAME " ROUTE: remote_host undefined");
... ...
@@ -220,13 +241,13 @@ static bool
220 220
 init_route (struct route *r,
221 221
 	    struct resolve_list *network_list,
222 222
 	    const struct route_option *ro,
223
-	    const struct route_special_addr *spec)
223
+	    const struct route_list *rl)
224 224
 {
225 225
   const in_addr_t default_netmask = ~0;
226 226
   bool status;
227 227
 
228
+  CLEAR (*r);
228 229
   r->option = ro;
229
-  r->defined = false;
230 230
 
231 231
   /* network */
232 232
 
... ...
@@ -235,7 +256,7 @@ init_route (struct route *r,
235 235
       goto fail;
236 236
     }
237 237
   
238
-  if (!get_special_addr (spec, ro->network, &r->network, &status))
238
+  if (!get_special_addr (rl, ro->network, &r->network, &status))
239 239
     {
240 240
       r->network = getaddr_multi (
241 241
 				  GETADDR_RESOLVE
... ...
@@ -272,7 +293,7 @@ init_route (struct route *r,
272 272
 
273 273
   if (is_route_parm_defined (ro->gateway))
274 274
     {
275
-      if (!get_special_addr (spec, ro->gateway, &r->gateway, &status))
275
+      if (!get_special_addr (rl, ro->gateway, &r->gateway, &status))
276 276
 	{
277 277
 	  r->gateway = getaddr (
278 278
 				GETADDR_RESOLVE
... ...
@@ -288,8 +309,8 @@ init_route (struct route *r,
288 288
     }
289 289
   else
290 290
     {
291
-      if (spec->remote_endpoint_defined)
292
-	r->gateway = spec->remote_endpoint;
291
+      if (rl->spec.flags & RTSA_REMOTE_ENDPOINT)
292
+	r->gateway = rl->spec.remote_endpoint;
293 293
       else
294 294
 	{
295 295
 	  msg (M_WARN, PACKAGE_NAME " ROUTE: " PACKAGE_NAME " needs a gateway parameter for a --route option and no default was specified by either --route-gateway or --ifconfig options");
... ...
@@ -299,7 +320,6 @@ init_route (struct route *r,
299 299
 
300 300
   /* metric */
301 301
 
302
-  r->metric_defined = false;
303 302
   r->metric = 0;
304 303
   if (is_route_parm_defined (ro->metric))
305 304
     {
... ...
@@ -311,22 +331,21 @@ init_route (struct route *r,
311 311
 	       ro->metric);
312 312
 	  goto fail;
313 313
 	}
314
-      r->metric_defined = true;
314
+      r->flags |= RT_METRIC_DEFINED;
315 315
     }
316
-  else if (spec->default_metric_defined)
316
+  else if (rl->spec.flags & RTSA_DEFAULT_METRIC)
317 317
     {
318
-      r->metric = spec->default_metric;
319
-      r->metric_defined = true;
318
+      r->metric = rl->spec.default_metric;
319
+      r->flags |= RT_METRIC_DEFINED;
320 320
     }
321 321
 
322
-  r->defined = true;
322
+  r->flags |= RT_DEFINED;
323 323
 
324 324
   return true;
325 325
 
326 326
  fail:
327 327
   msg (M_WARN, PACKAGE_NAME " ROUTE: failed to parse/resolve route for host/network: %s",
328 328
        ro->network);
329
-  r->defined = false;
330 329
   return false;
331 330
 }
332 331
 
... ...
@@ -447,15 +466,70 @@ clear_route_ipv6_list (struct route_ipv6_list *rl6)
447 447
 }
448 448
 
449 449
 void
450
-route_list_add_default_gateway (struct route_list *rl,
451
-				struct env_set *es,
452
-				const in_addr_t addr)
450
+route_list_add_vpn_gateway (struct route_list *rl,
451
+			    struct env_set *es,
452
+			    const in_addr_t addr)
453 453
 {
454 454
   rl->spec.remote_endpoint = addr;
455
-  rl->spec.remote_endpoint_defined = true;
455
+  rl->spec.flags |= RTSA_REMOTE_ENDPOINT;
456 456
   setenv_route_addr (es, "vpn_gateway", rl->spec.remote_endpoint, -1);
457 457
 }
458 458
 
459
+static void
460
+add_block_local_item (struct route_list *rl,
461
+		      const struct route_gateway_address *gateway,
462
+		      in_addr_t target)
463
+{
464
+  const int rgi_needed = (RGI_ADDR_DEFINED|RGI_NETMASK_DEFINED);
465
+  if ((rl->rgi.flags & rgi_needed) == rgi_needed
466
+      && rl->rgi.gateway.netmask < 0xFFFFFFFF
467
+      && (rl->n)+2 <= rl->capacity)
468
+    {
469
+      struct route r;
470
+      unsigned int l2;
471
+
472
+      /* split a route into two smaller blocking routes, and direct them to target */
473
+      CLEAR(r);
474
+      r.flags = RT_DEFINED;
475
+      r.gateway = target;
476
+      l2 = ((~gateway->netmask)+1)>>1;
477
+      r.netmask = ~(l2-1);
478
+      r.network = gateway->addr & r.netmask;
479
+      rl->routes[rl->n++] = r;
480
+      r.network += l2;
481
+      rl->routes[rl->n++] = r;
482
+    }
483
+}
484
+
485
+static void
486
+add_block_local (struct route_list *rl)
487
+{
488
+  const int rgi_needed = (RGI_ADDR_DEFINED|RGI_NETMASK_DEFINED);
489
+  if ((rl->flags & RG_BLOCK_LOCAL)
490
+      && (rl->rgi.flags & rgi_needed) == rgi_needed
491
+      && (rl->spec.flags & RTSA_REMOTE_ENDPOINT)
492
+      && rl->spec.remote_host_local != TLA_LOCAL)
493
+    {
494
+      size_t i;
495
+
496
+      /* add bypass for gateway addr */
497
+      add_bypass_address (&rl->spec.bypass, rl->rgi.gateway.addr);
498
+
499
+      /* block access to local subnet */
500
+      add_block_local_item (rl, &rl->rgi.gateway, rl->spec.remote_endpoint);
501
+
502
+      /* process additional subnets on gateway interface */
503
+      for (i = 0; i < rl->rgi.n_addrs; ++i)
504
+	{
505
+	  const struct route_gateway_address *gwa = &rl->rgi.addrs[i];
506
+	  /* omit the add/subnet in &rl->rgi which we processed above */
507
+	  if (!((rl->rgi.gateway.addr & rl->rgi.gateway.netmask) == (gwa->addr & gwa->netmask)
508
+		&& rl->rgi.gateway.netmask == gwa->netmask))
509
+	    add_block_local_item (rl, gwa, rl->spec.remote_endpoint);
510
+	}
511
+    }
512
+}
513
+
459 514
 bool
460 515
 init_route_list (struct route_list *rl,
461 516
 		 const struct route_option_list *opt,
... ...
@@ -474,48 +548,47 @@ init_route_list (struct route_list *rl,
474 474
   if (remote_host)
475 475
     {
476 476
       rl->spec.remote_host = remote_host;
477
-      rl->spec.remote_host_defined = true;
477
+      rl->spec.flags |= RTSA_REMOTE_HOST;
478 478
     }
479 479
 
480 480
   if (default_metric)
481 481
     {
482 482
       rl->spec.default_metric = default_metric;
483
-      rl->spec.default_metric_defined = true;
483
+      rl->spec.flags |= RTSA_DEFAULT_METRIC;
484 484
     }
485 485
 
486
-  rl->spec.net_gateway_defined = get_default_gateway (&rl->spec.net_gateway, NULL);
487
-  if (rl->spec.net_gateway_defined)
486
+  get_default_gateway (&rl->rgi);
487
+  if (rl->rgi.flags & RGI_ADDR_DEFINED)
488 488
     {
489
-      setenv_route_addr (es, "net_gateway", rl->spec.net_gateway, -1);
490
-      dmsg (D_ROUTE, "ROUTE default_gateway=%s", print_in_addr_t (rl->spec.net_gateway, 0, &gc));
489
+      setenv_route_addr (es, "net_gateway", rl->rgi.gateway.addr, -1);
490
+#ifdef ENABLE_DEBUG
491
+      print_default_gateway (D_ROUTE, &rl->rgi);
492
+#endif
491 493
     }
492 494
   else
493 495
     {
494 496
       dmsg (D_ROUTE, "ROUTE: default_gateway=UNDEF");
495 497
     }
496 498
 
497
-  if (rl->flags & RG_ENABLE)
498
-    {
499
-      get_bypass_addresses (&rl->spec.bypass, rl->flags);
500
-#ifdef ENABLE_DEBUG
501
-      print_bypass_addresses (&rl->spec.bypass);
502
-#endif
503
-    }
499
+  if (rl->spec.flags & RTSA_REMOTE_HOST)
500
+    rl->spec.remote_host_local = test_local_addr (remote_host, &rl->rgi);
504 501
 
505 502
   if (is_route_parm_defined (remote_endpoint))
506 503
     {
504
+      bool defined = false;
507 505
       rl->spec.remote_endpoint = getaddr (
508 506
 				     GETADDR_RESOLVE
509 507
 				     | GETADDR_HOST_ORDER
510 508
 				     | GETADDR_WARN_ON_SIGNAL,
511 509
 				     remote_endpoint,
512 510
 				     0,
513
-				     &rl->spec.remote_endpoint_defined,
511
+				     &defined,
514 512
 				     NULL);
515 513
 
516
-      if (rl->spec.remote_endpoint_defined)
514
+      if (defined)
517 515
 	{
518 516
 	  setenv_route_addr (es, "vpn_gateway", rl->spec.remote_endpoint, -1);
517
+	  rl->spec.flags |= RTSA_REMOTE_ENDPOINT;
519 518
 	}
520 519
       else
521 520
 	{
... ...
@@ -524,12 +597,20 @@ init_route_list (struct route_list *rl,
524 524
 	  ret = false;
525 525
 	}
526 526
     }
527
-  else
528
-    rl->spec.remote_endpoint_defined = false;
527
+
528
+  if (rl->flags & RG_ENABLE)
529
+    {
530
+      add_block_local (rl);
531
+      get_bypass_addresses (&rl->spec.bypass, rl->flags);
532
+#ifdef ENABLE_DEBUG
533
+      print_bypass_addresses (&rl->spec.bypass);
534
+#endif
535
+    }
529 536
 
530 537
   /* parse the routes from opt to rl */
531 538
   {
532
-    int i, j = 0;
539
+    int i = 0;
540
+    int j = rl->n;
533 541
     bool warned = false;
534 542
     for (i = 0; i < opt->n; ++i)
535 543
       {
... ...
@@ -542,7 +623,7 @@ init_route_list (struct route_list *rl,
542 542
 	if (!init_route (&r,
543 543
 			 &netlist,
544 544
 			 &opt->routes[i],
545
-			 &rl->spec))
545
+			 rl))
546 546
 	  ret = false;
547 547
 	else
548 548
 	  {
... ...
@@ -648,15 +729,16 @@ add_route3 (in_addr_t network,
648 648
 	    in_addr_t gateway,
649 649
 	    const struct tuntap *tt,
650 650
 	    unsigned int flags,
651
+	    const struct route_gateway_info *rgi,
651 652
 	    const struct env_set *es)
652 653
 {
653 654
   struct route r;
654 655
   CLEAR (r);
655
-  r.defined = true;
656
+  r.flags = RT_DEFINED;
656 657
   r.network = network;
657 658
   r.netmask = netmask;
658 659
   r.gateway = gateway;
659
-  add_route (&r, tt, flags, es);
660
+  add_route (&r, tt, flags, rgi, es);
660 661
 }
661 662
 
662 663
 static void
... ...
@@ -665,15 +747,16 @@ del_route3 (in_addr_t network,
665 665
 	    in_addr_t gateway,
666 666
 	    const struct tuntap *tt,
667 667
 	    unsigned int flags,
668
+	    const struct route_gateway_info *rgi,
668 669
 	    const struct env_set *es)
669 670
 {
670 671
   struct route r;
671 672
   CLEAR (r);
672
-  r.defined = true;
673
+  r.flags = RT_DEFINED|RT_ADDED;
673 674
   r.network = network;
674 675
   r.netmask = netmask;
675 676
   r.gateway = gateway;
676
-  delete_route (&r, tt, flags, es);
677
+  delete_route (&r, tt, flags, rgi, es);
677 678
 }
678 679
 
679 680
 static void
... ...
@@ -681,17 +764,19 @@ add_bypass_routes (struct route_bypass *rb,
681 681
 		   in_addr_t gateway,
682 682
 		   const struct tuntap *tt,
683 683
 		   unsigned int flags,
684
+		   const struct route_gateway_info *rgi,
684 685
 		   const struct env_set *es)
685 686
 {
686 687
   int i;
687 688
   for (i = 0; i < rb->n_bypass; ++i)
688 689
     {
689
-      if (rb->bypass[i] != gateway)
690
+      if (rb->bypass[i])
690 691
 	add_route3 (rb->bypass[i],
691 692
 		    ~0,
692 693
 		    gateway,
693 694
 		    tt,
694 695
 		    flags,
696
+		    rgi,
695 697
 		    es);
696 698
     }
697 699
 }
... ...
@@ -701,17 +786,19 @@ del_bypass_routes (struct route_bypass *rb,
701 701
 		   in_addr_t gateway,
702 702
 		   const struct tuntap *tt,
703 703
 		   unsigned int flags,
704
+		   const struct route_gateway_info *rgi,
704 705
 		   const struct env_set *es)
705 706
 {
706 707
   int i;
707 708
   for (i = 0; i < rb->n_bypass; ++i)
708 709
     {
709
-      if (rb->bypass[i] != gateway)
710
+      if (rb->bypass[i])
710 711
 	del_route3 (rb->bypass[i],
711 712
 		    ~0,
712 713
 		    gateway,
713 714
 		    tt,
714 715
 		    flags,
716
+		    rgi,
715 717
 		    es);
716 718
     }
717 719
 }
... ...
@@ -723,15 +810,15 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u
723 723
 
724 724
   if (rl->flags & RG_ENABLE)
725 725
     {
726
-      if (!rl->spec.remote_endpoint_defined)
726
+      if (!(rl->spec.flags & RTSA_REMOTE_ENDPOINT))
727 727
 	{
728 728
 	  msg (M_WARN, "%s VPN gateway parameter (--route-gateway or --ifconfig) is missing", err);
729 729
 	}
730
-      else if (!rl->spec.net_gateway_defined)
730
+      else if (!(rl->rgi.flags & RGI_ADDR_DEFINED))
731 731
 	{
732 732
 	  msg (M_WARN, "%s Cannot read current default gateway from system", err);
733 733
 	}
734
-      else if (!rl->spec.remote_host_defined)
734
+      else if (!(rl->spec.flags & RTSA_REMOTE_HOST))
735 735
 	{
736 736
 	  msg (M_WARN, "%s Cannot obtain current remote host address", err);
737 737
 	}
... ...
@@ -739,7 +826,7 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u
739 739
 	{
740 740
 	  bool local = BOOL_CAST(rl->flags & RG_LOCAL);
741 741
 	  if (rl->flags & RG_AUTO_LOCAL) {
742
-	    const int tla = test_local_addr (rl->spec.remote_host);
742
+	    const int tla = rl->spec.remote_host_local;
743 743
 	    if (tla == TLA_NONLOCAL)
744 744
 	      {
745 745
 		dmsg (D_ROUTE, "ROUTE remote_host is NOT LOCAL");
... ...
@@ -761,11 +848,12 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u
761 761
 #endif
762 762
 		add_route3 (rl->spec.remote_host,
763 763
 			    ~0,
764
-			    rl->spec.net_gateway,
764
+			    rl->rgi.gateway.addr,
765 765
 			    tt,
766 766
 			    flags,
767
+			    &rl->rgi,
767 768
 			    es);
768
-		rl->did_local = true;
769
+		rl->iflags |= RL_DID_LOCAL;
769 770
 #ifdef USE_PF_INET6
770 771
 	      } else {
771 772
 		dmsg (D_ROUTE, "ROUTE remote_host protocol differs from tunneled");
... ...
@@ -774,7 +862,7 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u
774 774
 	    }
775 775
 
776 776
 	  /* route DHCP/DNS server traffic through original default gateway */
777
-	  add_bypass_routes (&rl->spec.bypass, rl->spec.net_gateway, tt, flags, es);
777
+	  add_bypass_routes (&rl->spec.bypass, rl->rgi.gateway.addr, tt, flags, &rl->rgi, es);
778 778
 
779 779
 	  if (rl->flags & RG_REROUTE_GW)
780 780
 	    {
... ...
@@ -786,6 +874,7 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u
786 786
 			      rl->spec.remote_endpoint,
787 787
 			      tt,
788 788
 			      flags,
789
+			      &rl->rgi,
789 790
 			      es);
790 791
 
791 792
 		  /* add new default route (2nd component) */
... ...
@@ -794,6 +883,7 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u
794 794
 			      rl->spec.remote_endpoint,
795 795
 			      tt,
796 796
 			      flags,
797
+			      &rl->rgi,
797 798
 			      es);
798 799
 		}
799 800
 	      else
... ...
@@ -801,9 +891,10 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u
801 801
 		  /* delete default route */
802 802
 		  del_route3 (0,
803 803
 			      0,
804
-			      rl->spec.net_gateway,
804
+			      rl->rgi.gateway.addr,
805 805
 			      tt,
806 806
 			      flags,
807
+			      &rl->rgi,
807 808
 			      es);
808 809
 
809 810
 		  /* add new default route */
... ...
@@ -812,12 +903,13 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u
812 812
 			      rl->spec.remote_endpoint,
813 813
 			      tt,
814 814
 			      flags,
815
+			      &rl->rgi,
815 816
 			      es);
816 817
 		}
817 818
 	    }
818 819
 
819 820
 	  /* set a flag so we can undo later */
820
-	  rl->did_redirect_default_gateway = true;
821
+	  rl->iflags |= RL_DID_REDIRECT_DEFAULT_GATEWAY;
821 822
 	}
822 823
     }
823 824
 }
... ...
@@ -825,22 +917,23 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u
825 825
 static void
826 826
 undo_redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
827 827
 {
828
-  if (rl->did_redirect_default_gateway)
828
+  if (rl->iflags & RL_DID_REDIRECT_DEFAULT_GATEWAY)
829 829
     {
830 830
       /* delete remote host route */
831
-      if (rl->did_local)
831
+      if (rl->iflags & RL_DID_LOCAL)
832 832
 	{
833 833
 	  del_route3 (rl->spec.remote_host,
834 834
 		      ~0,
835
-		      rl->spec.net_gateway,
835
+		      rl->rgi.gateway.addr,
836 836
 		      tt,
837 837
 		      flags,
838
+		      &rl->rgi,
838 839
 		      es);
839
-	  rl->did_local = false;
840
+	  rl->iflags &= ~RL_DID_LOCAL;
840 841
 	}
841 842
 
842 843
       /* delete special DHCP/DNS bypass route */
843
-      del_bypass_routes (&rl->spec.bypass, rl->spec.net_gateway, tt, flags, es);
844
+      del_bypass_routes (&rl->spec.bypass, rl->rgi.gateway.addr, tt, flags, &rl->rgi, es);
844 845
 
845 846
       if (rl->flags & RG_REROUTE_GW)
846 847
 	{
... ...
@@ -852,6 +945,7 @@ undo_redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *
852 852
 			  rl->spec.remote_endpoint,
853 853
 			  tt,
854 854
 			  flags,
855
+			  &rl->rgi,
855 856
 			  es);
856 857
 
857 858
 	      /* delete default route (2nd component) */
... ...
@@ -860,6 +954,7 @@ undo_redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *
860 860
 			  rl->spec.remote_endpoint,
861 861
 			  tt,
862 862
 			  flags,
863
+			  &rl->rgi,
863 864
 			  es);
864 865
 	    }
865 866
 	  else
... ...
@@ -870,30 +965,29 @@ undo_redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *
870 870
 			  rl->spec.remote_endpoint,
871 871
 			  tt,
872 872
 			  flags,
873
+			  &rl->rgi,
873 874
 			  es);
874 875
 
875 876
 	      /* restore original default route */
876 877
 	      add_route3 (0,
877 878
 			  0,
878
-			  rl->spec.net_gateway,
879
+			  rl->rgi.gateway.addr,
879 880
 			  tt,
880 881
 			  flags,
882
+			  &rl->rgi,
881 883
 			  es);
882 884
 	    }
883 885
 	}
884 886
 
885
-      rl->did_redirect_default_gateway = false;
887
+      rl->iflags &= ~RL_DID_REDIRECT_DEFAULT_GATEWAY;
886 888
     }
887 889
 }
888 890
 
889 891
 void
890
-add_routes (struct route_list *rl, struct route_ipv6_list *rl6,
891
-	    const struct tuntap *tt, unsigned int flags, const struct env_set *es)
892
+add_routes (struct route_list *rl, struct route_ipv6_list *rl6, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
892 893
 {
893
-  if (rl) 
894
-      redirect_default_route_to_vpn (rl, tt, flags, es);
895
-
896
-  if (rl && !rl->routes_added)
894
+  redirect_default_route_to_vpn (rl, tt, flags, es);
895
+  if (!(rl->iflags & RL_ROUTES_ADDED))
897 896
     {
898 897
       int i;
899 898
 
... ...
@@ -913,12 +1007,11 @@ add_routes (struct route_list *rl, struct route_ipv6_list *rl6,
913 913
 	  struct route *r = &rl->routes[i];
914 914
 	  check_subnet_conflict (r->network, r->netmask, "route");
915 915
 	  if (flags & ROUTE_DELETE_FIRST)
916
-	    delete_route (r, tt, flags, es);
917
-	  add_route (r, tt, flags, es);
916
+	    delete_route (r, tt, flags, &rl->rgi, es);
917
+	  add_route (r, tt, flags, &rl->rgi, es);
918 918
 	}
919
-      rl->routes_added = true;
919
+      rl->iflags |= RL_ROUTES_ADDED;
920 920
     }
921
-
922 921
   if (rl6 && !rl6->routes_added)
923 922
     {
924 923
       int i;
... ...
@@ -938,22 +1031,19 @@ void
938 938
 delete_routes (struct route_list *rl, struct route_ipv6_list *rl6,
939 939
 	       const struct tuntap *tt, unsigned int flags, const struct env_set *es)
940 940
 {
941
-  if (rl && rl->routes_added)
941
+  if (rl->iflags & RL_ROUTES_ADDED)
942 942
     {
943 943
       int i;
944 944
       for (i = rl->n - 1; i >= 0; --i)
945 945
 	{
946 946
 	  const struct route *r = &rl->routes[i];
947
-	  delete_route (r, tt, flags, es);
947
+	  delete_route (r, tt, flags, &rl->rgi, es);
948 948
 	}
949
-      rl->routes_added = false;
949
+      rl->iflags &= ~RL_ROUTES_ADDED;
950 950
     }
951 951
 
952
-  if ( rl )
953
-    {
954
-      undo_redirect_default_route_to_vpn (rl, tt, flags, es);
955
-      clear_route_list (rl);
956
-    }
952
+   undo_redirect_default_route_to_vpn (rl, tt, flags, es);
953
+   clear_route_list (rl);
957 954
 
958 955
   if ( rl6 && rl6->routes_added )
959 956
     {
... ...
@@ -1005,13 +1095,38 @@ print_route_options (const struct route_option_list *rol,
1005 1005
     print_route_option (&rol->routes[i], level);
1006 1006
 }
1007 1007
 
1008
+void
1009
+print_default_gateway(const int msglevel, const struct route_gateway_info *rgi)
1010
+{
1011
+  struct gc_arena gc = gc_new ();
1012
+  if (rgi->flags & RGI_ADDR_DEFINED)
1013
+    {
1014
+      struct buffer out = alloc_buf_gc (256, &gc);
1015
+      buf_printf (&out, "ROUTE_GATEWAY");
1016
+      buf_printf (&out, " %s", print_in_addr_t (rgi->gateway.addr, 0, &gc));
1017
+      if (rgi->flags & RGI_NETMASK_DEFINED)
1018
+	buf_printf (&out, "/%s", print_in_addr_t (rgi->gateway.netmask, 0, &gc));
1019
+#ifdef WIN32
1020
+      if (rgi->flags & RGI_IFACE_DEFINED)
1021
+	buf_printf (&out, " I=%u", (unsigned int)rgi->adapter_index);
1022
+#else
1023
+      if (rgi->flags & RGI_IFACE_DEFINED)
1024
+	buf_printf (&out, " IFACE=%s", rgi->iface);
1025
+#endif
1026
+      if (rgi->flags & RGI_HWADDR_DEFINED)
1027
+	buf_printf (&out, " HWADDR=%s", format_hex_ex (rgi->hwaddr, 6, 0, 1, ":", &gc));
1028
+      msg (msglevel, "%s", BSTR (&out));
1029
+    }
1030
+  gc_free (&gc);
1031
+}
1032
+
1008 1033
 #endif
1009 1034
 
1010 1035
 static void
1011 1036
 print_route (const struct route *r, int level)
1012 1037
 {
1013 1038
   struct gc_arena gc = gc_new ();
1014
-  if (r->defined)
1039
+  if (r->flags & RT_DEFINED)
1015 1040
     msg (level, "%s", route_string (r, &gc));
1016 1041
   gc_free (&gc);
1017 1042
 }
... ...
@@ -1028,13 +1143,13 @@ static void
1028 1028
 setenv_route (struct env_set *es, const struct route *r, int i)
1029 1029
 {
1030 1030
   struct gc_arena gc = gc_new ();
1031
-  if (r->defined)
1031
+  if (r->flags & RT_DEFINED)
1032 1032
     {
1033 1033
       setenv_route_addr (es, "network", r->network, i);
1034 1034
       setenv_route_addr (es, "netmask", r->netmask, i);
1035 1035
       setenv_route_addr (es, "gateway", r->gateway, i);
1036 1036
 
1037
-      if (r->metric_defined)
1037
+      if (r->flags & RT_METRIC_DEFINED)
1038 1038
 	{
1039 1039
 	  struct buffer name = alloc_buf_gc (256, &gc);
1040 1040
 	  buf_printf (&name, "route_metric_%d", i);
... ...
@@ -1080,8 +1195,65 @@ setenv_routes_ipv6 (struct env_set *es, const struct route_ipv6_list *rl6)
1080 1080
     setenv_route_ipv6 (es, &rl6->routes_ipv6[i], i + 1);
1081 1081
 }
1082 1082
 
1083
+/*
1084
+ * local_route() determines whether the gateway of a provided host
1085
+ * route is on the same interface that owns the default gateway.
1086
+ * It uses the data structure
1087
+ * returned by get_default_gateway() (struct route_gateway_info)
1088
+ * to determine this.  If the route is local, LR_MATCH is returned.
1089
+ * When adding routes into the kernel, if LR_MATCH is defined for
1090
+ * a given route, the route should explicitly reference the default
1091
+ * gateway interface as the route destination.  For example, here
1092
+ * is an example on Linux that uses LR_MATCH:
1093
+ *
1094
+ *   route add -net 10.10.0.1 netmask 255.255.255.255 dev eth0
1095
+ *
1096
+ * This capability is needed by the "default-gateway block-local"
1097
+ * directive, to allow client access to the local subnet to be
1098
+ * blocked but still allow access to the local default gateway.
1099
+ */
1100
+
1101
+/* local_route() return values */
1102
+#define LR_NOMATCH 0 /* route is not local */
1103
+#define LR_MATCH   1 /* route is local */
1104
+#define LR_ERROR   2 /* caller should abort adding route */
1105
+
1106
+static int
1107
+local_route (in_addr_t network,
1108
+	     in_addr_t netmask,
1109
+	     in_addr_t gateway,
1110
+	     const struct route_gateway_info *rgi)
1111
+{
1112
+  /* set LR_MATCH on local host routes */
1113
+  const int rgi_needed = (RGI_ADDR_DEFINED|RGI_NETMASK_DEFINED|RGI_IFACE_DEFINED);
1114
+  if (rgi
1115
+      && (rgi->flags & rgi_needed) == rgi_needed
1116
+      && gateway == rgi->gateway.addr
1117
+      && netmask == 0xFFFFFFFF)
1118
+    {
1119
+      if (((network ^  rgi->gateway.addr) & rgi->gateway.netmask) == 0)
1120
+	return LR_MATCH;
1121
+      else
1122
+	{
1123
+	  /* examine additional subnets on gateway interface */
1124
+	  size_t i;
1125
+	  for (i = 0; i < rgi->n_addrs; ++i)
1126
+	    {
1127
+	      const struct route_gateway_address *gwa = &rgi->addrs[i];
1128
+	      if (((network ^ gwa->addr) & gwa->netmask) == 0)
1129
+		return LR_MATCH;
1130
+	    }
1131
+	}
1132
+    }
1133
+    return LR_NOMATCH;
1134
+}
1135
+
1083 1136
 void
1084
-add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
1137
+add_route (struct route *r,
1138
+	   const struct tuntap *tt,
1139
+	   unsigned int flags,
1140
+	   const struct route_gateway_info *rgi, /* may be NULL */
1141
+	   const struct env_set *es)
1085 1142
 {
1086 1143
   struct gc_arena gc;
1087 1144
   struct argv argv;
... ...
@@ -1089,8 +1261,9 @@ add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const s
1089 1089
   const char *netmask;
1090 1090
   const char *gateway;
1091 1091
   bool status = false;
1092
+  int is_local_route;
1092 1093
 
1093
-  if (!r->defined)
1094
+  if (!(r->flags & RT_DEFINED))
1094 1095
     return;
1095 1096
 
1096 1097
   gc_init (&gc);
... ...
@@ -1100,78 +1273,84 @@ add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const s
1100 1100
   netmask = print_in_addr_t (r->netmask, 0, &gc);
1101 1101
   gateway = print_in_addr_t (r->gateway, 0, &gc);
1102 1102
 
1103
-  /*
1104
-   * Filter out routes which are essentially no-ops
1105
-   */
1106
-  if (r->network == r->gateway && r->netmask == 0xFFFFFFFF)
1107
-    {
1108
-      msg (M_INFO, PACKAGE_NAME " ROUTE: omitted no-op route: %s/%s -> %s",
1109
-	   network, netmask, gateway);
1110
-      goto done;
1111
-    }
1103
+  is_local_route = local_route(r->network, r->netmask, r->gateway, rgi);
1104
+  if (is_local_route == LR_ERROR)
1105
+    goto done;
1112 1106
 
1113 1107
 #if defined(TARGET_LINUX)
1114 1108
 #ifdef CONFIG_FEATURE_IPROUTE
1109
+  /* FIXME -- add LR_MATCH support for CONFIG_FEATURE_IPROUTE */
1115 1110
   argv_printf (&argv, "%s route add %s/%d via %s",
1116 1111
   	      iproute_path,
1117 1112
 	      network,
1118 1113
 	      count_netmask_bits(netmask),
1119 1114
 	      gateway);
1120
-  if (r->metric_defined)
1115
+  if (r->flags & RT_METRIC_DEFINED)
1121 1116
     argv_printf_cat (&argv, "metric %d", r->metric);
1122 1117
 
1123 1118
 #else
1124
-  argv_printf (&argv, "%s add -net %s netmask %s gw %s",
1125
-		ROUTE_PATH,
1126
-	      network,
1127
-	      netmask,
1128
-	      gateway);
1129
-  if (r->metric_defined)
1119
+  argv_printf (&argv, "%s add -net %s netmask %s",
1120
+	       ROUTE_PATH,
1121
+	       network,
1122
+	       netmask);
1123
+  if (r->flags & RT_METRIC_DEFINED)
1130 1124
     argv_printf_cat (&argv, "metric %d", r->metric);
1125
+  if (rgi && is_local_route == LR_MATCH)
1126
+    argv_printf_cat (&argv, "dev %s", rgi->iface);
1127
+  else
1128
+    argv_printf_cat (&argv, "gw %s", gateway);
1129
+
1131 1130
 #endif  /*CONFIG_FEATURE_IPROUTE*/
1132 1131
   argv_msg (D_ROUTE, &argv);
1133 1132
   status = openvpn_execve_check (&argv, es, 0, "ERROR: Linux route add command failed");
1134 1133
 
1135 1134
 #elif defined (WIN32)
1135
+  {
1136
+    DWORD ai = ~0;
1137
+    argv_printf (&argv, "%s%sc ADD %s MASK %s %s",
1138
+		 get_win_sys_path(),
1139
+		 WIN_ROUTE_PATH_SUFFIX,
1140
+		 network,
1141
+		 netmask,
1142
+		 gateway);
1143
+    if (r->flags & RT_METRIC_DEFINED)
1144
+      argv_printf_cat (&argv, "METRIC %d", r->metric);
1145
+    if (rgi && is_local_route == LR_MATCH)
1146
+      {
1147
+	ai = rgi->adapter_index;
1148
+	argv_printf_cat (&argv, "IF %u", (unsigned int)ai);
1149
+      }
1136 1150
 
1137
-  argv_printf (&argv, "%s%sc ADD %s MASK %s %s",
1138
-	       get_win_sys_path(),
1139
-	       WIN_ROUTE_PATH_SUFFIX,
1140
-	       network,
1141
-	       netmask,
1142
-	       gateway);
1143
-  if (r->metric_defined)
1144
-    argv_printf_cat (&argv, "METRIC %d", r->metric);
1145
-
1146
-  argv_msg (D_ROUTE, &argv);
1151
+    argv_msg (D_ROUTE, &argv);
1147 1152
 
1148
-  if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_IPAPI)
1149
-    {
1150
-      status = add_route_ipapi (r, tt);
1151
-      msg (D_ROUTE, "Route addition via IPAPI %s", status ? "succeeded" : "failed");
1152
-    }
1153
-  else if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_EXE)
1154
-    {
1155
-      netcmd_semaphore_lock ();
1156
-      status = openvpn_execve_check (&argv, es, 0, "ERROR: Windows route add command failed");
1157
-      netcmd_semaphore_release ();
1158
-    }
1159
-  else if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_ADAPTIVE)
1160
-    {
1161
-      status = add_route_ipapi (r, tt);
1162
-      msg (D_ROUTE, "Route addition via IPAPI %s [adaptive]", status ? "succeeded" : "failed");
1163
-      if (!status)
1164
-	{
1165
-	  msg (D_ROUTE, "Route addition fallback to route.exe");
1166
-	  netcmd_semaphore_lock ();
1167
-	  status = openvpn_execve_check (&argv, es, 0, "ERROR: Windows route add command failed [adaptive]");
1168
-	  netcmd_semaphore_release ();
1169
-	}
1170
-    }
1171
-  else
1172
-    {
1173
-      ASSERT (0);
1174
-    }
1153
+    if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_IPAPI)
1154
+      {
1155
+	status = add_route_ipapi (r, tt, ai);
1156
+	msg (D_ROUTE, "Route addition via IPAPI %s", status ? "succeeded" : "failed");
1157
+      }
1158
+    else if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_EXE)
1159
+      {
1160
+	netcmd_semaphore_lock ();
1161
+	status = openvpn_execve_check (&argv, es, 0, "ERROR: Windows route add command failed");
1162
+	netcmd_semaphore_release ();
1163
+      }
1164
+    else if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_ADAPTIVE)
1165
+      {
1166
+	status = add_route_ipapi (r, tt, ai);
1167
+	msg (D_ROUTE, "Route addition via IPAPI %s [adaptive]", status ? "succeeded" : "failed");
1168
+	if (!status)
1169
+	  {
1170
+	    msg (D_ROUTE, "Route addition fallback to route.exe");
1171
+	    netcmd_semaphore_lock ();
1172
+	    status = openvpn_execve_check (&argv, es, 0, "ERROR: Windows route add command failed [adaptive]");
1173
+	    netcmd_semaphore_release ();
1174
+	  }
1175
+      }
1176
+    else
1177
+      {
1178
+	ASSERT (0);
1179
+      }
1180
+  }
1175 1181
 
1176 1182
 #elif defined (TARGET_SOLARIS)
1177 1183
 
... ...
@@ -1180,13 +1359,17 @@ add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const s
1180 1180
   argv_printf (&argv, "%s add",
1181 1181
 		ROUTE_PATH);
1182 1182
 
1183
+#if 0
1184
+  if (r->flags & RT_METRIC_DEFINED)
1185
+    argv_printf_cat (&argv, "-rtt %d", r->metric);
1186
+#endif
1187
+
1183 1188
   argv_printf_cat (&argv, "%s -netmask %s %s",
1184 1189
 	      network,
1185 1190
 	      netmask,
1186 1191
 	      gateway);
1187 1192
 
1188
-  if (r->metric_defined)
1189
-    argv_printf_cat (&argv, "%d", r->metric);
1193
+  /* FIXME -- add LR_MATCH support for Solaris */
1190 1194
 
1191 1195
   argv_msg (D_ROUTE, &argv);
1192 1196
   status = openvpn_execve_check (&argv, es, 0, "ERROR: Solaris route add command failed");
... ...
@@ -1197,7 +1380,7 @@ add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const s
1197 1197
 		ROUTE_PATH);
1198 1198
 
1199 1199
 #if 0
1200
-  if (r->metric_defined)
1200
+  if (r->flags & RT_METRIC_DEFINED)
1201 1201
     argv_printf_cat (&argv, "-rtt %d", r->metric);
1202 1202
 #endif
1203 1203
 
... ...
@@ -1206,6 +1389,8 @@ add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const s
1206 1206
 	      gateway,
1207 1207
 	      netmask);
1208 1208
 
1209
+  /* FIXME -- add LR_MATCH support for FreeBSD */
1210
+
1209 1211
   argv_msg (D_ROUTE, &argv);
1210 1212
   status = openvpn_execve_check (&argv, es, 0, "ERROR: FreeBSD route add command failed");
1211 1213
 
... ...
@@ -1215,7 +1400,7 @@ add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const s
1215 1215
 		ROUTE_PATH);
1216 1216
 
1217 1217
 #if 0
1218
-  if (r->metric_defined)
1218
+  if (r->flags & RT_METRIC_DEFINED)
1219 1219
     argv_printf_cat (&argv, "-rtt %d", r->metric);
1220 1220
 #endif
1221 1221
 
... ...
@@ -1224,6 +1409,8 @@ add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const s
1224 1224
 	      gateway,
1225 1225
 	      netmask);
1226 1226
 
1227
+  /* FIXME -- add LR_MATCH support for Dragonfly */
1228
+
1227 1229
   argv_msg (D_ROUTE, &argv);
1228 1230
   status = openvpn_execve_check (&argv, es, 0, "ERROR: DragonFly route add command failed");
1229 1231
 
... ...
@@ -1233,14 +1420,26 @@ add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const s
1233 1233
 		ROUTE_PATH);
1234 1234
 
1235 1235
 #if 0
1236
-  if (r->metric_defined)
1236
+  if (r->flags & RT_METRIC_DEFINED)
1237 1237
     argv_printf_cat (&argv, "-rtt %d", r->metric);
1238 1238
 #endif
1239 1239
 
1240
-  argv_printf_cat (&argv, "-net %s %s %s",
1241
-              network,
1242
-              gateway,
1243
-              netmask);
1240
+  if (rgi && is_local_route == LR_MATCH)
1241
+    {
1242
+      /* Mac OS X route syntax for LR_MATCH:
1243
+	 route add -cloning -net 10.10.0.1 -netmask 255.255.255.255 -interface en0 */
1244
+      argv_printf_cat (&argv, "-cloning -net %s -netmask %s -interface %s",
1245
+		       network,
1246
+		       netmask,
1247
+		       rgi->iface);
1248
+    }
1249
+  else
1250
+    {
1251
+      argv_printf_cat (&argv, "-net %s %s %s",
1252
+		       network,
1253
+		       gateway,
1254
+		       netmask);
1255
+    }
1244 1256
 
1245 1257
   argv_msg (D_ROUTE, &argv);
1246 1258
   status = openvpn_execve_check (&argv, es, 0, "ERROR: OS X route add command failed");
... ...
@@ -1251,7 +1450,7 @@ add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const s
1251 1251
 		ROUTE_PATH);
1252 1252
 
1253 1253
 #if 0
1254
-  if (r->metric_defined)
1254
+  if (r->flags & RT_METRIC_DEFINED)
1255 1255
     argv_printf_cat (&argv, "-rtt %d", r->metric);
1256 1256
 #endif
1257 1257
 
... ...
@@ -1260,6 +1459,8 @@ add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const s
1260 1260
 	      gateway,
1261 1261
 	      netmask);
1262 1262
 
1263
+  /* FIXME -- add LR_MATCH support for OpenBSD/NetBSD */
1264
+
1263 1265
   argv_msg (D_ROUTE, &argv);
1264 1266
   status = openvpn_execve_check (&argv, es, 0, "ERROR: OpenBSD/NetBSD route add command failed");
1265 1267
 
... ...
@@ -1268,7 +1469,10 @@ add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const s
1268 1268
 #endif
1269 1269
 
1270 1270
  done:
1271
-  r->defined = status;
1271
+  if (status)
1272
+    r->flags |= RT_ADDED;
1273
+  else
1274
+    r->flags &= ~RT_ADDED;
1272 1275
   argv_reset (&argv);
1273 1276
   gc_free (&gc);
1274 1277
 }
... ...
@@ -1455,15 +1659,20 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int fla
1455 1455
 }
1456 1456
 
1457 1457
 static void
1458
-delete_route (const struct route *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
1458
+delete_route (struct route *r,
1459
+	      const struct tuntap *tt,
1460
+	      unsigned int flags,
1461
+	      const struct route_gateway_info *rgi,
1462
+	      const struct env_set *es)
1459 1463
 {
1460 1464
   struct gc_arena gc;
1461 1465
   struct argv argv;
1462 1466
   const char *network;
1463 1467
   const char *netmask;
1464 1468
   const char *gateway;
1469
+  int is_local_route;
1465 1470
 
1466
-  if (!r->defined)
1471
+  if ((r->flags & (RT_DEFINED|RT_ADDED)) != (RT_DEFINED|RT_ADDED))
1467 1472
     return;
1468 1473
 
1469 1474
   gc_init (&gc);
... ...
@@ -1473,6 +1682,10 @@ delete_route (const struct route *r, const struct tuntap *tt, unsigned int flags
1473 1473
   netmask = print_in_addr_t (r->netmask, 0, &gc);
1474 1474
   gateway = print_in_addr_t (r->gateway, 0, &gc);
1475 1475
 
1476
+  is_local_route = local_route(r->network, r->netmask, r->gateway, rgi);
1477
+  if (is_local_route == LR_ERROR)
1478
+    goto done;
1479
+
1476 1480
 #if defined(TARGET_LINUX)
1477 1481
 #ifdef CONFIG_FEATURE_IPROUTE
1478 1482
   argv_printf (&argv, "%s route del %s/%d",
... ...
@@ -1480,13 +1693,12 @@ delete_route (const struct route *r, const struct tuntap *tt, unsigned int flags
1480 1480
 	      network,
1481 1481
 	      count_netmask_bits(netmask));
1482 1482
 #else
1483
-
1484 1483
   argv_printf (&argv, "%s del -net %s netmask %s",
1485
-		ROUTE_PATH,
1486
-	      network,
1487
-	      netmask);
1484
+	       ROUTE_PATH,
1485
+	       network,
1486
+	       netmask);
1488 1487
 #endif /*CONFIG_FEATURE_IPROUTE*/
1489
-  if (r->metric_defined)
1488
+  if (r->flags & RT_METRIC_DEFINED)
1490 1489
     argv_printf_cat (&argv, "metric %d", r->metric);
1491 1490
   argv_msg (D_ROUTE, &argv);
1492 1491
   openvpn_execve_check (&argv, es, 0, "ERROR: Linux route delete command failed");
... ...
@@ -1565,11 +1777,22 @@ delete_route (const struct route *r, const struct tuntap *tt, unsigned int flags
1565 1565
 
1566 1566
 #elif defined(TARGET_DARWIN)
1567 1567
 
1568
-  argv_printf (&argv, "%s delete -net %s %s %s",
1569
-		ROUTE_PATH,
1570
-              network,
1571
-              gateway,
1572
-              netmask);
1568
+  if (rgi && is_local_route == LR_MATCH)
1569
+    {
1570
+      argv_printf (&argv, "%s delete -cloning -net %s -netmask %s -interface %s",
1571
+		   ROUTE_PATH,
1572
+		   network,
1573
+		   netmask,
1574
+		   rgi->iface);
1575
+    }
1576
+  else
1577
+    {
1578
+      argv_printf (&argv, "%s delete -net %s %s %s",
1579
+		   ROUTE_PATH,
1580
+		   network,
1581
+		   gateway,
1582
+		   netmask);
1583
+    }
1573 1584
 
1574 1585
   argv_msg (D_ROUTE, &argv);
1575 1586
   openvpn_execve_check (&argv, es, 0, "ERROR: OS X route delete command failed");
... ...
@@ -1589,6 +1812,8 @@ delete_route (const struct route *r, const struct tuntap *tt, unsigned int flags
1589 1589
   msg (M_FATAL, "Sorry, but I don't know how to do 'route' commands on this operating system.  Try putting your routes in a --route-up script");
1590 1590
 #endif
1591 1591
 
1592
+ done:
1593
+  r->flags &= ~RT_ADDED;
1592 1594
   argv_reset (&argv);
1593 1595
   gc_free (&gc);
1594 1596
 }
... ...
@@ -1816,7 +2041,7 @@ test_routes (const struct route_list *rl, const struct tuntap *tt)
1816 1816
 	  for (i = 0; i < rl->n; ++i)
1817 1817
 	    test_route_helper (&ret, &count, &good, &ambig, adapters, rl->routes[i].gateway);
1818 1818
 
1819
-	  if ((rl->flags & RG_ENABLE) && rl->spec.remote_endpoint_defined)
1819
+	  if ((rl->flags & RG_ENABLE) && (rl->spec.flags & RTSA_REMOTE_ENDPOINT))
1820 1820
 	    test_route_helper (&ret, &count, &good, &ambig, adapters, rl->spec.remote_endpoint);
1821 1821
 	}
1822 1822
     }
... ...
@@ -1874,29 +2099,41 @@ get_default_gateway_row (const MIB_IPFORWARDTABLE *routes)
1874 1874
   return ret;
1875 1875
 }
1876 1876
 
1877
-bool
1878
-get_default_gateway (in_addr_t *gw, in_addr_t *netmask)
1877
+void
1878
+get_default_gateway (struct route_gateway_info *rgi)
1879 1879
 {
1880 1880
   struct gc_arena gc = gc_new ();
1881
-  bool ret_bool = false;
1882 1881
 
1883 1882
   const IP_ADAPTER_INFO *adapters = get_adapter_info_list (&gc);
1884 1883
   const MIB_IPFORWARDTABLE *routes = get_windows_routing_table (&gc);
1885 1884
   const MIB_IPFORWARDROW *row = get_default_gateway_row (routes);
1885
+  DWORD a_index;
1886
+  const IP_ADAPTER_INFO *ai;
1887
+
1888
+  CLEAR(*rgi);
1886 1889
 
1887 1890
   if (row)
1888 1891
     {
1889
-      *gw = ntohl (row->dwForwardNextHop);
1890
-      if (netmask)
1892
+      rgi->gateway.addr = ntohl (row->dwForwardNextHop);
1893
+      if (rgi->gateway.addr)
1891 1894
 	{
1892
-	  if (adapter_index_of_ip (adapters, *gw, NULL, netmask) == ~0)
1893
-	    *netmask = ~0;
1895
+	  rgi->flags |= RGI_ADDR_DEFINED;
1896
+	  a_index = adapter_index_of_ip (adapters, rgi->gateway.addr, NULL, &rgi->gateway.netmask);
1897
+	  if (a_index != ~0)
1898
+	    {
1899
+	      rgi->adapter_index = a_index;
1900
+	      rgi->flags |= (RGI_IFACE_DEFINED|RGI_NETMASK_DEFINED);
1901
+	      ai = get_adapter (adapters, a_index);
1902
+	      if (ai)
1903
+		{
1904
+		  memcpy (rgi->hwaddr, ai->Address, 6);
1905
+		  rgi->flags |= RGI_HWADDR_DEFINED;
1906
+		}
1907
+	    }
1894 1908
 	}
1895
-      ret_bool = true;
1896 1909
     }
1897 1910
 
1898 1911
   gc_free (&gc);
1899
-  return ret_bool;
1900 1912
 }
1901 1913
 
1902 1914
 static DWORD
... ...
@@ -1945,12 +2182,12 @@ windows_route_find_if_index (const struct route *r, const struct tuntap *tt)
1945 1945
 }
1946 1946
 
1947 1947
 bool
1948
-add_route_ipapi (const struct route *r, const struct tuntap *tt)
1948
+add_route_ipapi (const struct route *r, const struct tuntap *tt, DWORD adapter_index)
1949 1949
 {
1950 1950
   struct gc_arena gc = gc_new ();
1951 1951
   bool ret = false;
1952 1952
   DWORD status;
1953
-  const DWORD if_index = windows_route_find_if_index (r, tt);  
1953
+  const DWORD if_index = (adapter_index == ~0) ? windows_route_find_if_index (r, tt) : adapter_index;
1954 1954
 
1955 1955
   if (if_index != ~0)
1956 1956
     {
... ...
@@ -1965,7 +2202,7 @@ add_route_ipapi (const struct route *r, const struct tuntap *tt)
1965 1965
       fr.dwForwardProto = 3; /* PROTO_IP_NETMGMT */
1966 1966
       fr.dwForwardAge = 0;
1967 1967
       fr.dwForwardNextHopAS = 0;
1968
-      fr.dwForwardMetric1 = r->metric_defined ? r->metric : 1;
1968
+      fr.dwForwardMetric1 = (r->flags & RT_METRIC_DEFINED) ? r->metric : 1;
1969 1969
       fr.dwForwardMetric2 = ~0;
1970 1970
       fr.dwForwardMetric3 = ~0;
1971 1971
       fr.dwForwardMetric4 = ~0;
... ...
@@ -2096,75 +2333,136 @@ show_routes (int msglev)
2096 2096
 
2097 2097
 #elif defined(TARGET_LINUX)
2098 2098
 
2099
-bool
2100
-get_default_gateway (in_addr_t *gateway, in_addr_t *netmask)
2099
+void
2100
+get_default_gateway (struct route_gateway_info *rgi)
2101 2101
 {
2102 2102
   struct gc_arena gc = gc_new ();
2103
-  bool ret = false;
2104
-  FILE *fp = fopen ("/proc/net/route", "r");
2105
-  if (fp)
2106
-    {
2107
-      char line[256];
2108
-      int count = 0;
2109
-      int best_count = 0;
2110
-      unsigned int lowest_metric = ~0;
2111
-      in_addr_t best_gw = 0;
2112
-      while (fgets (line, sizeof (line), fp) != NULL)
2103
+  int sd = -1;
2104
+
2105
+  CLEAR(*rgi);
2106
+
2107
+  /* get default gateway IP addr */
2108
+  {
2109
+    FILE *fp = fopen ("/proc/net/route", "r");
2110
+    if (fp)
2111
+      {
2112
+	char line[256];
2113
+	int count = 0;
2114
+	unsigned int lowest_metric = ~0;
2115
+	in_addr_t best_gw = 0;
2116
+	while (fgets (line, sizeof (line), fp) != NULL)
2117
+	  {
2118
+	    if (count)
2119
+	      {
2120
+		unsigned int net_x = 0;
2121
+		unsigned int mask_x = 0;
2122
+		unsigned int gw_x = 0;
2123
+		unsigned int metric = 0;
2124
+		unsigned int flags = 0;
2125
+		const int np = sscanf (line, "%*s\t%x\t%x\t%x\t%*s\t%*s\t%d\t%x",
2126
+				       &net_x,
2127
+				       &gw_x,
2128
+				       &flags,
2129
+				       &metric,
2130
+				       &mask_x);
2131
+		if (np == 5 && (flags & IFF_UP))
2132
+		  {
2133
+		    const in_addr_t net = ntohl (net_x);
2134
+		    const in_addr_t mask = ntohl (mask_x);
2135
+		    const in_addr_t gw = ntohl (gw_x);
2136
+
2137
+		    if (!net && !mask && metric < lowest_metric)
2138
+		      {
2139
+			best_gw = gw;
2140
+			lowest_metric = metric;
2141
+		      }
2142
+		  }
2143
+	      }
2144
+	    ++count;
2145
+	  }
2146
+	fclose (fp);
2147
+
2148
+	if (best_gw)
2149
+	  {
2150
+	    rgi->gateway.addr = best_gw;
2151
+	    rgi->flags |= RGI_ADDR_DEFINED;
2152
+	  }
2153
+      }
2154
+  }
2155
+
2156
+  /* scan adapter list */
2157
+  if (rgi->flags & RGI_ADDR_DEFINED)
2158
+    {
2159
+      struct ifreq *ifr, *ifend;
2160
+      in_addr_t addr, netmask;
2161
+      struct ifreq ifreq;
2162
+      struct ifconf ifc;
2163
+      struct ifreq ifs[20]; /* Maximum number of interfaces to scan */
2164
+
2165
+      if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
2113 2166
 	{
2114
-	  if (count)
2115
-	    {
2116
-	      unsigned int net_x = 0;
2117
-	      unsigned int mask_x = 0;
2118
-	      unsigned int gw_x = 0;
2119
-	      unsigned int metric = 0;
2120
-	      const int np = sscanf (line, "%*s\t%x\t%x\t%*s\t%*s\t%*s\t%d\t%x",
2121
-				     &net_x,
2122
-				     &gw_x,
2123
-				     &metric,
2124
-				     &mask_x);
2125
-	      if (np == 4)
2126
-		{
2127
-		  const in_addr_t net = ntohl (net_x);
2128
-		  const in_addr_t mask = ntohl (mask_x);
2129
-		  const in_addr_t gw = ntohl (gw_x);
2130
-
2131
-		  dmsg (D_ROUTE_DEBUG, "GDG: route[%d] %s/%s/%s m=%u",
2132
-			count,
2133
-			print_in_addr_t ((in_addr_t) net, 0, &gc),
2134
-			print_in_addr_t ((in_addr_t) mask, 0, &gc),
2135
-			print_in_addr_t ((in_addr_t) gw, 0, &gc),
2136
-			metric);
2137
-
2138
-		  if (!net && !mask && metric < lowest_metric)
2139
-		    {
2140
-		      best_gw = gw;
2141
-		      lowest_metric = metric;
2142
-		      best_count = count;
2143
-		    }
2144
-		}
2145
-	    }
2146
-	  ++count;
2167
+	  msg (M_WARN, "GDG: socket() failed");
2168
+	  goto done;
2169
+	}
2170
+      ifc.ifc_len = sizeof (ifs);
2171
+      ifc.ifc_req = ifs;
2172
+      if (ioctl (sd, SIOCGIFCONF, &ifc) < 0)
2173
+	{
2174
+	  msg (M_WARN, "GDG: ioctl(SIOCGIFCONF) failed");
2175
+	  goto done;
2147 2176
 	}
2148
-      fclose (fp);
2149 2177
 
2150
-      if (best_gw)
2178
+      /* scan through interface list */
2179
+      ifend = ifs + (ifc.ifc_len / sizeof (struct ifreq));
2180
+      for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
2151 2181
 	{
2152
-	  *gateway = best_gw;
2153
-	  if (netmask)
2182
+	  if (ifr->ifr_addr.sa_family == AF_INET)
2154 2183
 	    {
2155
-	      *netmask = 0xFFFFFF00; /* FIXME -- get the real netmask of the adapter containing the default gateway */
2184
+	      /* get interface addr */
2185
+	      addr = ntohl(((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr);
2186
+
2187
+	      /* get interface name */
2188
+	      strncpynt (ifreq.ifr_name, ifr->ifr_name, sizeof (ifreq.ifr_name));
2189
+
2190
+	      /* check that the interface is up, and not point-to-point or loopback */
2191
+	      if (ioctl (sd, SIOCGIFFLAGS, &ifreq) < 0)
2192
+		continue;
2193
+	      if (!(ifreq.ifr_flags & IFF_UP))
2194
+		continue;
2195
+
2196
+	      /* get interface netmask */
2197
+	      if (ioctl (sd, SIOCGIFNETMASK, &ifreq) < 0)
2198
+		continue;
2199
+	      netmask = ntohl(((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
2200
+
2201
+	      /* check that interface matches default route */
2202
+	      if (((rgi->gateway.addr ^ addr) & netmask) != 0)
2203
+		continue;
2204
+
2205
+	      /* save iface name and netmask */
2206
+	      strncpynt (rgi->iface, ifreq.ifr_name, sizeof(rgi->iface));
2207
+	      rgi->gateway.netmask = netmask;
2208
+	      rgi->flags |= (RGI_IFACE_DEFINED|RGI_NETMASK_DEFINED);
2209
+
2210
+	      /* now get the hardware address. */
2211
+	      memset (&ifreq.ifr_hwaddr, 0, sizeof (struct sockaddr));
2212
+	      if (ioctl (sd, SIOCGIFHWADDR, &ifreq) < 0)
2213
+		{
2214
+		  msg (M_WARN, "GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
2215
+		  goto done;
2216
+		}
2217
+	      memcpy (rgi->hwaddr, &ifreq.ifr_hwaddr.sa_data, 6);
2218
+	      rgi->flags |= RGI_HWADDR_DEFINED;
2219
+
2220
+	      break;
2156 2221
 	    }
2157
-	  ret = true;
2158 2222
 	}
2159
-
2160
-      dmsg (D_ROUTE_DEBUG, "GDG: best=%s[%d] lm=%u",
2161
-	    print_in_addr_t ((in_addr_t) best_gw, 0, &gc),
2162
-	    best_count,
2163
-	    (unsigned int)lowest_metric);
2164 2223
     }
2165 2224
 
2225
+ done:
2226
+  if (sd >= 0)
2227
+    close (sd);
2166 2228
   gc_free (&gc);
2167
-  return ret;
2168 2229
 }
2169 2230
 
2170 2231
 #elif defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY)
... ...
@@ -2228,8 +2526,11 @@ struct {
2228 2228
 #define ROUNDUP(a) \
2229 2229
         ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
2230 2230
 
2231
-bool
2232
-get_default_gateway (in_addr_t *ret, in_addr_t *netmask)
2231
+/*
2232
+ * FIXME -- add support for netmask, hwaddr, and iface
2233
+ */
2234
+void
2235
+get_default_gateway (struct route_gateway_info *rgi)
2233 2236
 {
2234 2237
   struct gc_arena gc = gc_new ();
2235 2238
   int s, seq, l, pid, rtm_addrs, i;
... ...
@@ -2247,6 +2548,8 @@ get_default_gateway (in_addr_t *ret, in_addr_t *netmask)
2247 2247
 
2248 2248
 #define rtm m_rtmsg.m_rtm
2249 2249
 
2250
+  CLEAR(*rgi);
2251
+
2250 2252
   pid = getpid();
2251 2253
   seq = 0;
2252 2254
   rtm_addrs = RTA_DST | RTA_NETMASK;
... ...
@@ -2308,24 +2611,14 @@ get_default_gateway (in_addr_t *ret, in_addr_t *netmask)
2308 2308
 
2309 2309
   if (gate != NULL )
2310 2310
     {
2311
-      *ret = ntohl(((struct sockaddr_in *)gate)->sin_addr.s_addr);
2312
-#if 0
2313
-      msg (M_INFO, "gw %s",
2314
-	   print_in_addr_t ((in_addr_t) *ret, 0, &gc));
2315
-#endif
2316
-
2317
-      if (netmask)
2318
-	{
2319
-	  *netmask = 0xFFFFFF00; // FIXME -- get the real netmask of the adapter containing the default gateway
2320
-	}
2311
+      rgi->gateway.addr = ntohl(((struct sockaddr_in *)gate)->sin_addr.s_addr);
2312
+      rgi->flags |= RGI_ADDR_DEFINED;
2321 2313
 
2322 2314
       gc_free (&gc);
2323
-      return true;
2324 2315
     }
2325 2316
   else
2326 2317
     {
2327 2318
       gc_free (&gc);
2328
-      return false;
2329 2319
     }
2330 2320
 }
2331 2321
 
... ...
@@ -2345,26 +2638,32 @@ struct rtmsg {
2345 2345
 #define ROUNDUP(a) \
2346 2346
         ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
2347 2347
 
2348
-static bool
2349
-get_default_gateway_ex (in_addr_t *ret, in_addr_t *netmask, char **ifname)
2348
+#define NEXTADDR(w, u) \
2349
+        if (rtm_addrs & (w)) {\
2350
+            l = ROUNDUP(u.sa_len); memmove(cp, &(u), l); cp += l;\
2351
+        }
2352
+
2353
+#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
2354
+
2355
+#define max(a,b) ((a) > (b) ? (a) : (b))
2356
+
2357
+void
2358
+get_default_gateway (struct route_gateway_info *rgi)
2350 2359
 {
2351 2360
   struct gc_arena gc = gc_new ();
2352 2361
   struct rtmsg m_rtmsg;
2353
-  int s, seq, l, pid, rtm_addrs, i;
2362
+  int sockfd = -1;
2363
+  int seq, l, pid, rtm_addrs, i;
2354 2364
   struct sockaddr so_dst, so_mask;
2355 2365
   char *cp = m_rtmsg.m_space; 
2356 2366
   struct sockaddr *gate = NULL, *ifp = NULL, *sa;
2357 2367
   struct  rt_msghdr *rtm_aux;
2358 2368
 
2359
-#define NEXTADDR(w, u) \
2360
-        if (rtm_addrs & (w)) {\
2361
-            l = ROUNDUP(u.sa_len); memmove(cp, &(u), l); cp += l;\
2362
-        }
2363
-
2364
-#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
2369
+# define rtm m_rtmsg.m_rtm
2365 2370
 
2366
-#define rtm m_rtmsg.m_rtm
2371
+  CLEAR(*rgi);
2367 2372
 
2373
+  /* setup data to send to routing socket */
2368 2374
   pid = getpid();
2369 2375
   seq = 0;
2370 2376
   rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
... ...
@@ -2390,85 +2689,148 @@ get_default_gateway_ex (in_addr_t *ret, in_addr_t *netmask, char **ifname)
2390 2390
 
2391 2391
   rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
2392 2392
 
2393
-  s = socket(PF_ROUTE, SOCK_RAW, 0);
2394
-
2395
-  if (write(s, (char *)&m_rtmsg, l) < 0)
2393
+  /* transact with routing socket */
2394
+  sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
2395
+  if (sockfd < 0)
2396 2396
     {
2397
-      msg (M_WARN, "ROUTE: problem writing to routing socket");
2398
-      gc_free (&gc);
2399
-      close(s);
2400
-      return false;
2397
+      msg (M_WARN, "GDG: socket #1 failed");
2398
+      goto done;
2399
+    }
2400
+  if (write(sockfd, (char *)&m_rtmsg, l) < 0)
2401
+    {
2402
+      msg (M_WARN, "GDG: problem writing to routing socket");
2403
+      goto done;
2401 2404
     }
2402
-
2403 2405
   do {
2404
-    l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
2406
+    l = read(sockfd, (char *)&m_rtmsg, sizeof(m_rtmsg));
2405 2407
   } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
2406
-                        
2407
-  close(s);
2408
+  close(sockfd);
2409
+  sockfd = -1;
2408 2410
 
2411
+  /* extract return data from routing socket */
2409 2412
   rtm_aux = &rtm;
2410
-
2411 2413
   cp = ((char *)(rtm_aux + 1));
2412
-  if (rtm_aux->rtm_addrs) {
2413
-    for (i = 1; i; i <<= 1)
2414
-      {
2415
-	if (i & rtm_aux->rtm_addrs)
2416
-	  {
2417
-	    sa = (struct sockaddr *)cp;
2418
-	    if (i == RTA_GATEWAY )
2419
-	      gate = sa;
2420
-	    else if (i == RTA_IFP)
2421
-	      ifp = sa;
2422
-	    ADVANCE(cp, sa);
2423
-	  }
2424
-      }
2425
-  }
2414
+  if (rtm_aux->rtm_addrs)
2415
+    {
2416
+      for (i = 1; i; i <<= 1)
2417
+	{
2418
+	  if (i & rtm_aux->rtm_addrs)
2419
+	    {
2420
+	      sa = (struct sockaddr *)cp;
2421
+	      if (i == RTA_GATEWAY )
2422
+		gate = sa;
2423
+	      else if (i == RTA_IFP)
2424
+		ifp = sa;
2425
+	      ADVANCE(cp, sa);
2426
+	    }
2427
+	}
2428
+    }
2426 2429
   else
2430
+    goto done;
2431
+
2432
+  /* get gateway addr and interface name */
2433
+  if (gate != NULL )
2427 2434
     {
2428
-      gc_free (&gc);
2429
-      return false;
2435
+      /* get default gateway addr */
2436
+      rgi->gateway.addr = ntohl(((struct sockaddr_in *)gate)->sin_addr.s_addr);
2437
+      if (rgi->gateway.addr)
2438
+	  rgi->flags |= RGI_ADDR_DEFINED;
2439
+
2440
+      if (ifp)
2441
+	{
2442
+	  /* get interface name */
2443
+	  const struct sockaddr_dl *adl = (struct sockaddr_dl *) ifp;
2444
+	  int len = adl->sdl_nlen;
2445
+	  if (adl->sdl_nlen && adl->sdl_nlen < sizeof(rgi->iface))
2446
+	    {
2447
+	      memcpy (rgi->iface, adl->sdl_data, adl->sdl_nlen);
2448
+	      rgi->iface[adl->sdl_nlen] = '\0';
2449
+	      rgi->flags |= RGI_IFACE_DEFINED;
2450
+	    }
2451
+	}
2430 2452
     }
2431 2453
 
2454
+  /* get netmask of interface that owns default gateway */
2455
+  if (rgi->flags & RGI_IFACE_DEFINED) {
2456
+    struct ifreq ifr;
2432 2457
 
2433
-  if (gate != NULL )
2458
+    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
2459
+    if (sockfd < 0)
2460
+      {
2461
+	msg (M_WARN, "GDG: socket #2 failed");
2462
+	goto done;
2463
+      }
2464
+
2465
+    CLEAR(ifr);
2466
+    ifr.ifr_addr.sa_family = AF_INET;
2467
+    strncpynt(ifr.ifr_name, rgi->iface, IFNAMSIZ);
2468
+
2469
+    if (ioctl(sockfd, SIOCGIFNETMASK, (char *)&ifr) < 0)
2470
+      {
2471
+	msg (M_WARN, "GDG: ioctl #1 failed");
2472
+	goto done;
2473
+      }
2474
+    close(sockfd);
2475
+    sockfd = -1;
2476
+
2477
+    rgi->gateway.netmask = ntohl(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr);
2478
+    rgi->flags |= RGI_NETMASK_DEFINED;
2479
+  }
2480
+
2481
+  /* try to read MAC addr associated with interface that owns default gateway */
2482
+  if (rgi->flags & RGI_IFACE_DEFINED)
2434 2483
     {
2435
-      *ret = ntohl(((struct sockaddr_in *)gate)->sin_addr.s_addr);
2436
-#if 0
2437
-      msg (M_INFO, "gw %s",
2438
-	   print_in_addr_t ((in_addr_t) *ret, 0, &gc));
2439
-#endif
2484
+      struct ifconf ifc;
2485
+      struct ifreq *ifr;
2486
+      const int bufsize = 4096;
2487
+      char *buffer;
2440 2488
 
2441
-      if (netmask)
2489
+      buffer = (char *) gc_malloc (bufsize, true, &gc);
2490
+      sockfd = socket(AF_INET, SOCK_DGRAM, 0);
2491
+      if (sockfd < 0)
2442 2492
 	{
2443
-	  *netmask = 0xFFFFFF00; // FIXME -- get the real netmask of the adapter containing the default gateway
2493
+	  msg (M_WARN, "GDG: socket #3 failed");
2494
+	  goto done;
2444 2495
 	}
2445 2496
 
2446
-      if (ifp && ifname)
2497
+      ifc.ifc_len = bufsize;
2498
+      ifc.ifc_buf = buffer;
2499
+
2500
+      if (ioctl(sockfd, SIOCGIFCONF, (char *)&ifc) < 0)
2447 2501
 	{
2448
-	  struct sockaddr_dl *adl = (struct sockaddr_dl *) ifp;
2449
-	  char *name = malloc(adl->sdl_nlen+1);
2450
-	  check_malloc_return(name);
2451
-	  memcpy(name, adl->sdl_data, adl->sdl_nlen);
2452
-	  name[adl->sdl_nlen] = '\0';
2453
-	  *ifname = name;
2502
+	  msg (M_WARN, "GDG: ioctl #2 failed");
2503
+	  goto done;
2454 2504
 	}
2505
+      close(sockfd);
2506
+      sockfd = -1;
2455 2507
 
2456
-      gc_free (&gc);
2457
-      return true;
2458
-    }
2459
-  else
2460
-    {
2461
-      gc_free (&gc);
2462
-      return false;
2508
+      for (cp = buffer; cp <= buffer + ifc.ifc_len - sizeof(struct ifreq); )
2509
+	{
2510
+	  ifr = (struct ifreq *)cp;
2511
+	  const size_t len = sizeof(ifr->ifr_name) + max(sizeof(ifr->ifr_addr), ifr->ifr_addr.sa_len);
2512
+	  if (!ifr->ifr_addr.sa_family)
2513
+	    break;
2514
+	  if (!strncmp(ifr->ifr_name, rgi->iface, IFNAMSIZ))
2515
+	    {
2516
+	      if (ifr->ifr_addr.sa_family == AF_LINK)
2517
+		{
2518
+		  struct sockaddr_dl *sdl = (struct sockaddr_dl *)&ifr->ifr_addr;
2519
+		  memcpy(rgi->hwaddr, LLADDR(sdl), 6);
2520
+		  rgi->flags |= RGI_HWADDR_DEFINED;
2521
+		}
2522
+	    }
2523
+	  cp += len;
2524
+	}
2463 2525
     }
2464
-}
2465 2526
 
2466
-bool
2467
-get_default_gateway (in_addr_t *ret, in_addr_t *netmask)
2468
-{
2469
-  return get_default_gateway_ex(ret, netmask, NULL);
2527
+ done:
2528
+  if (sockfd >= 0)
2529
+    close(sockfd);
2530
+  gc_free (&gc);
2470 2531
 }
2471 2532
 
2533
+#undef max
2534
+
2472 2535
 #elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
2473 2536
 
2474 2537
 #include <sys/types.h>
... ...
@@ -2529,8 +2891,11 @@ struct {
2529 2529
 #define ROUNDUP(a) \
2530 2530
         ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
2531 2531
 
2532
-bool
2533
-get_default_gateway (in_addr_t *ret, in_addr_t *netmask)
2532
+/*
2533
+ * FIXME -- add support for netmask, hwaddr, and iface
2534
+ */
2535
+void
2536
+get_default_gateway (struct route_gateway_info *rgi)
2534 2537
 {
2535 2538
   struct gc_arena gc = gc_new ();
2536 2539
   int s, seq, l, rtm_addrs, i;
... ...
@@ -2549,6 +2914,8 @@ get_default_gateway (in_addr_t *ret, in_addr_t *netmask)
2549 2549
 
2550 2550
 #define rtm m_rtmsg.m_rtm
2551 2551
 
2552
+  CLEAR(*rgi);
2553
+
2552 2554
   pid = getpid();
2553 2555
   seq = 0;
2554 2556
   rtm_addrs = RTA_DST | RTA_NETMASK;
... ...
@@ -2610,33 +2977,47 @@ get_default_gateway (in_addr_t *ret, in_addr_t *netmask)
2610 2610
 
2611 2611
   if (gate != NULL )
2612 2612
     {
2613
-      *ret = ntohl(((struct sockaddr_in *)gate)->sin_addr.s_addr);
2614
-#if 0
2615
-      msg (M_INFO, "gw %s",
2616
-	   print_in_addr_t ((in_addr_t) *ret, 0, &gc));
2617
-#endif
2618
-
2619
-      if (netmask)
2620
-	{
2621
-	  *netmask = 0xFFFFFF00; // FIXME -- get the real netmask of the adapter containing the default gateway
2622
-	}
2613
+      rgi->gateway.addr = ntohl(((struct sockaddr_in *)gate)->sin_addr.s_addr);
2614
+      rgi->flags |= RGI_ADDR_DEFINED;
2623 2615
 
2624 2616
       gc_free (&gc);
2625
-      return true;
2626 2617
     }
2627 2618
   else
2628 2619
     {
2629 2620
       gc_free (&gc);
2630
-      return false;
2631 2621
     }
2632 2622
 }
2633 2623
 
2634 2624
 #else
2635 2625
 
2636
-bool
2637
-get_default_gateway (in_addr_t *ret, in_addr_t *netmask)  /* PLATFORM-SPECIFIC */
2626
+/*
2627
+ * This is a platform-specific method that returns data about
2628
+ * the current default gateway.  Return data is placed into
2629
+ * a struct route_gateway_info object provided by caller.  The
2630
+ * implementation should CLEAR the structure before adding
2631
+ * data to it.
2632
+ *
2633
+ * Data returned includes:
2634
+ * 1. default gateway address (rgi->gateway.addr)
2635
+ * 2. netmask of interface that owns default gateway
2636
+ *    (rgi->gateway.netmask)
2637
+ * 3. hardware address (i.e. MAC address) of interface that owns
2638
+ *    default gateway (rgi->hwaddr)
2639
+ * 4. interface name (or adapter index on Windows) that owns default
2640
+ *    gateway (rgi->iface or rgi->adapter_index)
2641
+ * 5. an array of additional address/netmask pairs defined by
2642
+ *    interface that owns default gateway (rgi->addrs with length
2643
+ *    given in rgi->n_addrs)
2644
+ *
2645
+ * The flags RGI_x_DEFINED may be used to indicate which of the data
2646
+ * members were successfully returned (set in rgi->flags).  All of
2647
+ * the data members are optional, however certain OpenVPN functionality
2648
+ * may be disabled by missing items.
2649
+ */
2650
+void
2651
+get_default_gateway (struct route_gateway_info *rgi)
2638 2652
 {
2639
-  return false;
2653
+  CLEAR(*rgi);
2640 2654
 }
2641 2655
 
2642 2656
 #endif
... ...
@@ -2676,18 +3057,8 @@ netmask_to_netbits (const in_addr_t network, const in_addr_t netmask, int *netbi
2676 2676
 static void
2677 2677
 add_host_route_if_nonlocal (struct route_bypass *rb, const in_addr_t addr)
2678 2678
 {
2679
-  if (test_local_addr(addr) == TLA_NONLOCAL && addr != 0 && addr != ~0) {
2680
-    int i;
2681
-    for (i = 0; i < rb->n_bypass; ++i)
2682
-      {
2683
-        if (addr == rb->bypass[i]) /* avoid duplicates */
2684
-          return;
2685
-      }
2686
-    if (rb->n_bypass < N_ROUTE_BYPASS)
2687
-      {
2688
-        rb->bypass[rb->n_bypass++] = addr;
2689
-      }
2690
-  }
2679
+  if (test_local_addr(addr, NULL) == TLA_NONLOCAL && addr != 0 && addr != ~0)
2680
+    add_bypass_address (rb, addr);
2691 2681
 }
2692 2682
 
2693 2683
 static void
... ...
@@ -2746,222 +3117,6 @@ get_bypass_addresses (struct route_bypass *rb, const unsigned int flags)  /* PLA
2746 2746
 
2747 2747
 #endif
2748 2748
 
2749
-#if AUTO_USERID || defined(ENABLE_PUSH_PEER_INFO)
2750
-
2751
-#if defined(TARGET_LINUX)
2752
-
2753
-bool
2754
-get_default_gateway_mac_addr (unsigned char *macaddr)
2755
-{
2756
-  struct ifreq *ifr, *ifend;
2757
-  in_addr_t ina, mask;
2758
-  struct ifreq ifreq;
2759
-  struct ifconf ifc;
2760
-  struct ifreq ifs[20]; // Maximum number of interfaces to scan
2761
-  int sd = -1;
2762
-  in_addr_t gwip = 0;
2763
-  bool ret = false;
2764
-
2765
-  if (!get_default_gateway (&gwip, NULL))
2766
-    {
2767
-      msg (M_WARN, "GDGMA: get_default_gateway failed");
2768
-      goto err;
2769
-    }
2770
-
2771
-  if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
2772
-    {
2773
-      msg (M_WARN, "GDGMA: socket() failed");
2774
-      goto err;
2775
-    }
2776
-
2777
-  ifc.ifc_len = sizeof (ifs);
2778
-  ifc.ifc_req = ifs;
2779
-  if (ioctl (sd, SIOCGIFCONF, &ifc) < 0)
2780
-    {
2781
-      msg (M_WARN, "GDGMA: ioctl(SIOCGIFCONF) failed");
2782
-      goto err;
2783
-    }
2784
-
2785
-  /* scan through interface list */
2786
-  ifend = ifs + (ifc.ifc_len / sizeof (struct ifreq));
2787
-  for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
2788
-    {
2789
-      if (ifr->ifr_addr.sa_family == AF_INET)
2790
-	{
2791
-	  ina = ntohl(((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr);
2792
-	  strncpynt (ifreq.ifr_name, ifr->ifr_name, sizeof (ifreq.ifr_name));
2793
-
2794
-	  dmsg (D_AUTO_USERID, "GDGMA: %s", ifreq.ifr_name);
2795
-
2796
-	  /* check that the interface is up, and not point-to-point or loopback */
2797
-	  if (ioctl (sd, SIOCGIFFLAGS, &ifreq) < 0)
2798
-	    {
2799
-	      dmsg (D_AUTO_USERID, "GDGMA: SIOCGIFFLAGS(%s) failed", ifreq.ifr_name);
2800
-	      continue;
2801
-	    }
2802
-
2803
-	  if ((ifreq.ifr_flags & (IFF_UP|IFF_LOOPBACK)) != IFF_UP)
2804
-	    {
2805
-	      dmsg (D_AUTO_USERID, "GDGMA: interface %s is down or loopback", ifreq.ifr_name);
2806
-	      continue;
2807
-	    }
2808
-
2809
-	  /* get interface netmask and check for correct subnet */
2810
-	  if (ioctl (sd, SIOCGIFNETMASK, &ifreq) < 0)
2811
-	    {
2812
-	      dmsg (D_AUTO_USERID, "GDGMA: SIOCGIFNETMASK(%s) failed", ifreq.ifr_name);
2813
-	      continue;
2814
-	    }
2815
-
2816
-	  mask = ntohl(((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
2817
-	  if (((gwip ^ ina) & mask) != 0)
2818
-	    {
2819
-	      dmsg (D_AUTO_USERID, "GDGMA: gwip=0x%08x ina=0x%08x mask=0x%08x",
2820
-		    (unsigned int)gwip,
2821
-		    (unsigned int)ina,
2822
-		    (unsigned int)mask);
2823
-	      continue;
2824
-	    }
2825
-	  break;
2826
-	}
2827
-    }
2828
-  if (ifr >= ifend)
2829
-    {
2830
-      msg (M_WARN, "GDGMA: couldn't find gw interface");
2831
-      goto err;
2832
-    }
2833
-
2834
-  /* now get the hardware address. */
2835
-  memset (&ifreq.ifr_hwaddr, 0, sizeof (struct sockaddr));
2836
-  if (ioctl (sd, SIOCGIFHWADDR, &ifreq) < 0)
2837
-    {
2838
-      msg (M_WARN, "GDGMA: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
2839
-      goto err;
2840
-    }
2841
-
2842
-  memcpy (macaddr, &ifreq.ifr_hwaddr.sa_data, 6);
2843
-  ret = true;
2844
-
2845
- err:
2846
-  if (sd >= 0)
2847
-    close (sd);
2848
-  return ret;
2849
-}
2850
-
2851
-#elif defined(WIN32)
2852
-
2853
-bool
2854
-get_default_gateway_mac_addr (unsigned char *macaddr)
2855
-{
2856
-  struct gc_arena gc = gc_new ();
2857
-  const IP_ADAPTER_INFO *adapters = get_adapter_info_list (&gc);
2858
-  in_addr_t gwip = 0;
2859
-  DWORD a_index;
2860
-  const IP_ADAPTER_INFO *ai;
2861
-
2862
-  if (!get_default_gateway (&gwip, NULL))
2863
-    {
2864
-      msg (M_WARN, "GDGMA: get_default_gateway failed");
2865
-      goto err;
2866
-    }
2867
-
2868
-  a_index = adapter_index_of_ip (adapters, gwip, NULL, NULL);
2869
-  ai = get_adapter (adapters, a_index);
2870
-
2871
-  if (!ai)
2872
-    {
2873
-      msg (M_WARN, "GDGMA: couldn't find gw interface");
2874
-      goto err;
2875
-    }
2876
-
2877
-  memcpy (macaddr, ai->Address, 6);
2878
-
2879
-  gc_free (&gc);
2880
-  return true;
2881
-
2882
- err:
2883
-  gc_free (&gc);
2884
-  return false;
2885
-}
2886
-
2887
-#elif defined(TARGET_DARWIN)
2888
-
2889
-bool
2890
-get_default_gateway_mac_addr (unsigned char *macaddr)
2891
-{
2892
-# define max(a,b) ((a) > (b) ? (a) : (b))
2893
-  struct gc_arena gc = gc_new ();
2894
-  struct ifconf ifc;
2895
-  struct ifreq *ifr;
2896
-  char *buffer, *cp;
2897
-  bool status = false;
2898
-  in_addr_t gw = 0;
2899
-  char *ifname = NULL;
2900
-  int sockfd = -1;
2901
-  const int bufsize = 4096;
2902
-
2903
-  if (!get_default_gateway_ex (&gw, NULL, &ifname)) /* get interface name of default gateway */
2904
-    {
2905
-      msg (M_WARN, "GDGMA: get_default_gateway_ex failed");
2906
-      goto done;
2907
-    }
2908
-
2909
-  if (!ifname)
2910
-    {
2911
-      msg (M_WARN, "GDGMA: cannot get default gateway ifname");
2912
-      goto done;
2913
-    }
2914
-
2915
-  buffer = (char *) gc_malloc (bufsize, true, &gc);
2916
-
2917
-  sockfd = socket(AF_INET, SOCK_DGRAM, 0);
2918
-  if (sockfd < 0)
2919
-    {
2920
-      msg (M_WARN, "GDGMA: socket failed");
2921
-      goto done;
2922
-    }
2923
-
2924
-  ifc.ifc_len = bufsize;
2925
-  ifc.ifc_buf = buffer;
2926
-
2927
-  if (ioctl(sockfd, SIOCGIFCONF, (char *)&ifc) < 0)
2928
-    {
2929
-      msg (M_WARN, "GDGMA: ioctl failed");
2930
-      goto done;
2931
-    }
2932
-
2933
-  for (cp = buffer; cp <= buffer + bufsize - sizeof(struct ifreq); )
2934
-    {
2935
-      ifr = (struct ifreq *)cp;
2936
-      if (ifr->ifr_addr.sa_family == AF_LINK && !strncmp(ifr->ifr_name, ifname, IFNAMSIZ))
2937
-	{
2938
-	  struct sockaddr_dl *sdl = (struct sockaddr_dl *)&ifr->ifr_addr;
2939
-	  memcpy(macaddr, LLADDR(sdl), 6);
2940
-	  status = true;
2941
-	}      
2942
-      cp += sizeof(ifr->ifr_name) + max(sizeof(ifr->ifr_addr), ifr->ifr_addr.sa_len);
2943
-    }
2944
-
2945
- done:
2946
-  if (sockfd >= 0)
2947
-    close (sockfd);
2948
-  free (ifname);
2949
-  gc_free (&gc);
2950
-  return status;
2951
-# undef max
2952
-}
2953
-
2954
-#else
2955
-
2956
-bool
2957
-get_default_gateway_mac_addr (unsigned char *macaddr) /* PLATFORM-SPECIFIC */
2958
-{
2959
-  return false;
2960
-}
2961
-
2962
-#endif
2963
-#endif /* AUTO_USERID */
2964
-
2965 2749
 /*
2966 2750
  * Test if addr is reachable via a local interface (return ILA_LOCAL),
2967 2751
  * or if it needs to be routed via the default gateway (return
... ...
@@ -2974,7 +3129,7 @@ get_default_gateway_mac_addr (unsigned char *macaddr) /* PLATFORM-SPECIFIC */
2974 2974
 #if defined(WIN32)
2975 2975
 
2976 2976
 int
2977
-test_local_addr (const in_addr_t addr)
2977
+test_local_addr (const in_addr_t addr, const struct route_gateway_info *rgi)
2978 2978
 {
2979 2979
   struct gc_arena gc = gc_new ();
2980 2980
   const in_addr_t nonlocal_netmask = 0x80000000L; /* routes with netmask <= to this are considered non-local */
... ...
@@ -3004,10 +3159,16 @@ test_local_addr (const in_addr_t addr)
3004 3004
 
3005 3005
 #else
3006 3006
 
3007
-
3008 3007
 int
3009
-test_local_addr (const in_addr_t addr) /* PLATFORM-SPECIFIC */
3008
+test_local_addr (const in_addr_t addr, const struct route_gateway_info *rgi) /* PLATFORM-SPECIFIC */
3010 3009
 {
3010
+  if (rgi)
3011
+    {
3012
+      if (local_route (addr, 0xFFFFFFFF, rgi->gateway.addr, rgi))
3013
+	return TLA_LOCAL;
3014
+      else
3015
+	return TLA_NONLOCAL;
3016
+    }
3011 3017
   return TLA_NOT_IMPLEMENTED;
3012 3018
 }
3013 3019
 
... ...
@@ -29,6 +29,7 @@
29 29
 #ifndef ROUTE_H
30 30
 #define ROUTE_H
31 31
 
32
+#include "basic.h"
32 33
 #include "tun.h"
33 34
 #include "misc.h"
34 35
 
... ...
@@ -58,15 +59,17 @@ struct route_bypass
58 58
 
59 59
 struct route_special_addr
60 60
 {
61
+  /* bits indicating which members below are defined */
62
+# define RTSA_REMOTE_ENDPOINT  (1<<0)
63
+# define RTSA_REMOTE_HOST      (1<<1)
64
+# define RTSA_DEFAULT_METRIC   (1<<2)
65
+  unsigned int flags;
66
+
61 67
   in_addr_t remote_endpoint;
62
-  bool remote_endpoint_defined;
63
-  in_addr_t net_gateway;
64
-  bool net_gateway_defined;
65 68
   in_addr_t remote_host;
66
-  bool remote_host_defined;
69
+  int remote_host_local;  /* TLA_x value */
67 70
   struct route_bypass bypass;
68 71
   int default_metric;
69
-  bool default_metric_defined;
70 72
 };
71 73
 
72 74
 struct route_option {
... ...
@@ -84,9 +87,10 @@ struct route_option {
84 84
 #define RG_BYPASS_DNS     (1<<4)
85 85
 #define RG_REROUTE_GW     (1<<5)
86 86
 #define RG_AUTO_LOCAL     (1<<6)
87
+#define RG_BLOCK_LOCAL    (1<<7)
87 88
 
88 89
 struct route_option_list {
89
-  unsigned int flags;
90
+  unsigned int flags;  /* RG_x flags */
90 91
   int capacity;
91 92
   int n;
92 93
   struct route_option routes[EMPTY_ARRAY_SIZE];
... ...
@@ -106,26 +110,17 @@ struct route_ipv6_option_list {
106 106
 };
107 107
 
108 108
 struct route {
109
-  bool defined;
109
+# define RT_DEFINED        (1<<0)
110
+# define RT_ADDED          (1<<1)
111
+# define RT_METRIC_DEFINED (1<<2)
112
+  unsigned int flags;
110 113
   const struct route_option *option;
111 114
   in_addr_t network;
112 115
   in_addr_t netmask;
113 116
   in_addr_t gateway;
114
-  bool metric_defined;
115 117
   int metric;
116 118
 };
117 119
 
118
-struct route_list {
119
-  bool routes_added;
120
-  struct route_special_addr spec;
121
-  unsigned int flags;
122
-  bool did_redirect_default_gateway;
123
-  bool did_local;
124
-  int capacity;
125
-  int n;
126
-  struct route routes[EMPTY_ARRAY_SIZE];
127
-};
128
-
129 120
 struct route_ipv6 {
130 121
   bool defined;
131 122
   const struct route_ipv6_option *option;
... ...
@@ -151,6 +146,52 @@ struct route_ipv6_list {
151 151
 };
152 152
 
153 153
 
154
+struct route_gateway_address {
155
+  in_addr_t addr;
156
+  in_addr_t netmask;
157
+};
158
+
159
+struct route_gateway_info {
160
+# define RGI_ADDR_DEFINED     (1<<0) /* set if gateway.addr defined */
161
+# define RGI_NETMASK_DEFINED  (1<<1) /* set if gateway.netmask defined */
162
+# define RGI_HWADDR_DEFINED   (1<<2) /* set if hwaddr is defined */
163
+# define RGI_IFACE_DEFINED    (1<<3) /* set if iface is defined */
164
+# define RGI_OVERFLOW         (1<<4) /* set if more interface addresses than will fit in addrs */
165
+  unsigned int flags;
166
+
167
+  /* gateway interface */
168
+# ifdef WIN32
169
+  DWORD adapter_index;  /* interface or ~0 if undefined */
170
+#else
171
+  char iface[16]; /* interface name (null terminated), may be empty */
172
+#endif
173
+
174
+  /* gateway interface hardware address */
175
+  uint8_t hwaddr[6];
176
+
177
+  /* gateway/router address */
178
+  struct route_gateway_address gateway;
179
+
180
+  /* address/netmask pairs bound to interface */
181
+# define RGI_N_ADDRESSES 8
182
+  int n_addrs; /* len of addrs, may be 0 */
183
+  struct route_gateway_address addrs[RGI_N_ADDRESSES]; /* local addresses attached to iface */
184
+};
185
+
186
+struct route_list {
187
+# define RL_DID_REDIRECT_DEFAULT_GATEWAY (1<<0)
188
+# define RL_DID_LOCAL                    (1<<1)
189
+# define RL_ROUTES_ADDED                 (1<<2)
190
+  unsigned int iflags;
191
+
192
+  struct route_special_addr spec;
193
+  struct route_gateway_info rgi;
194
+  unsigned int flags;     /* RG_x flags */
195
+  int capacity;
196
+  int n;
197
+  struct route routes[EMPTY_ARRAY_SIZE];
198
+};
199
+
154 200
 #if P2MP
155 201
 /* internal OpenVPN route */
156 202
 struct iroute {
... ...
@@ -168,16 +209,22 @@ struct iroute_ipv6 {
168 168
 
169 169
 struct route_option_list *new_route_option_list (const int max_routes, struct gc_arena *a);
170 170
 struct route_ipv6_option_list *new_route_ipv6_option_list (const int max_routes, struct gc_arena *a);
171
+
171 172
 struct route_option_list *clone_route_option_list (const struct route_option_list *src, struct gc_arena *a);
172 173
 void copy_route_option_list (struct route_option_list *dest, const struct route_option_list *src);
173 174
 
174 175
 struct route_list *new_route_list (const int max_routes, struct gc_arena *a);
175 176
 struct route_ipv6_list *new_route_ipv6_list (const int max_routes, struct gc_arena *a);
176 177
 
177
-void add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);
178 178
 void add_route_ipv6 (struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);
179 179
 void delete_route_ipv6 (const struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);
180 180
 
181
+void add_route (struct route *r,
182
+		const struct tuntap *tt,
183
+		unsigned int flags,
184
+		const struct route_gateway_info *rgi,
185
+		const struct env_set *es);
186
+
181 187
 void add_route_to_option_list (struct route_option_list *l,
182 188
 			       const char *network,
183 189
 			       const char *netmask,
... ...
@@ -202,9 +249,9 @@ bool init_route_ipv6_list (struct route_ipv6_list *rl6,
202 202
 		      int default_metric,
203 203
 		      struct env_set *es);
204 204
 
205
-void route_list_add_default_gateway (struct route_list *rl,
206
-				     struct env_set *es,
207
-				     const in_addr_t addr);
205
+void route_list_add_vpn_gateway (struct route_list *rl,
206
+				 struct env_set *es,
207
+				 const in_addr_t addr);
208 208
 
209 209
 void add_routes (struct route_list *rl,
210 210
 		 struct route_ipv6_list *rl6,
... ...
@@ -221,9 +268,12 @@ void delete_routes (struct route_list *rl,
221 221
 void setenv_routes (struct env_set *es, const struct route_list *rl);
222 222
 void setenv_routes_ipv6 (struct env_set *es, const struct route_ipv6_list *rl6);
223 223
 
224
+
225
+
224 226
 bool is_special_addr (const char *addr_str);
225 227
 
226
-bool get_default_gateway (in_addr_t *ip, in_addr_t *netmask);
228
+void get_default_gateway (struct route_gateway_info *rgi);
229
+void print_default_gateway(const int msglevel, const struct route_gateway_info *rgi);
227 230
 
228 231
 /*
229 232
  * Test if addr is reachable via a local interface (return ILA_LOCAL),
... ...
@@ -234,11 +284,7 @@ bool get_default_gateway (in_addr_t *ip, in_addr_t *netmask);
234 234
 #define TLA_NOT_IMPLEMENTED 0
235 235
 #define TLA_NONLOCAL        1
236 236
 #define TLA_LOCAL           2
237
-int test_local_addr (const in_addr_t addr);
238
-
239
-#if AUTO_USERID || defined(ENABLE_PUSH_PEER_INFO)
240
-bool get_default_gateway_mac_addr (unsigned char *macaddr);
241
-#endif
237
+int test_local_addr (const in_addr_t addr, const struct route_gateway_info *rgi);
242 238
 
243 239
 #ifdef ENABLE_DEBUG
244 240
 void print_route_options (const struct route_option_list *rol,
... ...
@@ -251,7 +297,7 @@ void print_routes (const struct route_list *rl, int level);
251 251
 
252 252
 void show_routes (int msglev);
253 253
 bool test_routes (const struct route_list *rl, const struct tuntap *tt);
254
-bool add_route_ipapi (const struct route *r, const struct tuntap *tt);
254
+bool add_route_ipapi (const struct route *r, const struct tuntap *tt, DWORD adapter_index);
255 255
 bool del_route_ipapi (const struct route *r, const struct tuntap *tt);
256 256
 
257 257
 #else
... ...
@@ -271,12 +317,18 @@ netbits_to_netmask (const int netbits)
271 271
 }
272 272
 
273 273
 static inline bool
274
-route_list_default_gateway_needed (const struct route_list *rl)
274
+route_list_vpn_gateway_needed (const struct route_list *rl)
275 275
 {
276 276
   if (!rl)
277 277
     return false;
278 278
   else
279
-    return !rl->spec.remote_endpoint_defined;
279
+    return !(rl->spec.flags & RTSA_REMOTE_ENDPOINT);
280
+}
281
+
282
+static inline int
283
+route_did_redirect_default_gateway(const struct route_list *rl)
284
+{
285
+  return BOOL_CAST(rl->iflags & RL_DID_REDIRECT_DEFAULT_GATEWAY);
280 286
 }
281 287
 
282 288
 #endif
... ...
@@ -52,6 +52,7 @@
52 52
 #include "pkcs11.h"
53 53
 #include "list.h"
54 54
 #include "base64.h"
55
+#include "route.h"
55 56
 
56 57
 #ifdef WIN32
57 58
 #include "cryptoapi.h"
... ...
@@ -295,17 +296,35 @@ static char *auth_challenge; /* GLOBAL */
295 295
 #endif
296 296
 
297 297
 void
298
-auth_user_pass_setup (const char *auth_file)
298
+auth_user_pass_setup (const char *auth_file, const struct static_challenge_info *sci)
299 299
 {
300 300
   auth_user_pass_enabled = true;
301 301
   if (!auth_user_pass.defined)
302 302
     {
303 303
 #if AUTO_USERID
304 304
       get_user_pass_auto_userid (&auth_user_pass, auth_file);
305
-#elif defined(ENABLE_CLIENT_CR)
306
-      get_user_pass_cr (&auth_user_pass, auth_file, UP_TYPE_AUTH, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE, auth_challenge);
307 305
 #else
308
-      get_user_pass (&auth_user_pass, auth_file, UP_TYPE_AUTH, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE);
306
+# ifdef ENABLE_CLIENT_CR
307
+      if (auth_challenge) /* dynamic challenge/response */
308
+       get_user_pass_cr (&auth_user_pass,
309
+                         auth_file,
310
+                         UP_TYPE_AUTH,
311
+                         GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE|GET_USER_PASS_DYNAMIC_CHALLENGE,
312
+                         auth_challenge);
313
+      else if (sci) /* static challenge response */
314
+       {
315
+         int flags = GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE|GET_USER_PASS_STATIC_CHALLENGE;
316
+         if (sci->flags & SC_ECHO)
317
+           flags |= GET_USER_PASS_STATIC_CHALLENGE_ECHO;
318
+         get_user_pass_cr (&auth_user_pass,
319
+                           auth_file,
320
+                           UP_TYPE_AUTH,
321
+                           flags,
322
+                           sci->challenge_text);
323
+       }
324
+      else
325
+# endif
326
+       get_user_pass (&auth_user_pass, auth_file, UP_TYPE_AUTH, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE);
309 327
 #endif
310 328
     }
311 329
 }
... ...
@@ -4033,10 +4052,10 @@ push_peer_info(struct buffer *buf, struct tls_session *session)
4033 4033
 
4034 4034
       /* push mac addr */
4035 4035
       {
4036
-	bool get_default_gateway_mac_addr (unsigned char *macaddr);
4037
-	uint8_t macaddr[6];
4038
-	get_default_gateway_mac_addr (macaddr);
4039
-	buf_printf (&out, "IV_HWADDR=%s\n", format_hex_ex (macaddr, 6, 0, 1, ":", &gc));
4036
+	struct route_gateway_info rgi;
4037
+	get_default_gateway (&rgi);
4038
+	if (rgi.flags & RGI_HWADDR_DEFINED)
4039
+	  buf_printf (&out, "IV_HWADDR=%s\n", format_hex_ex (rgi.hwaddr, 6, 0, 1, ":", &gc));
4040 4040
       }
4041 4041
 
4042 4042
       /* push LZO status */
... ...
@@ -4097,7 +4116,11 @@ key_method_2_write (struct buffer *buf, struct tls_session *session)
4097 4097
   /* write username/password if specified */
4098 4098
   if (auth_user_pass_enabled)
4099 4099
     {
4100
-      auth_user_pass_setup (NULL);
4100
+#ifdef ENABLE_CLIENT_CR
4101
+      auth_user_pass_setup (NULL, session->opt->sci);
4102
+#else
4103
+      auth_user_pass_setup (NULL, NULL);
4104
+#endif
4101 4105
       if (!write_string (buf, auth_user_pass.username, -1))
4102 4106
 	goto error;
4103 4107
       if (!write_string (buf, auth_user_pass.password, -1))
... ...
@@ -519,6 +519,10 @@ struct tls_options
519 519
   const struct x509_track *x509_track;
520 520
 #endif
521 521
 
522
+#ifdef ENABLE_CLIENT_CR
523
+  const struct static_challenge_info *sci;
524
+#endif
525
+
522 526
   /* --gremlin bits */
523 527
   int gremlin;
524 528
 };
... ...
@@ -723,7 +727,7 @@ void get_highest_preference_tls_cipher (char *buf, int size);
723 723
 
724 724
 void pem_password_setup (const char *auth_file);
725 725
 int pem_password_callback (char *buf, int size, int rwflag, void *u);
726
-void auth_user_pass_setup (const char *auth_file);
726
+void auth_user_pass_setup (const char *auth_file, const struct static_challenge_info *sc_info);
727 727
 void ssl_set_auth_nocache (void);
728 728
 void ssl_set_auth_token (const char *token);
729 729
 void ssl_purge_auth (const bool auth_user_pass_only);
... ...
@@ -652,6 +652,15 @@ socket_defined (const socket_descriptor_t sd)
652 652
 #endif
653 653
 
654 654
 /*
655
+ * Should we include --management-query-remote functionality
656
+ */
657
+#if defined(ENABLE_CONNECTION) && defined(ENABLE_MANAGEMENT)
658
+#define MANAGEMENT_QUERY_REMOTE 1
659
+#else
660
+#define MANAGEMENT_QUERY_REMOTE 0
661
+#endif
662
+
663
+/*
655 664
  * Reduce sensitivity to system clock instability
656 665
  * and backtracks.
657 666
  */
... ...
@@ -674,7 +683,7 @@ socket_defined (const socket_descriptor_t sd)
674 674
 #endif
675 675
 
676 676
 /*
677
- * Do we support challenge/response authentication, as a console-based client?
677
+ * Do we support challenge/response authentication as client?
678 678
  */
679 679
 #define ENABLE_CLIENT_CR
680 680
 
... ...
@@ -248,11 +248,12 @@ check_subnet_conflict (const in_addr_t ip,
248 248
 		       const in_addr_t netmask,
249 249
 		       const char *prefix)
250 250
 {
251
+#if 0 /* too many false positives */
251 252
   struct gc_arena gc = gc_new ();
252 253
   in_addr_t lan_gw = 0;
253 254
   in_addr_t lan_netmask = 0;
254 255
 
255
-  if (get_default_gateway (&lan_gw, &lan_netmask))
256
+  if (get_default_gateway (&lan_gw, &lan_netmask) && lan_netmask)
256 257
     {
257 258
       const in_addr_t lan_network = lan_gw & lan_netmask; 
258 259
       const in_addr_t network = ip & netmask;
... ...
@@ -270,18 +271,20 @@ check_subnet_conflict (const in_addr_t ip,
270 270
 	}
271 271
     }
272 272
   gc_free (&gc);
273
+#endif
273 274
 }
274 275
 
275 276
 void
276 277
 warn_on_use_of_common_subnets (void)
277 278
 {
278 279
   struct gc_arena gc = gc_new ();
279
-  in_addr_t lan_gw = 0;
280
-  in_addr_t lan_netmask = 0;
280
+  struct route_gateway_info rgi;
281
+  const int needed = (RGI_ADDR_DEFINED|RGI_NETMASK_DEFINED);
281 282
 
282
-  if (get_default_gateway (&lan_gw, &lan_netmask))
283
+  get_default_gateway (&rgi);
284
+  if ((rgi.flags & needed) == needed)
283 285
     {
284
-      const in_addr_t lan_network = lan_gw & lan_netmask; 
286
+      const in_addr_t lan_network = rgi.gateway.addr & rgi.gateway.netmask;
285 287
       if (lan_network == 0xC0A80000 || lan_network == 0xC0A80100)
286 288
 	msg (M_WARN, "NOTE: your local LAN uses the extremely common subnet address 192.168.0.x or 192.168.1.x.  Be aware that this might create routing conflicts if you connect to the VPN server from public locations such as internet cafes that use the same subnet.");
287 289
     }