gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r25667 - in gnunet/src: include vpn


From: gnunet
Subject: [GNUnet-SVN] r25667 - in gnunet/src: include vpn
Date: Mon, 31 Dec 2012 16:52:36 +0100

Author: cfuchs
Date: 2012-12-31 16:52:36 +0100 (Mon, 31 Dec 2012)
New Revision: 25667

Added:
   gnunet/src/include/tap-windows.h
Modified:
   gnunet/src/vpn/gnunet-helper-vpn-windows.c
Log:
* added tap version checking logics. Many tap32 versions are broken,
Only version 9.8 and later support IPv6, 9.8 is broken with IPv4. Thus,
we are using the same minium version as openvpn 2.3: tap32-9.9

* created our TAP/TUN handle-object (equivalent to the *nix init_tun() 
function), this still requires some more logics to be
complete.

* added logics to set the tun up (+a fixed sleep, to wait for it to
come up)

* we now also store the device's GUID, as we need it for creating the
handle.

* added the exports of tap32: src/include/tap_windows.h , for the sake 
of upgradability. This file contains version-specific defines for the 
driver.

* happy new year!



Added: gnunet/src/include/tap-windows.h
===================================================================
--- gnunet/src/include/tap-windows.h                            (rev 0)
+++ gnunet/src/include/tap-windows.h    2012-12-31 15:52:36 UTC (rev 25667)
@@ -0,0 +1,80 @@
+/*
+ *  TAP-Windows -- A kernel driver to provide virtual tap
+ *                 device functionality on Windows.
+ *
+ *  This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
+ *
+ *  This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
+ *  and is released under the GPL version 2 (see below).
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program (see the file COPYING included with this
+ *  distribution); if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/**
+ * @file include/tap-windows.h
+ * @brief TAP32 virtual network driver defines
+ * @attention This file is part of openvpn and for kept
+ *            as a separate file to allow easier upgrading.
+ */
+#ifndef __TAP_WIN_H
+#define __TAP_WIN_H
+
+/*
+ * =============
+ * TAP IOCTLs
+ * =============
+ */
+
+#define TAP_WIN_CONTROL_CODE(request,method) \
+  CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
+
+/* Present in 8.1 */
+
+#define TAP_WIN_IOCTL_GET_MAC               TAP_WIN_CONTROL_CODE (1, 
METHOD_BUFFERED)
+#define TAP_WIN_IOCTL_GET_VERSION           TAP_WIN_CONTROL_CODE (2, 
METHOD_BUFFERED)
+#define TAP_WIN_IOCTL_GET_MTU               TAP_WIN_CONTROL_CODE (3, 
METHOD_BUFFERED)
+#define TAP_WIN_IOCTL_GET_INFO              TAP_WIN_CONTROL_CODE (4, 
METHOD_BUFFERED)
+#define TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT TAP_WIN_CONTROL_CODE (5, 
METHOD_BUFFERED)
+#define TAP_WIN_IOCTL_SET_MEDIA_STATUS      TAP_WIN_CONTROL_CODE (6, 
METHOD_BUFFERED)
+#define TAP_WIN_IOCTL_CONFIG_DHCP_MASQ      TAP_WIN_CONTROL_CODE (7, 
METHOD_BUFFERED)
+#define TAP_WIN_IOCTL_GET_LOG_LINE          TAP_WIN_CONTROL_CODE (8, 
METHOD_BUFFERED)
+#define TAP_WIN_IOCTL_CONFIG_DHCP_SET_OPT   TAP_WIN_CONTROL_CODE (9, 
METHOD_BUFFERED)
+
+/* Added in 8.2 */
+
+/* obsoletes TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT */
+#define TAP_WIN_IOCTL_CONFIG_TUN            TAP_WIN_CONTROL_CODE (10, 
METHOD_BUFFERED)
+
+/*
+ * =================
+ * Registry keys
+ * =================
+ */
+
+#define ADAPTER_KEY 
"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
+
+#define NETWORK_CONNECTIONS_KEY 
"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
+
+/*
+ * ======================
+ * Filesystem prefixes
+ * ======================
+ */
+
+#define USERMODEDEVICEDIR "\\\\.\\Global\\"
+#define SYSDEVICEDIR      "\\Device\\"
+#define USERDEVICEDIR     "\\DosDevices\\Global\\"
+#define TAP_WIN_SUFFIX    ".tap"
+
+#endif

Modified: gnunet/src/vpn/gnunet-helper-vpn-windows.c
===================================================================
--- gnunet/src/vpn/gnunet-helper-vpn-windows.c  2012-12-29 20:25:46 UTC (rev 
25666)
+++ gnunet/src/vpn/gnunet-helper-vpn-windows.c  2012-12-31 15:52:36 UTC (rev 
25667)
@@ -36,6 +36,7 @@
 #include <setupapi.h>
 #include <ddk/cfgmgr32.h>
 #include "platform.h"
+#include "tap-windows.h"
 #include <Winsock2.h>
 
 /**
@@ -72,6 +73,31 @@
 #define HARDWARE_ID "TAP0901"
 
 /**
+ * Component ID if our driver
+ */
+#define TAP_WIN_COMPONENT_ID "tap0901"
+
+/**
+ * Minimum major-id of the driver version we can work with
+ */
+#define TAP_WIN_MIN_MAJOR 9
+
+/**
+ * Minimum minor-id of the driver version we can work with. 
+ * v <= 7 has buggy IPv6.
+ * v == 8 is broken for small IPv4 Packets
+ */
+#define TAP_WIN_MIN_MINOR 9
+
+/**
+ * Time to wait for our virtual device to go up after telling it to do so.
+ * 
+ * openvpn doesn't specify a value, 4 seems sane for testing, even for openwrt
+ * (in fact, 4 was chosen by a fair dice roll...)
+ */
+#define TAP32_POSTUP_WAITTIME 4
+
+/**
  * Location of the network interface list resides in registry.
  * TODO: is this fixed on all version of windows? Checked with XP and 7
  */
@@ -106,17 +132,10 @@
 static SP_DEVINFO_DATA DeviceNode;
 
 /**
- * Class-tag of our virtual device
- */
-static char class[128];
-
-/**
  * GUID of our virtual device in the form of 
  * {12345678-1234-1234-1234-123456789abc} - in hex
  */
-static GUID guid;
-
-
+static char device_guid[256];
 /**
  * inet_pton() wrapper for WSAStringToAddress()
  *
@@ -131,6 +150,7 @@
 #if WINVER >= 0x0600
 int inet_pton (int af, const char *src, void *dst);
 #else
+
 int
 inet_pton (int af, const char *src, void *dst)
 {
@@ -158,6 +178,7 @@
   return 0;
 }
 #endif
+
 /**
  * Wrapper for executing a shellcommand in windows.
  * 
@@ -220,8 +241,8 @@
    * prepare the command
    */
   snprintf (command, LINE_LEN,
-              "netsh interface ipv6 add address \"%s\" %s/%d",
-              device_visible_name, address, prefix_len);
+            "netsh interface ipv6 add address \"%s\" %s/%d",
+            device_visible_name, address, prefix_len);
   /*
    * Set the address
    */
@@ -265,8 +286,8 @@
    * prepare the command
    */
   snprintf (command, LINE_LEN,
-              "netsh interface ipv4 add address \"%s\" %s %s",
-              device_visible_name, address, mask);
+            "netsh interface ipv4 add address \"%s\" %s %s",
+            device_visible_name, address, mask);
   /*
    * Set the address
    */
@@ -296,10 +317,10 @@
    */
   char inf_file_path[MAX_PATH];
   char hwidlist[LINE_LEN + 4];
-
+  char class_name[128];
+  GUID class_guid;
   int str_lenth = 0;
 
-
   /** 
    * Set the device's hardware ID and add it to a list.
    * This information will later on identify this device in registry. 
@@ -330,35 +351,35 @@
    * Bootstrap our device info using the drivers inf-file
    */
   if (!SetupDiGetINFClassA (inf_file_path,
-                           &guid,
-                           class, sizeof (class) / sizeof (char),
-                           NULL))
+                            &class_guid,
+                            class_name, sizeof (class_name) / sizeof (char),
+                            NULL))
     return FALSE;
 
   /** 
    * Collect all the other needed information... 
    * let the system fill our this form 
    */
-  DeviceInfo = SetupDiCreateDeviceInfoList (&guid, NULL);
+  DeviceInfo = SetupDiCreateDeviceInfoList (&class_guid, NULL);
   if (DeviceInfo == INVALID_HANDLE_VALUE)
     return FALSE;
 
   DeviceNode.cbSize = sizeof (SP_DEVINFO_DATA);
   if (!SetupDiCreateDeviceInfoA (DeviceInfo,
-                                class,
-                                &guid,
-                                NULL,
-                                NULL,
-                                DICD_GENERATE_ID,
-                                &DeviceNode))
+                                 class_name,
+                                 &class_guid,
+                                 NULL,
+                                 NULL,
+                                 DICD_GENERATE_ID,
+                                 &DeviceNode))
     return FALSE;
 
   /* Deploy all the information collected into the registry */
   if (!SetupDiSetDeviceRegistryPropertyA (DeviceInfo,
-                                         &DeviceNode,
-                                         SPDRP_HARDWAREID,
-                                         (LPBYTE) hwidlist,
-                                         (strlen (hwidlist) + 2) * sizeof 
(char)))
+                                          &DeviceNode,
+                                          SPDRP_HARDWAREID,
+                                          (LPBYTE) hwidlist,
+                                          (strlen (hwidlist) + 2) * sizeof 
(char)))
     return FALSE;
 
   /* Install our new class(=device) into the system */
@@ -393,9 +414,9 @@
    *    uninstall related information into the structure
    */
   if (!SetupDiSetClassInstallParamsA (DeviceInfo,
-                                     (PSP_DEVINFO_DATA) & DeviceNode,
-                                     &remove.ClassInstallHeader,
-                                     sizeof (remove)))
+                                      (PSP_DEVINFO_DATA) & DeviceNode,
+                                      &remove.ClassInstallHeader,
+                                      sizeof (remove)))
     return FALSE;
   /*
    * 2. Uninstall the virtual interface using the class installer
@@ -432,19 +453,19 @@
   /* We can obtain the PNP instance ID from our setupapi handle */
   device_details.cbSize = sizeof (device_details);
   if (CR_SUCCESS != CM_Get_Device_ID_ExA (DeviceNode.DevInst,
-                                         (PCHAR) pnp_instance_id,
-                                         MAX_DEVICE_ID_LEN,
-                                         0, //must be 0
-                                         NULL)) //hMachine, we are local
+                                          (PCHAR) pnp_instance_id,
+                                          MAX_DEVICE_ID_LEN,
+                                          0, //must be 0
+                                          NULL)) //hMachine, we are local
     return FALSE;
 
   /* Now we can use this ID to locate the correct networks interface in 
registry */
   if (ERROR_SUCCESS != RegOpenKeyExA (
-                                     HKEY_LOCAL_MACHINE,
-                                     adapter,
-                                     0,
-                                     KEY_READ,
-                                     &adapter_key_handle))
+                                      HKEY_LOCAL_MACHINE,
+                                      adapter,
+                                      0,
+                                      KEY_READ,
+                                      &adapter_key_handle))
     return FALSE;
 
   /* Of course there is a multitude of entries here, with arbitrary names, 
@@ -463,14 +484,14 @@
       len = sizeof (adapter_key_handle);
       /* optain a subkey of {4D36E972-E325-11CE-BFC1-08002BE10318} */
       status = RegEnumKeyExA (
-                             adapter_key_handle,
-                             i,
-                             instance_key,
-                             &len,
-                             NULL,
-                             NULL,
-                             NULL,
-                             NULL);
+                              adapter_key_handle,
+                              i,
+                              instance_key,
+                              &len,
+                              NULL,
+                              NULL,
+                              NULL,
+                              NULL);
 
       /* this may fail due to one of two reasons: 
        * we are at the end of the list*/
@@ -482,16 +503,16 @@
 
       /* prepare our new query string: */
       snprintf (query_key, 256, "%s\\%s\\Connection",
-                  INTERFACE_REGISTRY_LOCATION,
-                  instance_key);
+                INTERFACE_REGISTRY_LOCATION,
+                instance_key);
 
       /* look inside instance_key\\Connection */
       status = RegOpenKeyExA (
-                             HKEY_LOCAL_MACHINE,
-                             query_key,
-                             0,
-                             KEY_READ,
-                             &instance_key_handle);
+                              HKEY_LOCAL_MACHINE,
+                              query_key,
+                              0,
+                              KEY_READ,
+                              &instance_key_handle);
 
       if (status != ERROR_SUCCESS)
         continue;
@@ -499,33 +520,40 @@
       /* now, read our PnpInstanceID */
       len = sizeof (pnpinstanceid_value);
       status = RegQueryValueExA (instance_key_handle,
-                                pnpinstanceid_name,
-                                NULL, //reserved, always NULL according to MSDN
-                                &data_type,
-                                (LPBYTE) pnpinstanceid_value,
-                                &len);
+                                 pnpinstanceid_name,
+                                 NULL, //reserved, always NULL according to 
MSDN
+                                 &data_type,
+                                 (LPBYTE) pnpinstanceid_value,
+                                 &len);
 
       if (status != ERROR_SUCCESS || data_type != REG_SZ)
         goto cleanup;
 
       /* compare the value we got to our devices PNPInstanceID*/
       if (0 != strncmp (pnpinstanceid_value, pnp_instance_id,
-                         sizeof (pnpinstanceid_value) / sizeof (char)))
+                        sizeof (pnpinstanceid_value) / sizeof (char)))
         goto cleanup;
 
       len = sizeof (device_visible_name);
       status = RegQueryValueExA (
-                                instance_key_handle,
-                                adaptername_name,
-                                NULL, //reserved, always NULL according to MSDN
-                                &data_type,
-                                (LPBYTE) device_visible_name,
-                                &len);
+                                 instance_key_handle,
+                                 adaptername_name,
+                                 NULL, //reserved, always NULL according to 
MSDN
+                                 &data_type,
+                                 (LPBYTE) device_visible_name,
+                                 &len);
 
-      if (status == ERROR_SUCCESS && data_type == REG_SZ)
-        {
-          retval = TRUE;
-        }
+      if (status != ERROR_SUCCESS || data_type != REG_SZ)
+        goto cleanup;
+
+      /* 
+       * we have successfully found OUR instance, 
+       * save the device GUID before exiting
+       */
+
+      strncpy (device_guid, instance_key, 256);
+      retval = TRUE;
+
 cleanup:
       RegCloseKey (instance_key_handle);
 
@@ -537,45 +565,120 @@
   return retval;
 }
 
+static boolean
+check_tapw32_version (HANDLE handle)
+{
+  {
+    ULONG version[3];
+    DWORD len;
+    memset (&(version), 0, sizeof (version));
+
+
+    if (DeviceIoControl (handle, TAP_WIN_IOCTL_GET_VERSION,
+                         &version, sizeof (version),
+                         &version, sizeof (version), &len, NULL))
+      {
+#ifdef TESTING
+        fprintf (stderr, "TAP-Windows Driver Version %d.%d %s",
+                 (int) version[0],
+                 (int) version[1],
+                 (version[2] ? "(DEBUG)" : ""));
+#endif
+      }
+
+    if (version[0] != TAP_WIN_MIN_MAJOR || version[1] < TAP_WIN_MIN_MINOR)
+      {
+        fprintf (stderr, "ERROR:  This version of gnunet requires a 
TAP-Windows driver that is at least version %d.%d!\n",
+                 TAP_WIN_MIN_MAJOR,
+                 TAP_WIN_MIN_MINOR);
+        return FALSE;
+      }
+    return TRUE;
+  }
+}
+
 /**
  * Creates a tun-interface called dev;
  *
  * @return the fd to the tun or -1 on error
  */
-static int
+static HANDLE
 init_tun ()
 {
-  int fd = -1;
+  char device_path[256];
+  HANDLE handle;
 
   if (!setup_interface ())
     {
       errno = ENODEV;
-      return -1;
+      return INVALID_HANDLE_VALUE;
     }
 
   if (!resolve_interface_name ())
     {
       errno = ENODEV;
-      return -1;
+      return INVALID_HANDLE_VALUE;
     }
 
-  //openvpn
-  /* get driver MTU */
-  // tun.c:2869
-  
-  /* tun up: */
-  // tun.c: 3024
-  
-  return fd;
+  /* Open Windows TAP-Windows adapter */
+  snprintf (device_path, sizeof (device_path), "%s%s%s",
+            USERMODEDEVICEDIR,
+            device_guid,
+            TAP_WIN_SUFFIX);
+
+  handle = CreateFile (
+                       device_path,
+                       GENERIC_READ | GENERIC_WRITE,
+                       0, /* was: FILE_SHARE_READ */
+                       0,
+                       OPEN_EXISTING,
+                       FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
+                       0
+                       );
+
+  if (handle == INVALID_HANDLE_VALUE)
+    {
+      fprintf (stderr, "CreateFile failed on TAP device: %s\n", device_path);
+      return handle;
+    }
+
+  /* get driver version info */
+  if (!check_tapw32_version (handle))
+    {
+      CloseHandle (handle);
+      return INVALID_HANDLE_VALUE;
+    }
+
+  return handle;
 }
 
+static boolean
+tun_up (HANDLE handle)
+{
+  ULONG status = TRUE;
+  DWORD len;
+  if (DeviceIoControl (handle, TAP_WIN_IOCTL_SET_MEDIA_STATUS,
+                       &status, sizeof (status),
+                       &status, sizeof (status), &len, NULL))
+    {
+      fprintf (stderr, "The TAP-Windows driver ignored our request to set the 
interface UP (TAP_WIN_IOCTL_SET_MEDIA_STATUS DeviceIoControl call)!\n");
+      return FALSE;
+    }
+
+  /* Wait for the device to go UP, might take some time. */
+  Sleep ((TAP32_POSTUP_WAITTIME)*1000);
+
+  return TRUE;
+
+}
+
 /**
  * Start forwarding to and from the tunnel.
  *
  * @param fd_tun tunnel FD
  */
 static void
-run (int fd_tun)
+run (HANDLE handle)
 {
   /*
    * The buffer filled by reading from fd_tun
@@ -591,19 +694,29 @@
   ssize_t bufin_size = 0;
   ssize_t bufin_rpos = 0;
   unsigned char *bufin_read = NULL;
-  /* Hello, I am a stub function! I did my job, yay me! */
-  
+
   //openvpn  
-  
+  // Set Device to Subnet-Mode? 
+  // do we really need tun.c:2925 ?
+  // Why do we also assign IPv4's there??? Foobar??
+
+  /* tun up: */
+  if (!tun_up (handle))
+    goto teardown;
+
+  // tun.c:3038 
+
   // mainloop:
   // tunnel_point_to_point
   //openvpn.c:62
-  
+
+  // init.c:3337
   /* setup ansync IO */
   //forward.c: 1515
 
-  
-  //teardown:
+
+teardown:
+  ;
   //init.c:3472
 }
 
@@ -622,7 +735,7 @@
 main (int argc, char **argv)
 {
   char hwid[LINE_LEN];
-  int fd_tun;
+  HANDLE handle;
   int global_ret;
 
   if (6 != argc)
@@ -640,10 +753,10 @@
    * as additional hardware-id for our device.
    */
   snprintf (secondary_hwid, LINE_LEN / 2, "%s-%d",
-              hwid,
-              _getpid ());
+            hwid,
+            _getpid ());
 
-  if (-1 == (fd_tun = init_tun ()))
+  if (INVALID_HANDLE_VALUE == (handle = init_tun ()))
     {
       fprintf (stderr, "Fatal: could not initialize virtual-interface %s with 
IPv6 %s/%s and IPv4 %s/%s\n",
                hwid,
@@ -681,7 +794,7 @@
   // tap_allow_nonadmin_access
   //tun.c:2023
 
-  run (fd_tun);
+  run (handle);
   global_ret = 0;
 cleanup:
   remove_interface ();




reply via email to

[Prev in Thread] Current Thread [Next in Thread]