aboutsummaryrefslogtreecommitdiff
path: root/src/vpn/gnunet-helper-vpn-windows.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vpn/gnunet-helper-vpn-windows.c')
-rw-r--r--src/vpn/gnunet-helper-vpn-windows.c305
1 files changed, 209 insertions, 96 deletions
diff --git a/src/vpn/gnunet-helper-vpn-windows.c b/src/vpn/gnunet-helper-vpn-windows.c
index bf5585204..2df5377c6 100644
--- a/src/vpn/gnunet-helper-vpn-windows.c
+++ b/src/vpn/gnunet-helper-vpn-windows.c
@@ -36,6 +36,7 @@
36#include <setupapi.h> 36#include <setupapi.h>
37#include <ddk/cfgmgr32.h> 37#include <ddk/cfgmgr32.h>
38#include "platform.h" 38#include "platform.h"
39#include "tap-windows.h"
39#include <Winsock2.h> 40#include <Winsock2.h>
40 41
41/** 42/**
@@ -72,6 +73,31 @@
72#define HARDWARE_ID "TAP0901" 73#define HARDWARE_ID "TAP0901"
73 74
74/** 75/**
76 * Component ID if our driver
77 */
78#define TAP_WIN_COMPONENT_ID "tap0901"
79
80/**
81 * Minimum major-id of the driver version we can work with
82 */
83#define TAP_WIN_MIN_MAJOR 9
84
85/**
86 * Minimum minor-id of the driver version we can work with.
87 * v <= 7 has buggy IPv6.
88 * v == 8 is broken for small IPv4 Packets
89 */
90#define TAP_WIN_MIN_MINOR 9
91
92/**
93 * Time to wait for our virtual device to go up after telling it to do so.
94 *
95 * openvpn doesn't specify a value, 4 seems sane for testing, even for openwrt
96 * (in fact, 4 was chosen by a fair dice roll...)
97 */
98#define TAP32_POSTUP_WAITTIME 4
99
100/**
75 * Location of the network interface list resides in registry. 101 * Location of the network interface list resides in registry.
76 * TODO: is this fixed on all version of windows? Checked with XP and 7 102 * TODO: is this fixed on all version of windows? Checked with XP and 7
77 */ 103 */
@@ -106,17 +132,10 @@ static HDEVINFO DeviceInfo = INVALID_HANDLE_VALUE;
106static SP_DEVINFO_DATA DeviceNode; 132static SP_DEVINFO_DATA DeviceNode;
107 133
108/** 134/**
109 * Class-tag of our virtual device
110 */
111static char class[128];
112
113/**
114 * GUID of our virtual device in the form of 135 * GUID of our virtual device in the form of
115 * {12345678-1234-1234-1234-123456789abc} - in hex 136 * {12345678-1234-1234-1234-123456789abc} - in hex
116 */ 137 */
117static GUID guid; 138static char device_guid[256];
118
119
120/** 139/**
121 * inet_pton() wrapper for WSAStringToAddress() 140 * inet_pton() wrapper for WSAStringToAddress()
122 * 141 *
@@ -131,6 +150,7 @@ static GUID guid;
131#if WINVER >= 0x0600 150#if WINVER >= 0x0600
132int inet_pton (int af, const char *src, void *dst); 151int inet_pton (int af, const char *src, void *dst);
133#else 152#else
153
134int 154int
135inet_pton (int af, const char *src, void *dst) 155inet_pton (int af, const char *src, void *dst)
136{ 156{
@@ -158,6 +178,7 @@ inet_pton (int af, const char *src, void *dst)
158 return 0; 178 return 0;
159} 179}
160#endif 180#endif
181
161/** 182/**
162 * Wrapper for executing a shellcommand in windows. 183 * Wrapper for executing a shellcommand in windows.
163 * 184 *
@@ -220,8 +241,8 @@ set_address6 (const char *address, unsigned long prefix_len)
220 * prepare the command 241 * prepare the command
221 */ 242 */
222 snprintf (command, LINE_LEN, 243 snprintf (command, LINE_LEN,
223 "netsh interface ipv6 add address \"%s\" %s/%d", 244 "netsh interface ipv6 add address \"%s\" %s/%d",
224 device_visible_name, address, prefix_len); 245 device_visible_name, address, prefix_len);
225 /* 246 /*
226 * Set the address 247 * Set the address
227 */ 248 */
@@ -265,8 +286,8 @@ set_address4 (const char *address, const char *mask)
265 * prepare the command 286 * prepare the command
266 */ 287 */
267 snprintf (command, LINE_LEN, 288 snprintf (command, LINE_LEN,
268 "netsh interface ipv4 add address \"%s\" %s %s", 289 "netsh interface ipv4 add address \"%s\" %s %s",
269 device_visible_name, address, mask); 290 device_visible_name, address, mask);
270 /* 291 /*
271 * Set the address 292 * Set the address
272 */ 293 */
@@ -296,10 +317,10 @@ setup_interface ()
296 */ 317 */
297 char inf_file_path[MAX_PATH]; 318 char inf_file_path[MAX_PATH];
298 char hwidlist[LINE_LEN + 4]; 319 char hwidlist[LINE_LEN + 4];
299 320 char class_name[128];
321 GUID class_guid;
300 int str_lenth = 0; 322 int str_lenth = 0;
301 323
302
303 /** 324 /**
304 * Set the device's hardware ID and add it to a list. 325 * Set the device's hardware ID and add it to a list.
305 * This information will later on identify this device in registry. 326 * This information will later on identify this device in registry.
@@ -330,35 +351,35 @@ setup_interface ()
330 * Bootstrap our device info using the drivers inf-file 351 * Bootstrap our device info using the drivers inf-file
331 */ 352 */
332 if (!SetupDiGetINFClassA (inf_file_path, 353 if (!SetupDiGetINFClassA (inf_file_path,
333 &guid, 354 &class_guid,
334 class, sizeof (class) / sizeof (char), 355 class_name, sizeof (class_name) / sizeof (char),
335 NULL)) 356 NULL))
336 return FALSE; 357 return FALSE;
337 358
338 /** 359 /**
339 * Collect all the other needed information... 360 * Collect all the other needed information...
340 * let the system fill our this form 361 * let the system fill our this form
341 */ 362 */
342 DeviceInfo = SetupDiCreateDeviceInfoList (&guid, NULL); 363 DeviceInfo = SetupDiCreateDeviceInfoList (&class_guid, NULL);
343 if (DeviceInfo == INVALID_HANDLE_VALUE) 364 if (DeviceInfo == INVALID_HANDLE_VALUE)
344 return FALSE; 365 return FALSE;
345 366
346 DeviceNode.cbSize = sizeof (SP_DEVINFO_DATA); 367 DeviceNode.cbSize = sizeof (SP_DEVINFO_DATA);
347 if (!SetupDiCreateDeviceInfoA (DeviceInfo, 368 if (!SetupDiCreateDeviceInfoA (DeviceInfo,
348 class, 369 class_name,
349 &guid, 370 &class_guid,
350 NULL, 371 NULL,
351 NULL, 372 NULL,
352 DICD_GENERATE_ID, 373 DICD_GENERATE_ID,
353 &DeviceNode)) 374 &DeviceNode))
354 return FALSE; 375 return FALSE;
355 376
356 /* Deploy all the information collected into the registry */ 377 /* Deploy all the information collected into the registry */
357 if (!SetupDiSetDeviceRegistryPropertyA (DeviceInfo, 378 if (!SetupDiSetDeviceRegistryPropertyA (DeviceInfo,
358 &DeviceNode, 379 &DeviceNode,
359 SPDRP_HARDWAREID, 380 SPDRP_HARDWAREID,
360 (LPBYTE) hwidlist, 381 (LPBYTE) hwidlist,
361 (strlen (hwidlist) + 2) * sizeof (char))) 382 (strlen (hwidlist) + 2) * sizeof (char)))
362 return FALSE; 383 return FALSE;
363 384
364 /* Install our new class(=device) into the system */ 385 /* Install our new class(=device) into the system */
@@ -393,9 +414,9 @@ remove_interface ()
393 * uninstall related information into the structure 414 * uninstall related information into the structure
394 */ 415 */
395 if (!SetupDiSetClassInstallParamsA (DeviceInfo, 416 if (!SetupDiSetClassInstallParamsA (DeviceInfo,
396 (PSP_DEVINFO_DATA) & DeviceNode, 417 (PSP_DEVINFO_DATA) & DeviceNode,
397 &remove.ClassInstallHeader, 418 &remove.ClassInstallHeader,
398 sizeof (remove))) 419 sizeof (remove)))
399 return FALSE; 420 return FALSE;
400 /* 421 /*
401 * 2. Uninstall the virtual interface using the class installer 422 * 2. Uninstall the virtual interface using the class installer
@@ -432,19 +453,19 @@ resolve_interface_name ()
432 /* We can obtain the PNP instance ID from our setupapi handle */ 453 /* We can obtain the PNP instance ID from our setupapi handle */
433 device_details.cbSize = sizeof (device_details); 454 device_details.cbSize = sizeof (device_details);
434 if (CR_SUCCESS != CM_Get_Device_ID_ExA (DeviceNode.DevInst, 455 if (CR_SUCCESS != CM_Get_Device_ID_ExA (DeviceNode.DevInst,
435 (PCHAR) pnp_instance_id, 456 (PCHAR) pnp_instance_id,
436 MAX_DEVICE_ID_LEN, 457 MAX_DEVICE_ID_LEN,
437 0, //must be 0 458 0, //must be 0
438 NULL)) //hMachine, we are local 459 NULL)) //hMachine, we are local
439 return FALSE; 460 return FALSE;
440 461
441 /* Now we can use this ID to locate the correct networks interface in registry */ 462 /* Now we can use this ID to locate the correct networks interface in registry */
442 if (ERROR_SUCCESS != RegOpenKeyExA ( 463 if (ERROR_SUCCESS != RegOpenKeyExA (
443 HKEY_LOCAL_MACHINE, 464 HKEY_LOCAL_MACHINE,
444 adapter, 465 adapter,
445 0, 466 0,
446 KEY_READ, 467 KEY_READ,
447 &adapter_key_handle)) 468 &adapter_key_handle))
448 return FALSE; 469 return FALSE;
449 470
450 /* Of course there is a multitude of entries here, with arbitrary names, 471 /* Of course there is a multitude of entries here, with arbitrary names,
@@ -463,14 +484,14 @@ resolve_interface_name ()
463 len = sizeof (adapter_key_handle); 484 len = sizeof (adapter_key_handle);
464 /* optain a subkey of {4D36E972-E325-11CE-BFC1-08002BE10318} */ 485 /* optain a subkey of {4D36E972-E325-11CE-BFC1-08002BE10318} */
465 status = RegEnumKeyExA ( 486 status = RegEnumKeyExA (
466 adapter_key_handle, 487 adapter_key_handle,
467 i, 488 i,
468 instance_key, 489 instance_key,
469 &len, 490 &len,
470 NULL, 491 NULL,
471 NULL, 492 NULL,
472 NULL, 493 NULL,
473 NULL); 494 NULL);
474 495
475 /* this may fail due to one of two reasons: 496 /* this may fail due to one of two reasons:
476 * we are at the end of the list*/ 497 * we are at the end of the list*/
@@ -482,16 +503,16 @@ resolve_interface_name ()
482 503
483 /* prepare our new query string: */ 504 /* prepare our new query string: */
484 snprintf (query_key, 256, "%s\\%s\\Connection", 505 snprintf (query_key, 256, "%s\\%s\\Connection",
485 INTERFACE_REGISTRY_LOCATION, 506 INTERFACE_REGISTRY_LOCATION,
486 instance_key); 507 instance_key);
487 508
488 /* look inside instance_key\\Connection */ 509 /* look inside instance_key\\Connection */
489 status = RegOpenKeyExA ( 510 status = RegOpenKeyExA (
490 HKEY_LOCAL_MACHINE, 511 HKEY_LOCAL_MACHINE,
491 query_key, 512 query_key,
492 0, 513 0,
493 KEY_READ, 514 KEY_READ,
494 &instance_key_handle); 515 &instance_key_handle);
495 516
496 if (status != ERROR_SUCCESS) 517 if (status != ERROR_SUCCESS)
497 continue; 518 continue;
@@ -499,33 +520,40 @@ resolve_interface_name ()
499 /* now, read our PnpInstanceID */ 520 /* now, read our PnpInstanceID */
500 len = sizeof (pnpinstanceid_value); 521 len = sizeof (pnpinstanceid_value);
501 status = RegQueryValueExA (instance_key_handle, 522 status = RegQueryValueExA (instance_key_handle,
502 pnpinstanceid_name, 523 pnpinstanceid_name,
503 NULL, //reserved, always NULL according to MSDN 524 NULL, //reserved, always NULL according to MSDN
504 &data_type, 525 &data_type,
505 (LPBYTE) pnpinstanceid_value, 526 (LPBYTE) pnpinstanceid_value,
506 &len); 527 &len);
507 528
508 if (status != ERROR_SUCCESS || data_type != REG_SZ) 529 if (status != ERROR_SUCCESS || data_type != REG_SZ)
509 goto cleanup; 530 goto cleanup;
510 531
511 /* compare the value we got to our devices PNPInstanceID*/ 532 /* compare the value we got to our devices PNPInstanceID*/
512 if (0 != strncmp (pnpinstanceid_value, pnp_instance_id, 533 if (0 != strncmp (pnpinstanceid_value, pnp_instance_id,
513 sizeof (pnpinstanceid_value) / sizeof (char))) 534 sizeof (pnpinstanceid_value) / sizeof (char)))
514 goto cleanup; 535 goto cleanup;
515 536
516 len = sizeof (device_visible_name); 537 len = sizeof (device_visible_name);
517 status = RegQueryValueExA ( 538 status = RegQueryValueExA (
518 instance_key_handle, 539 instance_key_handle,
519 adaptername_name, 540 adaptername_name,
520 NULL, //reserved, always NULL according to MSDN 541 NULL, //reserved, always NULL according to MSDN
521 &data_type, 542 &data_type,
522 (LPBYTE) device_visible_name, 543 (LPBYTE) device_visible_name,
523 &len); 544 &len);
524 545
525 if (status == ERROR_SUCCESS && data_type == REG_SZ) 546 if (status != ERROR_SUCCESS || data_type != REG_SZ)
526 { 547 goto cleanup;
527 retval = TRUE; 548
528 } 549 /*
550 * we have successfully found OUR instance,
551 * save the device GUID before exiting
552 */
553
554 strncpy (device_guid, instance_key, 256);
555 retval = TRUE;
556
529cleanup: 557cleanup:
530 RegCloseKey (instance_key_handle); 558 RegCloseKey (instance_key_handle);
531 559
@@ -537,36 +565,111 @@ cleanup:
537 return retval; 565 return retval;
538} 566}
539 567
568static boolean
569check_tapw32_version (HANDLE handle)
570{
571 {
572 ULONG version[3];
573 DWORD len;
574 memset (&(version), 0, sizeof (version));
575
576
577 if (DeviceIoControl (handle, TAP_WIN_IOCTL_GET_VERSION,
578 &version, sizeof (version),
579 &version, sizeof (version), &len, NULL))
580 {
581#ifdef TESTING
582 fprintf (stderr, "TAP-Windows Driver Version %d.%d %s",
583 (int) version[0],
584 (int) version[1],
585 (version[2] ? "(DEBUG)" : ""));
586#endif
587 }
588
589 if (version[0] != TAP_WIN_MIN_MAJOR || version[1] < TAP_WIN_MIN_MINOR)
590 {
591 fprintf (stderr, "ERROR: This version of gnunet requires a TAP-Windows driver that is at least version %d.%d!\n",
592 TAP_WIN_MIN_MAJOR,
593 TAP_WIN_MIN_MINOR);
594 return FALSE;
595 }
596 return TRUE;
597 }
598}
599
540/** 600/**
541 * Creates a tun-interface called dev; 601 * Creates a tun-interface called dev;
542 * 602 *
543 * @return the fd to the tun or -1 on error 603 * @return the fd to the tun or -1 on error
544 */ 604 */
545static int 605static HANDLE
546init_tun () 606init_tun ()
547{ 607{
548 int fd = -1; 608 char device_path[256];
609 HANDLE handle;
549 610
550 if (!setup_interface ()) 611 if (!setup_interface ())
551 { 612 {
552 errno = ENODEV; 613 errno = ENODEV;
553 return -1; 614 return INVALID_HANDLE_VALUE;
554 } 615 }
555 616
556 if (!resolve_interface_name ()) 617 if (!resolve_interface_name ())
557 { 618 {
558 errno = ENODEV; 619 errno = ENODEV;
559 return -1; 620 return INVALID_HANDLE_VALUE;
560 } 621 }
561 622
562 //openvpn 623 /* Open Windows TAP-Windows adapter */
563 /* get driver MTU */ 624 snprintf (device_path, sizeof (device_path), "%s%s%s",
564 // tun.c:2869 625 USERMODEDEVICEDIR,
565 626 device_guid,
566 /* tun up: */ 627 TAP_WIN_SUFFIX);
567 // tun.c: 3024 628
568 629 handle = CreateFile (
569 return fd; 630 device_path,
631 GENERIC_READ | GENERIC_WRITE,
632 0, /* was: FILE_SHARE_READ */
633 0,
634 OPEN_EXISTING,
635 FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
636 0
637 );
638
639 if (handle == INVALID_HANDLE_VALUE)
640 {
641 fprintf (stderr, "CreateFile failed on TAP device: %s\n", device_path);
642 return handle;
643 }
644
645 /* get driver version info */
646 if (!check_tapw32_version (handle))
647 {
648 CloseHandle (handle);
649 return INVALID_HANDLE_VALUE;
650 }
651
652 return handle;
653}
654
655static boolean
656tun_up (HANDLE handle)
657{
658 ULONG status = TRUE;
659 DWORD len;
660 if (DeviceIoControl (handle, TAP_WIN_IOCTL_SET_MEDIA_STATUS,
661 &status, sizeof (status),
662 &status, sizeof (status), &len, NULL))
663 {
664 fprintf (stderr, "The TAP-Windows driver ignored our request to set the interface UP (TAP_WIN_IOCTL_SET_MEDIA_STATUS DeviceIoControl call)!\n");
665 return FALSE;
666 }
667
668 /* Wait for the device to go UP, might take some time. */
669 Sleep ((TAP32_POSTUP_WAITTIME)*1000);
670
671 return TRUE;
672
570} 673}
571 674
572/** 675/**
@@ -575,7 +678,7 @@ init_tun ()
575 * @param fd_tun tunnel FD 678 * @param fd_tun tunnel FD
576 */ 679 */
577static void 680static void
578run (int fd_tun) 681run (HANDLE handle)
579{ 682{
580 /* 683 /*
581 * The buffer filled by reading from fd_tun 684 * The buffer filled by reading from fd_tun
@@ -591,19 +694,29 @@ run (int fd_tun)
591 ssize_t bufin_size = 0; 694 ssize_t bufin_size = 0;
592 ssize_t bufin_rpos = 0; 695 ssize_t bufin_rpos = 0;
593 unsigned char *bufin_read = NULL; 696 unsigned char *bufin_read = NULL;
594 /* Hello, I am a stub function! I did my job, yay me! */ 697
595
596 //openvpn 698 //openvpn
597 699 // Set Device to Subnet-Mode?
700 // do we really need tun.c:2925 ?
701 // Why do we also assign IPv4's there??? Foobar??
702
703 /* tun up: */
704 if (!tun_up (handle))
705 goto teardown;
706
707 // tun.c:3038
708
598 // mainloop: 709 // mainloop:
599 // tunnel_point_to_point 710 // tunnel_point_to_point
600 //openvpn.c:62 711 //openvpn.c:62
601 712
713 // init.c:3337
602 /* setup ansync IO */ 714 /* setup ansync IO */
603 //forward.c: 1515 715 //forward.c: 1515
604 716
605 717
606 //teardown: 718teardown:
719 ;
607 //init.c:3472 720 //init.c:3472
608} 721}
609 722
@@ -622,7 +735,7 @@ int
622main (int argc, char **argv) 735main (int argc, char **argv)
623{ 736{
624 char hwid[LINE_LEN]; 737 char hwid[LINE_LEN];
625 int fd_tun; 738 HANDLE handle;
626 int global_ret; 739 int global_ret;
627 740
628 if (6 != argc) 741 if (6 != argc)
@@ -640,10 +753,10 @@ main (int argc, char **argv)
640 * as additional hardware-id for our device. 753 * as additional hardware-id for our device.
641 */ 754 */
642 snprintf (secondary_hwid, LINE_LEN / 2, "%s-%d", 755 snprintf (secondary_hwid, LINE_LEN / 2, "%s-%d",
643 hwid, 756 hwid,
644 _getpid ()); 757 _getpid ());
645 758
646 if (-1 == (fd_tun = init_tun ())) 759 if (INVALID_HANDLE_VALUE == (handle = init_tun ()))
647 { 760 {
648 fprintf (stderr, "Fatal: could not initialize virtual-interface %s with IPv6 %s/%s and IPv4 %s/%s\n", 761 fprintf (stderr, "Fatal: could not initialize virtual-interface %s with IPv6 %s/%s and IPv4 %s/%s\n",
649 hwid, 762 hwid,
@@ -681,7 +794,7 @@ main (int argc, char **argv)
681 // tap_allow_nonadmin_access 794 // tap_allow_nonadmin_access
682 //tun.c:2023 795 //tun.c:2023
683 796
684 run (fd_tun); 797 run (handle);
685 global_ret = 0; 798 global_ret = 0;
686cleanup: 799cleanup:
687 remove_interface (); 800 remove_interface ();