37 #ifndef __MINGW64_VERSION_MAJOR 38 #include <ddk/cfgmgr32.h> 39 #include <ddk/newdev.h> 65 #define DEBUG GNUNET_NO 69 #define LOG_DEBUG(msg) fprintf(stderr, "%s", msg); 71 #define LOG_DEBUG(msg) do {} while (0) 82 #define MAX_SIZE 65536 88 #define INF_FILE "share/gnunet/openvpn-tap32/tapw32/OemWin2k.inf" 94 #define INF_FILE64 "share/gnunet/openvpn-tap32/tapw64/OemWin2k.inf" 100 #define HARDWARE_ID "tap0901" 105 #define TAP_WIN_MIN_MAJOR 9 112 #define TAP_WIN_MIN_MINOR 9 120 #define TAP32_POSTUP_WAITTIME 4 125 #define INTERFACE_REGISTRY_LOCATION "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" 242 WINBASEAPI HANDLE WINAPI
ReOpenFile(HANDLE, DWORD, DWORD, DWORD);
270 memcpy(dst, src, slen);
287 #elif defined(_WIN32) 289 BOOL success = FALSE;
290 BOOL on_wow64 = FALSE;
293 if (NULL != IsWow64Process)
294 success = IsWow64Process(GetCurrentProcess(), &on_wow64);
296 return success && on_wow64;
312 if ((NULL == command) ||
313 (NULL == (pipe = _popen(command,
"rt"))))
317 fprintf(stderr,
"DEBUG: Command output: \n");
318 char output[LINE_LEN];
319 while (NULL != fgets(output,
sizeof(output), pipe))
320 fprintf(stderr,
"%s", output);
323 return _pclose(pipe);
337 char command[LINE_LEN];
338 struct sockaddr_in6 sa6;
343 memset(&sa6, 0,
sizeof(
struct sockaddr_in6));
344 sa6.sin6_family = AF_INET6;
345 if (1 !=
inet_pton(AF_INET6, address, &sa6.sin6_addr.s6_addr))
347 fprintf(stderr,
"ERROR: Failed to parse address `%s': %s\n", address,
355 snprintf(command, LINE_LEN,
356 "netsh interface ipv6 add address \"%s\" %s/%d store=active",
365 fprintf(stderr,
"FATAL: Setting IPv6 address failed: %s\n", strerror(ret));
378 char command[LINE_LEN];
385 snprintf(command, LINE_LEN,
386 "netsh interface ipv6 delete address \"%s\" store=persistent",
395 fprintf(stderr,
"FATAL: removing IPv6 address failed: %s\n", strerror(ret));
409 char command[LINE_LEN];
411 struct sockaddr_in addr;
413 addr.sin_family = AF_INET;
418 if (1 !=
inet_pton(AF_INET, address, &addr.sin_addr.s_addr))
420 fprintf(stderr,
"ERROR: Failed to parse address `%s': %s\n", address,
430 snprintf(command, LINE_LEN,
431 "netsh interface ipv4 add address \"%s\" %s %s store=active",
440 fprintf(stderr,
"FATAL: Setting IPv4 address failed: %s\n", strerror(ret));
453 char command[LINE_LEN];
461 snprintf(command, LINE_LEN,
462 "netsh interface ipv4 delete address \"%s\" gateway=all store=persistent",
471 fprintf(stderr,
"FATAL: removing IPv4 address failed: %s\n", strerror(ret));
489 char inf_file_path[MAX_PATH];
490 char * temp_inf_filename;
491 char hwidlist[LINE_LEN + 4];
492 char class_name[128];
502 sizeof(hwidlist)) + 1;
509 str_length = strlen(hwidlist) + 1;
512 sizeof(hwidlist) - str_length) + 1;
514 hwidlist[str_length] =
'\0';
522 GetFullPathNameA(
INF_FILE64, MAX_PATH, inf_file_path, &temp_inf_filename);
524 GetFullPathNameA(
INF_FILE, MAX_PATH, inf_file_path, &temp_inf_filename);
526 fprintf(stderr,
"INFO: Located our driver's .inf file at %s\n", inf_file_path);
530 if (!SetupDiGetINFClassA(inf_file_path,
532 class_name,
sizeof(class_name) /
sizeof(
char),
540 DeviceInfo = SetupDiCreateDeviceInfoList(&class_guid, NULL);
555 if (!SetupDiSetDeviceRegistryPropertyA(
DeviceInfo,
559 str_length *
sizeof(
char)))
563 if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE,
570 if (!UpdateDriverForPlugAndPlayDevicesA(NULL,
573 INSTALLFLAG_FORCE | INSTALLFLAG_NONINTERACTIVE,
577 fprintf(stderr,
"DEBUG: successfully created a network device\n");
591 SP_REMOVEDEVICE_PARAMS
remove;
596 remove.ClassInstallHeader.cbSize =
sizeof(SP_CLASSINSTALL_HEADER);
597 remove.HwProfile = 0;
598 remove.Scope = DI_REMOVEDEVICE_GLOBAL;
599 remove.ClassInstallHeader.InstallFunction = DIF_REMOVE;
604 if (!SetupDiSetClassInstallParamsA(
DeviceInfo,
606 &
remove.ClassInstallHeader,
612 if (!SetupDiCallClassInstaller(DIF_REMOVE,
614 (PSP_DEVINFO_DATA)&DeviceNode))
619 fprintf(stderr,
"DEBUG: removed interface successfully\n");
634 SP_DEVINFO_LIST_DETAIL_DATA device_details;
635 char pnp_instance_id [MAX_DEVICE_ID_LEN];
636 HKEY adapter_key_handle;
645 device_details.cbSize =
sizeof(device_details);
646 if (CR_SUCCESS != CM_Get_Device_ID_ExA(
DeviceNode.DevInst,
647 (PCHAR)pnp_instance_id,
653 fprintf(stderr,
"DEBUG: Resolving interface name for network device %s\n", pnp_instance_id);
656 for (retrys = 0; retrys < 120 && !retval; retrys++)
662 if (ERROR_SUCCESS != RegOpenKeyExA(
667 &adapter_key_handle))
675 char instance_key[256];
677 HKEY instance_key_handle;
678 char pnpinstanceid_name[] =
"PnpInstanceID";
679 char pnpinstanceid_value[256];
680 char adaptername_name[] =
"Name";
683 len = 256 *
sizeof(char);
685 status = RegEnumKeyExA(
697 if (ERROR_NO_MORE_ITEMS == status)
700 if (ERROR_SUCCESS != status)
704 snprintf(query_key, 256,
"%s\\%s\\Connection",
709 if (ERROR_SUCCESS != RegOpenKeyExA(
714 &instance_key_handle))
718 len =
sizeof(pnpinstanceid_value);
719 status = RegQueryValueExA(instance_key_handle,
723 (LPBYTE)pnpinstanceid_value,
726 if (status != ERROR_SUCCESS || data_type != REG_SZ)
730 if (0 != strncmp(pnpinstanceid_value, pnp_instance_id,
731 sizeof(pnpinstanceid_value) /
sizeof(
char)))
735 status = RegQueryValueExA(
743 if (status != ERROR_SUCCESS || data_type != REG_SZ)
752 fprintf(stderr,
"DEBUG: Interface Name lookup succeeded on retry %d, got \"%s\" %s\n", retrys, device_visible_name,
device_guid);
755 RegCloseKey(instance_key_handle);
760 RegCloseKey(adapter_key_handle);
778 memset(&(version), 0,
sizeof(version));
781 &version,
sizeof(version),
782 &version,
sizeof(version), &len, NULL))
783 fprintf(stderr,
"INFO: TAP-Windows Driver Version %d.%d %s\n",
786 (version[2] ?
"(DEBUG)" :
""));
791 fprintf(stderr,
"FATAL: This version of gnunet requires a TAP-Windows driver that is at least version %d.%d\n",
809 char device_path[256];
815 return INVALID_HANDLE_VALUE;
821 return INVALID_HANDLE_VALUE;
825 snprintf(device_path,
sizeof(device_path),
"%s%s%s",
832 GENERIC_READ | GENERIC_WRITE,
836 FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
840 if (INVALID_HANDLE_VALUE == handle)
842 fprintf(stderr,
"FATAL: CreateFile failed on TAP device: %s\n", device_path);
850 return INVALID_HANDLE_VALUE;
855 fprintf(stderr,
"DEBUG: successfully opened TAP device\n");
873 &status,
sizeof(status),
874 &status,
sizeof(status), &len, NULL))
876 fprintf(stderr,
"FATAL: TAP driver ignored request to UP interface (DeviceIoControl call)\n");
882 fprintf(stderr,
"DEBUG: successfully set TAP device to UP\n");
924 if (!ResetEvent(input_facility->
overlapped.hEvent))
932 if (ReadFile(input_facility->
handle,
939 if (!SetEvent(input_facility->
overlapped.hEvent))
942 fprintf(stderr,
"DEBUG: tap read succeeded immediately\n");
958 hdr->
size = htons(size);
968 int err = GetLastError();
969 if (ERROR_IO_PENDING == err)
980 fprintf(stderr,
"FATAL: Read from handle failed, allowing write to finish\n");
991 if (GetOverlappedResult(input_facility->
handle,
996 if (!ResetEvent(input_facility->
overlapped.hEvent))
999 fprintf(stderr,
"DEBUG: tap read succeeded delayed\n");
1015 hdr->
size = htons(size);
1028 int err = GetLastError();
1029 if ((ERROR_IO_INCOMPLETE != err) && (ERROR_IO_PENDING != err))
1035 fprintf(stderr,
"FATAL: Read from handle failed, allowing write to finish\n");
1050 hdr->
size = htons(size);
1100 partial_read_iostate_ready:
1101 if (!ResetEvent(input_facility->
overlapped.hEvent))
1105 if (ReadFile(input_facility->
handle,
1114 if (!SetEvent(input_facility->
overlapped.hEvent))
1117 fprintf(stderr,
"DEBUG: stdin read succeeded immediately\n");
1121 ntohs(hdr->
size) >
sizeof(input_facility->
buffer))
1123 fprintf(stderr,
"WARNING: Protocol violation, got GNUnet Message type %h, size %h\n", ntohs(hdr->
type), ntohs(hdr->
size));
1129 goto partial_read_iostate_ready;
1153 int err = GetLastError();
1154 if (ERROR_IO_PENDING == err)
1163 fprintf(stderr,
"FATAL: Read from handle failed, allowing write to finish\n");
1173 if (GetOverlappedResult(input_facility->
handle,
1180 if (!ResetEvent(input_facility->
overlapped.hEvent))
1183 fprintf(stderr,
"DEBUG: stdin read succeeded delayed\n");
1187 (ntohs(hdr->
size) >
sizeof(input_facility->
buffer)))
1189 fprintf(stderr,
"WARNING: Protocol violation, got GNUnet Message type %h, size %h\n", ntohs(hdr->
type), ntohs(hdr->
size));
1196 goto partial_read_iostate_ready;
1218 int err = GetLastError();
1219 if ((ERROR_IO_INCOMPLETE != err) && (ERROR_IO_PENDING != err))
1225 fprintf(stderr,
"FATAL: Read from handle failed, allowing write to finish\n");
1264 continue_partial_write:
1265 if (!ResetEvent(output_facility->
overlapped.hEvent))
1269 if (WriteFile(output_facility->
handle,
1275 fprintf(stderr,
"DEBUG: write succeeded immediately\n");
1279 if (!SetEvent(output_facility->
overlapped.hEvent))
1284 goto continue_partial_write;
1297 int err = GetLastError();
1298 if (ERROR_IO_PENDING == err)
1306 fprintf(stderr,
"FATAL: Write to handle failed, exiting\n");
1314 if (GetOverlappedResult(output_facility->
handle,
1319 if (!ResetEvent(output_facility->
overlapped.hEvent))
1322 fprintf(stderr,
"DEBUG: write succeeded delayed\n");
1327 goto continue_partial_write;
1340 int err = GetLastError();
1341 if ((ERROR_IO_INCOMPLETE != err) && (ERROR_IO_PENDING != err))
1345 fprintf(stderr,
"FATAL: Write to handle failed, exiting\n");
1369 elem->
handle = INVALID_HANDLE_VALUE;
1372 elem->
overlapped.hEvent = CreateEvent(NULL, TRUE, signaled, NULL);
1397 HANDLE parent_std_in_handle = GetStdHandle(STD_INPUT_HANDLE);
1398 HANDLE parent_std_out_handle = GetStdHandle(STD_OUTPUT_HANDLE);
1408 goto teardown_final;
1415 goto teardown_final;
1418 tap_read.
handle = tap_handle;
1419 tap_write.
handle = tap_handle;
1421 #ifdef DEBUG_TO_CONSOLE 1423 std_in.
handle = parent_std_in_handle;
1424 std_out.
handle = parent_std_out_handle;
1426 fprintf(stderr,
"DEBUG: reopening stdin/out for overlapped IO\n");
1432 if ((FILE_TYPE_PIPE != GetFileType(parent_std_in_handle)) ||
1433 (FILE_TYPE_PIPE != GetFileType(parent_std_out_handle)))
1435 fprintf(stderr,
"ERROR: stdin/stdout must be named pipes\n");
1441 FILE_SHARE_WRITE | FILE_SHARE_READ,
1442 FILE_FLAG_OVERLAPPED);
1444 if (INVALID_HANDLE_VALUE == std_in.
handle)
1446 fprintf(stderr,
"FATAL: Could not reopen stdin for in overlapped mode, has to be a named pipe\n");
1453 FILE_FLAG_OVERLAPPED);
1455 if (INVALID_HANDLE_VALUE == std_out.
handle)
1457 fprintf(stderr,
"FATAL: Could not reopen stdout for in overlapped mode, has to be a named pipe\n");
1462 fprintf(stderr,
"DEBUG: mainloop has begun\n");
1482 fprintf(stderr,
"DEBUG: teardown initiated\n");
1486 CancelIo(tap_handle);
1488 CancelIo(std_out.
handle);
1492 CloseHandle(tap_handle);
1511 char hwid[LINE_LEN];
1514 int local_ret = EINVAL;
1515 BOOL have_ip4 = FALSE;
1516 BOOL have_ip6 = FALSE;
1517 BOOL have_nat44 = FALSE;
1519 if ((1 < argc) && (0 != strcmp(argv[1],
"-d")))
1524 "DEBUG: Running binary in privilege testing mode.");
1533 "FATAL: must supply 6 arguments\nUsage:\ngnunet-helper-exit [-d] <if name prefix> <uplink-interface name> <address6 or \"-\"> <netbits6> <address4 or \"-\"> <netmask4>\n");
1548 if (INVALID_HANDLE_VALUE == (handle =
init_tun()))
1550 fprintf(stderr,
"FATAL: could not initialize virtual-interface %s with IPv6 %s/%s and IPv4 %s/%s\n",
1560 fprintf(stderr,
"DEBUG: Setting IPs, if needed\n");
1561 if (0 != strcmp(argv[3],
"-"))
1563 char command[LINE_LEN];
1564 const char *
address = argv[3];
1565 long prefix_len = atol(argv[4]);
1567 if ((prefix_len < 1) || (prefix_len > 127))
1569 fprintf(stderr,
"FATAL: ipv6 prefix_len out of range\n");
1574 fprintf(stderr,
"DEBUG: Setting IP6 address: %s/%d\n", address, prefix_len);
1575 if (0 != (global_ret =
set_address6(address, prefix_len)))
1581 fprintf(stderr,
"DEBUG: Setting IPv6 Forwarding for internal and external interface.\n");
1583 snprintf(command, LINE_LEN,
1584 "netsh interface ipv6 set interface interface=\"%s\" metric=1 forwarding=enabled store=active",
1589 fprintf(stderr,
"FATAL: Could not enable forwarding via netsh: %s\n", strerror(local_ret));
1593 snprintf(command, LINE_LEN,
1594 "netsh interface ipv6 set interface interface=\"%s\" metric=1 forwarding=enabled advertise=enabled store=active",
1599 fprintf(stderr,
"FATAL: Could not enable forwarding via netsh: %s\n", strerror(local_ret));
1606 if (0 != strcmp(argv[5],
"-"))
1608 const char *
address = argv[5];
1609 const char *mask = argv[6];
1611 fprintf(stderr,
"DEBUG: Setting IP4 address: %s/%s\n", address, mask);
1629 if (0 != strcmp(argv[2],
"-"))
1631 char command[LINE_LEN];
1634 fprintf(stderr,
"DEBUG: Adding NAPT/Masquerading between external IF %s and mine.\n", argv[2]);
1638 fprintf(stderr,
"FATAL: Could not install NAPT support via Netsh: %s\n", strerror(local_ret));
1642 snprintf(command, LINE_LEN,
1643 "netsh routing ip nat add interface \"%s\" full",
1648 fprintf(stderr,
"FATAL: IPv4-NAPT on external interface failed: %s\n", strerror(local_ret));
1652 snprintf(command, LINE_LEN,
1653 "netsh routing ip nat add interface \"%s\" private",
1658 fprintf(stderr,
"FATAL: IPv4-NAPT on internal interface failed: %s\n", strerror(local_ret));
1671 const char *
address = argv[5];
1674 char command[LINE_LEN];
1675 fprintf(stderr,
"DEBUG: removing IP4 NAPT from virtual interface \n");
1676 snprintf(command, LINE_LEN,
1677 "netsh routing ip nat del interface \"%s\"",
1681 fprintf(stderr,
"WARNING: Could not remove IPv4-NAPT from internal interface, hopefully this will have no effect in future runs: %s\n", strerror(local_ret));
1684 fprintf(stderr,
"DEBUG: Removing IP4 address\n");
1689 const char *
address = argv[3];
1690 fprintf(stderr,
"DEBUG: Removing IP6 address\n");
1694 fprintf(stderr,
"DEBUG: removing interface\n");
1696 fprintf(stderr,
"DEBUG: graceful exit completed\n");
static int set_address6(const char *address, unsigned long prefix_len)
Sets the IPv6-Address given in address on the interface dev.
static BOOL initialize_io_facility(struct io_facility *elem, int initial_state, BOOL signaled)
Initialize a overlapped structure.
BOOL path_open
If the path is open or blocked in general (used for quickly checking)
#define HARDWARE_ID
Hardware ID used in the inf-file.
static BOOL resolve_interface_name()
Do all the lookup necessary to retrieve the inteface's actual name off the registry.
overlapped I/O has been queued
DWORD buffer_size_processed
Amount of data actually written or read by readfile/writefile.
static HANDLE init_tun()
Creates a tun-interface called dev;.
#define TAP_WIN_MIN_MINOR
Minimum minor-id of the driver version we can work with.
TAP32 virtual network driver defines.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static char device_visible_name[256]
Device's visible Name, used to identify a network device in netsh.
static char * query_key
The key for the query.
DWORD buffer_size
How much of this buffer was used when reading or how much data can be written.
#define TAP_WIN_IOCTL_GET_VERSION
#define TAP_WIN_MIN_MAJOR
Minimum major-id of the driver version we can work with.
#define TAP_WIN_IOCTL_SET_MEDIA_STATUS
static int ret
Final status code.
static void run(HANDLE tap_handle)
Start forwarding to and from the tunnel.
static BOOL setup_interface()
Setup a new virtual interface to use for tunneling.
#define INF_FILE
Name or Path+Name of our win32 driver.
OVERLAPPED overlapped
Overlaped IO structure used for asynchronous IO in windows.
cryptographic primitives for GNUnet
Operlapped IO states for facility objects overlapped I/O has failed, stop processing.
#define GNUNET_memcpy(dst, src, n)
static int set_address4(const char *address, const char *mask)
Sets the IPv4-Address given in address on the interface dev.
int main(int argc, char **argv)
Open VPN tunnel interface.
static BOOL attempt_read_tap(struct io_facility *input_facility, struct io_facility *output_facility)
Attempts to read off an input facility (tap or named pipe) in overlapped mode.
static BOOL attempt_read_stdin(struct io_facility *input_facility, struct io_facility *output_facility)
Attempts to read off an input facility (tap or named pipe) in overlapped mode.
BOOL(WINAPI * LPFN_ISWOW64PROCESS)(HANDLE, PBOOL)
IsWow64Process definition for our is_win64, as this is a kernel function.
uint16_t status
See PRISM_STATUS_*-constants.
static void cleanup(void *cls)
Function scheduled as very last function, cleans up after us.
#define INF_FILE64
Name or Path+Name of our win64 driver.
static BOOL remove_interface()
Remove our new virtual interface to use for tunneling.
static char secondary_hwid[LINE_LEN/2]
Our local process' PID.
BOOL is_win64()
Determines if the host OS is win32 or win64.
static boolean privilege_testing
Will this binary be run in permissions testing mode?
static BOOL attempt_write(struct io_facility *output_facility, struct io_facility *input_facility)
Attempts to write to an output facility (tap or named pipe) in overlapped mode.
static void remove_address4(const char *address)
Removes the IPv4-Address given in address from the interface dev.
IO_State
Possible states of an IO facility.
static unsigned int size
Size of the "table".
there is a full buffer waiting
static HDEVINFO DeviceInfo
This is our own local instance of a virtual network interface It is (somewhat) equivalent to using tu...
static void remove_address6(const char *address)
Removes the IPv6-Address given in address from the interface dev.
enum IO_State facility_state
The mode the state machine associated with this object is in.
static char device_guid[256]
GUID of our virtual device in the form of {12345678-1234-1234-1234-123456789abc} - in hex...
unsigned char buffer[65536]
Buffer for reading things to and writing from...
#define USERMODEDEVICEDIR
overlapped I/O is ready for work
HANDLE handle
Windows Object-Handle (used for accessing TAP and STDIN/STDOUT)
static int inet_pton(int af, const char *cp, struct in_addr *buf)
Convert IPv4 address from text to binary form.
static BOOL tun_up(HANDLE handle)
Brings a TAP device up and sets it to connected state.
#define TAP32_POSTUP_WAITTIME
Time in seconds to wait for our virtual device to go up after telling it to do so.
static BOOL check_tapw32_version(HANDLE handle)
Determines the version of the installed TAP32 driver and checks if it's sufficiently new for GNUNET...
#define MAX_SIZE
Maximum size of a GNUnet message (GNUNET_MAX_MESSAGE_SIZE)
overlapped I/O has finished, but is waiting for it's write-partner
commonly used definitions; globals in this file are exempt from the rule that the module name ("commo...
static int execute_shellcommand(const char *command)
Wrapper for executing a shellcommand in windows.
A IO Object + read/writebuffer + buffer-size for windows asynchronous IO handling.
static SP_DEVINFO_DATA DeviceNode
Registry Key we hand over to windows to spawn a new virtual interface.
#define INTERFACE_REGISTRY_LOCATION
Location of the network interface list resides in registry.
static char * address
GNS address for this phone.
size_t GNUNET_strlcpy(char *dst, const char *src, size_t n)
Like strlcpy but portable.
static int global_ret
Return value from main.
static size_t strnlen(const char *s, size_t n)
WINBASEAPI HANDLE WINAPI ReOpenFile(HANDLE, DWORD, DWORD, DWORD)
ReOpenFile is only available as of XP SP2 and 2003 SP1.
#define GNUNET_MESSAGE_TYPE_VPN_HELPER
Type of messages between the gnunet-vpn-helper and the daemon.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
DWORD buffer_size_written
How much of this buffer we have written in total.