]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
--ip-win32 adaptive is now the default.
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Thu, 22 Dec 2005 18:09:40 +0000 (18:09 +0000)
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Thu, 22 Dec 2005 18:09:40 +0000 (18:09 +0000)
--ip-win32 netsh (or --ip-win32 adaptive when in netsh
mode) can now set DNS/WINS addresses on the TAP-Win32
adapter.

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

ChangeLog
forward.c
init.c
openvpn.h
options.c
tun.c
tun.h

index 9aa137832f98fe41e04c1bd6ba8dec7c27303500..e8c2005f0e9c07e4d7a3dbe9f412e3497b92ce97 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -32,7 +32,11 @@ $Id$
   forcing a username/password re-query.
 * Fixed bug where if --daemon and --management-hold are
   used together, --user or --group options would be ignored.
-
+* --ip-win32 adaptive is now the default.
+* --ip-win32 netsh (or --ip-win32 adaptive when in netsh
+  mode) can now set DNS/WINS addresses on the TAP-Win32
+  adapter.
+       
 2005.11.12 -- Version 2.1-beta7
 
 * Allow blank passwords to be passed via the management
index 5c35562d6067e984f9486861f22a3dbde96bb90c..4705f44de1b3518b3662f0edb7c7a9f64dcd46dc 100644 (file)
--- a/forward.c
+++ b/forward.c
@@ -275,7 +275,18 @@ check_add_routes_dowork (struct context *c)
     {
       msg (D_ROUTE, "Route: Waiting for TUN/TAP interface to come up...");
       if (c->c1.tuntap)
-       tun_standby (c->c1.tuntap);
+       {
+         if (!tun_standby (c->c1.tuntap))
+           {
+             c->sig->signal_received = SIGHUP;
+             c->sig->signal_text = "ip-fail";
+             c->persist.restart_sleep_seconds = 10;
+#ifdef WIN32
+             show_routes (M_INFO|M_NOPREFIX);
+             show_adapters (M_INFO|M_NOPREFIX);
+#endif
+           }
+       }
       update_time ();
       if (c->c2.route_wakeup.n != 1)
        event_timeout_init (&c->c2.route_wakeup, 1, now);
diff --git a/init.c b/init.c
index 8e730f1b0fdc429b39cc8b4af6f643c1caf6b3e5..930d2208aa95e1bd5a05f2f973c42bfd53eb499b 100644 (file)
--- a/init.c
+++ b/init.c
@@ -75,8 +75,10 @@ void
 context_clear_all_except_first_time (struct context *c)
 {
   const bool first_time_save = c->first_time;
+  const struct context_persist cpsave = c->persist;
   context_clear (c);
   c->first_time = first_time_save;
+  c->persist = cpsave;
 }
 
 /*
@@ -630,11 +632,15 @@ initialization_sequence_completed (struct context *c, const unsigned int flags)
 
   /* Test if errors */
   if (flags & ISC_ERRORS)
+    {
 #ifdef WIN32
-    msg (M_INFO, "%s With Errors ( see http://openvpn.net/faq.html#dhcpclientserv )", message);
+      show_routes (M_INFO|M_NOPREFIX);
+      show_adapters (M_INFO|M_NOPREFIX);
+      msg (M_INFO, "%s With Errors ( see http://openvpn.net/faq.html#dhcpclientserv )", message);
 #else
-    msg (M_INFO, "%s With Errors", message);
+      msg (M_INFO, "%s With Errors", message);
 #endif
+    }
   else
     msg (M_INFO, "%s", message);
 
@@ -1165,6 +1171,10 @@ socket_restart_pause (struct context *c)
     sec = 10;
 #endif
 
+  if (c->persist.restart_sleep_seconds > 0 && c->persist.restart_sleep_seconds > sec)
+    sec = c->persist.restart_sleep_seconds;
+  c->persist.restart_sleep_seconds = 0;
+
   if (do_hold (NULL))
     sec = 0;
 
index 437a02f3c38a4617f9aeadcbf87ab2bc2672f043..3ddc1a739895d182b3261659c47ebd8f2428ddf8 100644 (file)
--- a/openvpn.h
+++ b/openvpn.h
@@ -117,6 +117,14 @@ struct context_buffers
   struct buffer read_tun_buf;
 };
 
+/*
+ * always-persistent context variables
+ */
+struct context_persist
+{
+  int restart_sleep_seconds;
+};
+
 /* 
  * level 0 context contains data related to
  * once-per OpenVPN instantiation events
@@ -461,6 +469,9 @@ struct context
   /* set to true after we daemonize */
   bool did_we_daemonize;
 
+  /* persistent across SIGHUP */
+  struct context_persist persist;
+
   /* level 0 context contains data related to
      once-per OpenVPN instantiation events
      such as daemonization */
index 1ef201c2ff63dd9c303a21b09e5519b62435468d..75c8825d11988926f37f6f0f4299c626bd984f2e 100644 (file)
--- a/options.c
+++ b/options.c
@@ -637,7 +637,11 @@ init_options (struct options *o)
   o->tuntap_options.txqueuelen = 100;
 #endif
 #ifdef WIN32
+#if 1
+  o->tuntap_options.ip_win32_type = IPW32_SET_ADAPTIVE;
+#else
   o->tuntap_options.ip_win32_type = IPW32_SET_DHCP_MASQ;
+#endif
   o->tuntap_options.dhcp_lease_time = 31536000; /* one year */
   o->tuntap_options.dhcp_masq_offset = 0;       /* use network address as internal DHCP server address */
   o->route_method = ROUTE_METHOD_IPAPI;
diff --git a/tun.c b/tun.c
index eafa8d6e1ba59c409a602773e39299e035aa6979..07f6ea40bc90a410662720ecc7f94c99924db2ab 100644 (file)
--- a/tun.c
+++ b/tun.c
@@ -50,6 +50,8 @@
 
 #ifdef WIN32
 
+/* #define SIMULATE_DHCP_FAILED */       /* JYFIXME -- simulate bad DHCP negotiation */
+
 #define NI_TEST_FIRST  (1<<0)
 #define NI_IP_NETMASK  (1<<1)
 #define NI_OPTIONS     (1<<2)
@@ -3093,23 +3095,181 @@ netsh_command (const char *cmd, int n)
   for (i = 0; i < n; ++i)
     {
       bool status;
+      openvpn_sleep (1);
       netcmd_semaphore_lock ();
       msg (M_INFO, "NETSH: %s", cmd);
       status = system_check (cmd, NULL, 0, "ERROR: netsh command failed");
       netcmd_semaphore_release ();
       if (status)
        return;
-      openvpn_sleep (5);
+      openvpn_sleep (4);
     }
   msg (M_FATAL, "NETSH: command failed");
 }
 
+void
+ip_addr_string_to_array (in_addr_t *dest, int *dest_len, const IP_ADDR_STRING *src)
+{
+  int i = 0;
+  while (src)
+    {
+      const unsigned int getaddr_flags = GETADDR_HOST_ORDER;
+      const char *ip_str = src->IpAddress.String;
+      in_addr_t ip = 0;
+      bool succeed = false;
+
+      if (i >= *dest_len)
+       break;
+      if (!ip_str || !strlen (ip_str))
+       break;
+
+      ip = getaddr (getaddr_flags, ip_str, 0, &succeed, NULL);
+      if (!succeed)
+       break;
+      dest[i++] = ip;
+
+      src = src->Next;
+    }
+  *dest_len = i;
+
+#if 0
+ {
+   struct gc_arena gc = gc_new ();
+   msg (M_INFO, "ip_addr_string_to_array [%d]", *dest_len);
+   for (i = 0; i < *dest_len; ++i)
+     {
+       msg (M_INFO, "%s", print_in_addr_t (dest[i], 0, &gc));
+     }
+   gc_free (&gc);
+ }
+#endif
+}
+
+static bool
+ip_addr_one_to_one (const in_addr_t *a1, const int a1len, const IP_ADDR_STRING *ias)
+{
+  in_addr_t a2[8];
+  int a2len = SIZE(a2);
+  int i;
+
+  ip_addr_string_to_array (a2, &a2len, ias);
+  /*msg (M_INFO, "a1len=%d a2len=%d", a1len, a2len);*/
+  if (a1len != a2len)
+    return false;
+
+  for (i = 0; i < a1len; ++i)
+    {
+      if (a1[i] != a2[i])
+       return false;
+    }
+  return true;
+}
+
+static bool
+ip_addr_member_of (const in_addr_t addr, const IP_ADDR_STRING *ias)
+{
+  in_addr_t aa[8];
+  int len = SIZE(aa);
+  int i;
+
+  ip_addr_string_to_array (aa, &len, ias);
+  for (i = 0; i < len; ++i)
+    {
+      if (addr == aa[i])
+       return true;
+    }
+  return false;
+}
+
+static void
+netsh_ifconfig_options (const char *type,
+                       const in_addr_t *addr_list,
+                       const int addr_len,
+                       const IP_ADDR_STRING *current,
+                       const char *flex_name,
+                       const bool test_first)
+{
+  struct gc_arena gc = gc_new ();
+  struct buffer out = alloc_buf_gc (256, &gc);
+  bool delete_first = false;
+
+  /* first check if we should delete existing DNS/WINS settings from TAP interface */
+  if (test_first)
+    {
+      if (!ip_addr_one_to_one (addr_list, addr_len, current))
+       delete_first = true;
+    }
+  else
+    delete_first = true;
+  
+  /* delete existing DNS/WINS settings from TAP interface */
+  if (delete_first)
+    {
+      buf_init (&out, 0);
+      buf_printf (&out, "netsh interface ip delete %s \"%s\" all",
+                 type,
+                 flex_name);
+      netsh_command (BSTR(&out), 2);
+    }
+
+  /* add new DNS/WINS settings to TAP interface */
+  {
+    int count = 0;
+    int i;
+    for (i = 0; i < addr_len; ++i)
+      {
+       if (delete_first || !test_first || !ip_addr_member_of (addr_list[i], current))
+         {
+           const char *fmt = count ?
+               "netsh interface ip add %s \"%s\" %s"
+             : "netsh interface ip set %s \"%s\" static %s";
+
+           buf_init (&out, 0);
+           buf_printf (&out, fmt,
+                       type,
+                       flex_name,
+                       print_in_addr_t (addr_list[i], 0, &gc));
+           netsh_command (BSTR(&out), 2);
+         
+           ++count;
+         }
+       else
+         {
+           msg (M_INFO, "NETSH: \"%s\" %s %s [already set]",
+                flex_name,
+                type,
+                print_in_addr_t (addr_list[i], 0, &gc));
+         }
+      }
+  }
+
+  gc_free (&gc);
+}
+
+static void
+init_ip_addr_string2 (IP_ADDR_STRING *dest, const IP_ADDR_STRING *src1, const IP_ADDR_STRING *src2)
+{
+  CLEAR (dest[0]);
+  CLEAR (dest[1]);
+  if (src1)
+    {
+      dest[0] = *src1;
+      dest[0].Next = NULL;
+    }
+  if (src2)
+    {
+      dest[1] = *src2;
+      dest[0].Next = &dest[1];
+      dest[1].Next = NULL;
+    }
+}
+
 static void
 netsh_ifconfig (const struct tuntap_options *to,
                const char *flex_name,
                const in_addr_t ip,
                const in_addr_t netmask,
-               unsigned int flags)
+               const unsigned int flags)
 {
   struct gc_arena gc = gc_new ();
   struct buffer out = alloc_buf_gc (256, &gc);
@@ -3147,6 +3307,30 @@ netsh_ifconfig (const struct tuntap_options *to,
        }
     }
 
+  /* set WINS/DNS options */
+  if (flags & NI_OPTIONS)
+    {
+      IP_ADDR_STRING wins[2];
+      CLEAR (wins[0]);
+      CLEAR (wins[1]);
+
+      netsh_ifconfig_options ("dns",
+                             to->dns,
+                             to->dns_len,
+                             pai ? &pai->DnsServerList : NULL,
+                             flex_name,
+                             BOOL_CAST (flags & NI_TEST_FIRST));
+      if (ai && ai->HaveWins)
+       init_ip_addr_string2 (wins, &ai->PrimaryWinsServer, &ai->SecondaryWinsServer);
+
+      netsh_ifconfig_options ("wins",
+                             to->wins,
+                             to->wins_len,
+                             ai ? wins : NULL,
+                             flex_name,
+                             BOOL_CAST (flags & NI_TEST_FIRST));
+    }
+  
   gc_free (&gc);
 }
 
@@ -3209,20 +3393,28 @@ tun_standby_init (struct tuntap *tt)
   tt->standby_iter = 0;
 }
 
-void
+bool
 tun_standby (struct tuntap *tt)
 {
+  bool ret = true;
   ++tt->standby_iter;
-  if (tt->options.ip_win32_type == IPW32_SET_ADAPTIVE
-      && tt->standby_iter % IPW32_SET_ADAPTIVE_TRY_NETSH == 0)
+  if (tt->options.ip_win32_type == IPW32_SET_ADAPTIVE)
     {
-      msg (M_INFO, "NOTE: --ip-win32 dynamic failed, now trying --ip-win32 netsh (this may take some time)");
-      netsh_ifconfig (&tt->options,
-                     tt->actual_name,
-                     tt->local,
-                     tt->adapter_netmask,
-                     NI_TEST_FIRST|NI_IP_NETMASK|NI_OPTIONS);
+      if (tt->standby_iter == IPW32_SET_ADAPTIVE_TRY_NETSH)
+       {
+         msg (M_INFO, "NOTE: now trying netsh (this may take some time)");
+         netsh_ifconfig (&tt->options,
+                         tt->actual_name,
+                         tt->local,
+                         tt->adapter_netmask,
+                         NI_TEST_FIRST|NI_IP_NETMASK|NI_OPTIONS);
+       }
+      else if (tt->standby_iter >= IPW32_SET_ADAPTIVE_TRY_NETSH*2)
+       {
+         ret = false;
+       }
     }
+  return ret;
 }
 
 /*
@@ -3577,7 +3769,7 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
 
       ASSERT (ep[3] > 0);
 
-#if 1 /* TAP_IOCTL_CONFIG_DHCP_MASQ -- disable to simulate bad DHCP negotiation */
+#ifndef SIMULATE_DHCP_FAILED /* this code is disabled to simulate bad DHCP negotiation */
       if (!DeviceIoControl (tt->hand, TAP_IOCTL_CONFIG_DHCP_MASQ,
                            ep, sizeof (ep),
                            ep, sizeof (ep), &len, NULL))
@@ -3590,7 +3782,6 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
           print_in_addr_t (ep[2], IA_NET_ORDER, &gc),
           ep[3]
           );
-#endif
 
       /* user-supplied DHCP options capability */
       if (tt->options.dhcp_options)
@@ -3604,6 +3795,7 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
            msg (M_FATAL, "ERROR: The TAP-Win32 driver rejected a TAP_IOCTL_CONFIG_DHCP_SET_OPT DeviceIoControl call");
          free_buf (&buf);
        }
+#endif
     }
 
   /* set driver media status to 'connected' */
diff --git a/tun.h b/tun.h
index 6f66961dbef84a5a6c47852f0c5068170dabc1f2..082a6fcd22050a1c7f9c6d155185aa03ae9c8793 100644 (file)
--- a/tun.h
+++ b/tun.h
@@ -326,7 +326,7 @@ bool dhcp_release (const struct tuntap *tt);
 bool dhcp_renew (const struct tuntap *tt);
 
 void tun_standby_init (struct tuntap *tt);
-void tun_standby (struct tuntap *tt);
+bool tun_standby (struct tuntap *tt);
 
 int tun_read_queue (struct tuntap *tt, int maxsize);
 int tun_write_queue (struct tuntap *tt, struct buffer *buf);
@@ -392,9 +392,10 @@ tun_standby_init (struct tuntap *tt)
 {
 }
 
-static inline void
+static inline bool
 tun_standby (struct tuntap *tt)
 {
+  return true;
 }
 
 #endif