aboutsummaryrefslogtreecommitdiff
path: root/src/vpn
diff options
context:
space:
mode:
authorChristian Fuchs <christian.fuchs@cfuchs.net>2013-01-17 14:23:24 +0000
committerChristian Fuchs <christian.fuchs@cfuchs.net>2013-01-17 14:23:24 +0000
commit98ff7cc0d495e235024467467c77409ac5359253 (patch)
tree1c939e8b12a5d166c87ec42477215026db407ee6 /src/vpn
parentb2671f5cb4e45f6902b0cfe05147b18d36bb2788 (diff)
downloadgnunet-98ff7cc0d495e235024467467c77409ac5359253.tar.gz
gnunet-98ff7cc0d495e235024467467c77409ac5359253.zip
* a little bit of bugfixing
* added functionality to remove ip addresses from our interfaces * some formatting work * added rety-loop for the interface-name resolver (retry up to 30 seconds) * set new ipv4/v6 addresses to be forgotten on bootup (store=active) * adjusted some debug output (added a few \n here and there)
Diffstat (limited to 'src/vpn')
-rw-r--r--src/vpn/gnunet-helper-vpn-windows.c600
1 files changed, 340 insertions, 260 deletions
diff --git a/src/vpn/gnunet-helper-vpn-windows.c b/src/vpn/gnunet-helper-vpn-windows.c
index 5249bfd70..05a0aeeff 100644
--- a/src/vpn/gnunet-helper-vpn-windows.c
+++ b/src/vpn/gnunet-helper-vpn-windows.c
@@ -37,6 +37,7 @@
37#include <ddk/cfgmgr32.h> 37#include <ddk/cfgmgr32.h>
38#include <ddk/newdev.h> 38#include <ddk/newdev.h>
39#include <Winsock2.h> 39#include <Winsock2.h>
40#include <time.h>
40#include "platform.h" 41#include "platform.h"
41#include "tap-windows.h" 42#include "tap-windows.h"
42/** 43/**
@@ -184,6 +185,7 @@ execute_shellcommand (const char *command)
184 return EINVAL; 185 return EINVAL;
185 186
186#ifdef TESTING 187#ifdef TESTING
188 fprintf (stderr, "DEBUG: Command output: \n");
187 char output[LINE_LEN]; 189 char output[LINE_LEN];
188 while (NULL != fgets (output, sizeof (output), pipe)) 190 while (NULL != fgets (output, sizeof (output), pipe))
189 fprintf (stderr, "%s", output); 191 fprintf (stderr, "%s", output);
@@ -212,7 +214,7 @@ set_address6 (const char *address, unsigned long prefix_len)
212 sa6.sin6_family = AF_INET6; 214 sa6.sin6_family = AF_INET6;
213 if (1 != inet_pton (AF_INET6, address, &sa6.sin6_addr.s6_addr)) 215 if (1 != inet_pton (AF_INET6, address, &sa6.sin6_addr.s6_addr))
214 { 216 {
215 fprintf (stderr, "Failed to parse address `%s': %s\n", address, 217 fprintf (stderr, "ERROR: Failed to parse address `%s': %s\n", address,
216 strerror (errno)); 218 strerror (errno));
217 return -1; 219 return -1;
218 } 220 }
@@ -221,7 +223,7 @@ set_address6 (const char *address, unsigned long prefix_len)
221 * prepare the command 223 * prepare the command
222 */ 224 */
223 snprintf (command, LINE_LEN, 225 snprintf (command, LINE_LEN,
224 "netsh interface ipv6 add address \"%s\" %s/%d", 226 "netsh interface ipv6 add address \"%s\" %s/%d store=active",
225 device_visible_name, address, prefix_len); 227 device_visible_name, address, prefix_len);
226 /* 228 /*
227 * Set the address 229 * Set the address
@@ -230,11 +232,42 @@ set_address6 (const char *address, unsigned long prefix_len)
230 232
231 /* Did it work?*/ 233 /* Did it work?*/
232 if (0 != ret) 234 if (0 != ret)
233 fprintf (stderr, "Setting IPv6 address failed: %s\n", strerror (ret)); 235 fprintf (stderr, "FATAL: Setting IPv6 address failed: %s\n", strerror (ret));
234 return ret; 236 return ret;
235} 237}
236 238
237/** 239/**
240 * @brief Removes the IPv6-Address given in address from the interface dev
241 *
242 * @param dev the interface to remove
243 * @param address the IPv4-Address
244 * @param mask the netmask
245 */
246static void
247remove_address6 (const char *address)
248{
249 char command[LINE_LEN];
250 int ret = EINVAL;
251
252 // sanity checking was already done in set_address6
253 /*
254 * prepare the command
255 */
256 snprintf (command, LINE_LEN,
257 "netsh interface ipv6 delete address \"%s\" store=persistent",
258 device_visible_name, address);
259 /*
260 * Set the address
261 */
262 ret = execute_shellcommand (command);
263
264 /* Did it work?*/
265 if (0 != ret)
266 fprintf (stderr, "FATAL: removing IPv6 address failed: %s\n", strerror (ret));
267}
268
269
270/**
238 * @brief Sets the IPv4-Address given in address on the interface dev 271 * @brief Sets the IPv4-Address given in address on the interface dev
239 * 272 *
240 * @param dev the interface to configure 273 * @param dev the interface to configure
@@ -255,7 +288,7 @@ set_address4 (const char *address, const char *mask)
255 */ 288 */
256 if (1 != inet_pton (AF_INET, address, &addr.sin_addr.s_addr)) 289 if (1 != inet_pton (AF_INET, address, &addr.sin_addr.s_addr))
257 { 290 {
258 fprintf (stderr, "Failed to parse address `%s': %s\n", address, 291 fprintf (stderr, "ERROR: Failed to parse address `%s': %s\n", address,
259 strerror (errno)); 292 strerror (errno));
260 return -1; 293 return -1;
261 } 294 }
@@ -266,7 +299,7 @@ set_address4 (const char *address, const char *mask)
266 * prepare the command 299 * prepare the command
267 */ 300 */
268 snprintf (command, LINE_LEN, 301 snprintf (command, LINE_LEN,
269 "netsh interface ipv4 add address \"%s\" %s %s", 302 "netsh interface ipv4 add address \"%s\" %s %s store=active",
270 device_visible_name, address, mask); 303 device_visible_name, address, mask);
271 /* 304 /*
272 * Set the address 305 * Set the address
@@ -275,11 +308,42 @@ set_address4 (const char *address, const char *mask)
275 308
276 /* Did it work?*/ 309 /* Did it work?*/
277 if (0 != ret) 310 if (0 != ret)
278 fprintf (stderr, "Setting IPv4 address failed: %s\n", strerror (ret)); 311 fprintf (stderr, "FATAL: Setting IPv4 address failed: %s\n", strerror (ret));
279 return ret; 312 return ret;
280} 313}
281 314
282/** 315/**
316 * @brief Removes the IPv4-Address given in address from the interface dev
317 *
318 * @param dev the interface to remove
319 * @param address the IPv4-Address
320 * @param mask the netmask
321 */
322static void
323remove_address4 (const char *address)
324{
325 char command[LINE_LEN];
326 int ret = EINVAL;
327
328 // sanity checking was already done in set_address4
329
330 /*
331 * prepare the command
332 */
333 snprintf (command, LINE_LEN,
334 "netsh interface ipv4 delete address \"%s\" gateway=all store=persistent",
335 device_visible_name, address);
336 /*
337 * Set the address
338 */
339 ret = execute_shellcommand (command);
340
341 /* Did it work?*/
342 if (0 != ret)
343 fprintf (stderr, "FATAL: removing IPv4 address failed: %s\n", strerror (ret));
344}
345
346/**
283 * Setup a new virtual interface to use for tunneling. 347 * Setup a new virtual interface to use for tunneling.
284 * 348 *
285 * @return: TRUE if setup was successful, else FALSE 349 * @return: TRUE if setup was successful, else FALSE
@@ -327,7 +391,7 @@ setup_interface ()
327 /** 391 /**
328 * Bootstrap our device info using the drivers inf-file 392 * Bootstrap our device info using the drivers inf-file
329 */ 393 */
330 if (!SetupDiGetINFClassA (inf_file_path, 394 if ( ! SetupDiGetINFClassA (inf_file_path,
331 &class_guid, 395 &class_guid,
332 class_name, sizeof (class_name) / sizeof (char), 396 class_name, sizeof (class_name) / sizeof (char),
333 NULL)) 397 NULL))
@@ -342,7 +406,7 @@ setup_interface ()
342 return FALSE; 406 return FALSE;
343 407
344 DeviceNode.cbSize = sizeof (SP_DEVINFO_DATA); 408 DeviceNode.cbSize = sizeof (SP_DEVINFO_DATA);
345 if (!SetupDiCreateDeviceInfoA (DeviceInfo, 409 if ( ! SetupDiCreateDeviceInfoA (DeviceInfo,
346 class_name, 410 class_name,
347 &class_guid, 411 &class_guid,
348 NULL, 412 NULL,
@@ -352,7 +416,7 @@ setup_interface ()
352 return FALSE; 416 return FALSE;
353 417
354 /* Deploy all the information collected into the registry */ 418 /* Deploy all the information collected into the registry */
355 if (!SetupDiSetDeviceRegistryPropertyA (DeviceInfo, 419 if ( ! SetupDiSetDeviceRegistryPropertyA (DeviceInfo,
356 &DeviceNode, 420 &DeviceNode,
357 SPDRP_HARDWAREID, 421 SPDRP_HARDWAREID,
358 (LPBYTE) hwidlist, 422 (LPBYTE) hwidlist,
@@ -360,14 +424,14 @@ setup_interface ()
360 return FALSE; 424 return FALSE;
361 425
362 /* Install our new class(=device) into the system */ 426 /* Install our new class(=device) into the system */
363 if (!SetupDiCallClassInstaller (DIF_REGISTERDEVICE, 427 if ( ! SetupDiCallClassInstaller (DIF_REGISTERDEVICE,
364 DeviceInfo, 428 DeviceInfo,
365 &DeviceNode)) 429 &DeviceNode))
366 return FALSE; 430 return FALSE;
367 431
368 /* This system call tends to take a while (several seconds!) on 432 /* This system call tends to take a while (several seconds!) on
369 "modern" Windoze systems */ 433 "modern" Windoze systems */
370 if (!UpdateDriverForPlugAndPlayDevicesA (NULL, 434 if ( ! UpdateDriverForPlugAndPlayDevicesA (NULL,
371 secondary_hwid, 435 secondary_hwid,
372 inf_file_path, 436 inf_file_path,
373 INSTALLFLAG_FORCE | INSTALLFLAG_NONINTERACTIVE, 437 INSTALLFLAG_FORCE | INSTALLFLAG_NONINTERACTIVE,
@@ -399,7 +463,7 @@ remove_interface ()
399 * 1. Prepare our existing device information set, and place the 463 * 1. Prepare our existing device information set, and place the
400 * uninstall related information into the structure 464 * uninstall related information into the structure
401 */ 465 */
402 if (!SetupDiSetClassInstallParamsA (DeviceInfo, 466 if ( ! SetupDiSetClassInstallParamsA (DeviceInfo,
403 (PSP_DEVINFO_DATA) & DeviceNode, 467 (PSP_DEVINFO_DATA) & DeviceNode,
404 &remove.ClassInstallHeader, 468 &remove.ClassInstallHeader,
405 sizeof (remove))) 469 sizeof (remove)))
@@ -407,7 +471,7 @@ remove_interface ()
407 /* 471 /*
408 * 2. Uninstall the virtual interface using the class installer 472 * 2. Uninstall the virtual interface using the class installer
409 */ 473 */
410 if (!SetupDiCallClassInstaller (DIF_REMOVE, 474 if ( ! SetupDiCallClassInstaller (DIF_REMOVE,
411 DeviceInfo, 475 DeviceInfo,
412 (PSP_DEVINFO_DATA) & DeviceNode)) 476 (PSP_DEVINFO_DATA) & DeviceNode))
413 return FALSE; 477 return FALSE;
@@ -426,19 +490,16 @@ remove_interface ()
426static boolean 490static boolean
427resolve_interface_name () 491resolve_interface_name ()
428{ 492{
429
430 SP_DEVINFO_LIST_DETAIL_DATA device_details; 493 SP_DEVINFO_LIST_DETAIL_DATA device_details;
431 char pnp_instance_id [MAX_DEVICE_ID_LEN]; 494 char pnp_instance_id [MAX_DEVICE_ID_LEN];
432 HKEY adapter_key_handle; 495 HKEY adapter_key_handle;
433 LONG status; 496 LONG status;
434 DWORD len; 497 DWORD len;
435 int i = 0; 498 int i = 0;
499 int retrys;
436 boolean retval = FALSE; 500 boolean retval = FALSE;
437 char adapter[] = INTERFACE_REGISTRY_LOCATION; 501 char adapter[] = INTERFACE_REGISTRY_LOCATION;
438 502
439 /* Registry is incredibly slow, wait a few seconds for it to refresh */
440 sleep (5); // FIXME: instead use sleep (1) in a retrying loop; maybe even nanosleep for 50-250ms instead
441
442 /* We can obtain the PNP instance ID from our setupapi handle */ 503 /* We can obtain the PNP instance ID from our setupapi handle */
443 device_details.cbSize = sizeof (device_details); 504 device_details.cbSize = sizeof (device_details);
444 if (CR_SUCCESS != CM_Get_Device_ID_ExA (DeviceNode.DevInst, 505 if (CR_SUCCESS != CM_Get_Device_ID_ExA (DeviceNode.DevInst,
@@ -448,142 +509,145 @@ resolve_interface_name ()
448 NULL)) //hMachine, we are local 509 NULL)) //hMachine, we are local
449 return FALSE; 510 return FALSE;
450 511
451 /* Now we can use this ID to locate the correct networks interface in registry */ 512 /* Registry is incredibly slow, retry for up to 30 seconds to allow registry to refresh */
452 if (ERROR_SUCCESS != RegOpenKeyExA ( 513 for (retrys = 0; retrys < 120 && !retval; retrys++)
453 HKEY_LOCAL_MACHINE,
454 adapter,
455 0,
456 KEY_READ,
457 &adapter_key_handle))
458 return FALSE;
459
460 /* Of course there is a multitude of entries here, with arbitrary names,
461 * thus we need to iterate through there.
462 */
463 while (!retval)
464 { 514 {
465 char instance_key[256]; 515 /* sleep for 250ms*/
466 char query_key [256]; 516 Sleep (250);
467 HKEY instance_key_handle; 517
468 char pnpinstanceid_name[] = "PnpInstanceID"; 518 /* Now we can use this ID to locate the correct networks interface in registry */
469 char pnpinstanceid_value[256]; 519 if (ERROR_SUCCESS != RegOpenKeyExA (
470 char adaptername_name[] = "Name"; 520 HKEY_LOCAL_MACHINE,
471 DWORD data_type; 521 adapter,
472 522 0,
473 len = 256 * sizeof (char); 523 KEY_READ,
474 /* optain a subkey of {4D36E972-E325-11CE-BFC1-08002BE10318} */ 524 &adapter_key_handle))
475 status = RegEnumKeyExA ( 525 return FALSE;
476 adapter_key_handle,
477 i,
478 instance_key,
479 &len,
480 NULL,
481 NULL,
482 NULL,
483 NULL);
484
485 /* this may fail due to one of two reasons:
486 * we are at the end of the list*/
487 if (ERROR_NO_MORE_ITEMS == status)
488 break;
489 // * we found a broken registry key, continue with the next key.
490 if (ERROR_SUCCESS != status)
491 goto cleanup;
492
493 /* prepare our new query string: */
494 snprintf (query_key, 256, "%s\\%s\\Connection",
495 adapter,
496 instance_key);
497
498 /* look inside instance_key\\Connection */
499 status = RegOpenKeyExA (
500 HKEY_LOCAL_MACHINE,
501 query_key,
502 0,
503 KEY_READ,
504 &instance_key_handle);
505
506 if (status != ERROR_SUCCESS)
507 goto cleanup;
508
509 /* now, read our PnpInstanceID */
510 len = sizeof (pnpinstanceid_value);
511 status = RegQueryValueExA (instance_key_handle,
512 pnpinstanceid_name,
513 NULL, //reserved, always NULL according to MSDN
514 &data_type,
515 (LPBYTE) pnpinstanceid_value,
516 &len);
517
518 if (status != ERROR_SUCCESS || data_type != REG_SZ)
519 goto cleanup;
520
521 /* compare the value we got to our devices PNPInstanceID*/
522 if (0 != strncmp (pnpinstanceid_value, pnp_instance_id,
523 sizeof (pnpinstanceid_value) / sizeof (char)))
524 goto cleanup;
525
526 len = sizeof (device_visible_name);
527 status = RegQueryValueExA (
528 instance_key_handle,
529 adaptername_name,
530 NULL, //reserved, always NULL according to MSDN
531 &data_type,
532 (LPBYTE) device_visible_name,
533 &len);
534
535 if (status != ERROR_SUCCESS || data_type != REG_SZ)
536 goto cleanup;
537 526
538 /* 527 /* Of course there is a multitude of entries here, with arbitrary names,
539 * we have successfully found OUR instance, 528 * thus we need to iterate through there.
540 * save the device GUID before exiting
541 */ 529 */
542 530 while ( ! retval)
543 strncpy (device_guid, instance_key, 256); 531 {
544 retval = TRUE; 532 char instance_key[256];
533 char query_key [256];
534 HKEY instance_key_handle;
535 char pnpinstanceid_name[] = "PnpInstanceID";
536 char pnpinstanceid_value[256];
537 char adaptername_name[] = "Name";
538 DWORD data_type;
539
540 len = 256 * sizeof (char);
541 /* optain a subkey of {4D36E972-E325-11CE-BFC1-08002BE10318} */
542 status = RegEnumKeyExA (
543 adapter_key_handle,
544 i,
545 instance_key,
546 &len,
547 NULL,
548 NULL,
549 NULL,
550 NULL);
551
552 /* this may fail due to one of two reasons:
553 * we are at the end of the list*/
554 if (ERROR_NO_MORE_ITEMS == status)
555 break;
556 // * we found a broken registry key, continue with the next key.
557 if (ERROR_SUCCESS != status)
558 goto cleanup;
559
560 /* prepare our new query string: */
561 snprintf (query_key, 256, "%s\\%s\\Connection",
562 adapter,
563 instance_key);
564
565 /* look inside instance_key\\Connection */
566 status = RegOpenKeyExA (
567 HKEY_LOCAL_MACHINE,
568 query_key,
569 0,
570 KEY_READ,
571 &instance_key_handle);
572
573 if (status != ERROR_SUCCESS)
574 goto cleanup;
575
576 /* now, read our PnpInstanceID */
577 len = sizeof (pnpinstanceid_value);
578 status = RegQueryValueExA (instance_key_handle,
579 pnpinstanceid_name,
580 NULL, //reserved, always NULL according to MSDN
581 &data_type,
582 (LPBYTE) pnpinstanceid_value,
583 &len);
584
585 if (status != ERROR_SUCCESS || data_type != REG_SZ)
586 goto cleanup;
587
588 /* compare the value we got to our devices PNPInstanceID*/
589 if (0 != strncmp (pnpinstanceid_value, pnp_instance_id,
590 sizeof (pnpinstanceid_value) / sizeof (char)))
591 goto cleanup;
592
593 len = sizeof (device_visible_name);
594 status = RegQueryValueExA (
595 instance_key_handle,
596 adaptername_name,
597 NULL, //reserved, always NULL according to MSDN
598 &data_type,
599 (LPBYTE) device_visible_name,
600 &len);
601
602 if (status != ERROR_SUCCESS || data_type != REG_SZ)
603 goto cleanup;
604
605 /*
606 * we have successfully found OUR instance,
607 * save the device GUID before exiting
608 */
609
610 strncpy (device_guid, instance_key, 256);
611 retval = TRUE;
612 fprintf (stderr, "DEBUG: Interface Name lookup succeeded on retry %d\n", retrys);
545 613
546cleanup: 614cleanup:
547 RegCloseKey (instance_key_handle); 615 RegCloseKey (instance_key_handle);
548 616
549 ++i; 617 ++i;
550 } 618 }
551
552 RegCloseKey (adapter_key_handle);
553 619
620 RegCloseKey (adapter_key_handle);
621 }
554 return retval; 622 return retval;
555} 623}
556 624
557static boolean 625static boolean
558check_tapw32_version (HANDLE handle) 626check_tapw32_version (HANDLE handle)
559{ 627{
560 { 628 ULONG version[3];
561 ULONG version[3]; 629 DWORD len;
562 DWORD len; 630 memset (&(version), 0, sizeof (version));
563 memset (&(version), 0, sizeof (version));
564 631
565 632
566 if (DeviceIoControl (handle, TAP_WIN_IOCTL_GET_VERSION, 633 if (DeviceIoControl (handle, TAP_WIN_IOCTL_GET_VERSION,
567 &version, sizeof (version), 634 &version, sizeof (version),
568 &version, sizeof (version), &len, NULL)) 635 &version, sizeof (version), &len, NULL))
569 { 636 {
570#ifdef TESTING 637 fprintf (stderr, "INFO: TAP-Windows Driver Version %d.%d %s\n",
571 fprintf (stderr, "TAP-Windows Driver Version %d.%d %s", 638 (int) version[0],
572 (int) version[0], 639 (int) version[1],
573 (int) version[1], 640 (version[2] ? "(DEBUG)" : ""));
574 (version[2] ? "(DEBUG)" : "")); 641 }
575#endif
576 }
577 642
578 if (version[0] != TAP_WIN_MIN_MAJOR || version[1] < TAP_WIN_MIN_MINOR) 643 if (version[0] != TAP_WIN_MIN_MAJOR || version[1] < TAP_WIN_MIN_MINOR)
579 { 644 {
580 fprintf (stderr, "ERROR: This version of gnunet requires a TAP-Windows driver that is at least version %d.%d!\n", 645 fprintf (stderr, "FATAL: This version of gnunet requires a TAP-Windows driver that is at least version %d.%d!\n",
581 TAP_WIN_MIN_MAJOR, 646 TAP_WIN_MIN_MAJOR,
582 TAP_WIN_MIN_MINOR); 647 TAP_WIN_MIN_MINOR);
583 return FALSE; 648 return FALSE;
584 } 649 }
585 return TRUE; 650 return TRUE;
586 }
587} 651}
588 652
589/** 653/**
@@ -597,13 +661,13 @@ init_tun ()
597 char device_path[256]; 661 char device_path[256];
598 HANDLE handle; 662 HANDLE handle;
599 663
600 if (!setup_interface ()) 664 if ( ! setup_interface ())
601 { 665 {
602 errno = ENODEV; 666 errno = ENODEV;
603 return INVALID_HANDLE_VALUE; 667 return INVALID_HANDLE_VALUE;
604 } 668 }
605 669
606 if (!resolve_interface_name ()) 670 if ( ! resolve_interface_name ())
607 { 671 {
608 errno = ENODEV; 672 errno = ENODEV;
609 return INVALID_HANDLE_VALUE; 673 return INVALID_HANDLE_VALUE;
@@ -627,12 +691,12 @@ init_tun ()
627 691
628 if (handle == INVALID_HANDLE_VALUE) 692 if (handle == INVALID_HANDLE_VALUE)
629 { 693 {
630 fprintf (stderr, "CreateFile failed on TAP device: %s\n", device_path); 694 fprintf (stderr, "FATAL: CreateFile failed on TAP device: %s\n", device_path);
631 return handle; 695 return handle;
632 } 696 }
633 697
634 /* get driver version info */ 698 /* get driver version info */
635 if (!check_tapw32_version (handle)) 699 if ( ! check_tapw32_version (handle))
636 { 700 {
637 CloseHandle (handle); 701 CloseHandle (handle);
638 return INVALID_HANDLE_VALUE; 702 return INVALID_HANDLE_VALUE;
@@ -654,11 +718,11 @@ tun_up (HANDLE handle)
654{ 718{
655 ULONG status = TRUE; 719 ULONG status = TRUE;
656 DWORD len; 720 DWORD len;
657 if (DeviceIoControl (handle, TAP_WIN_IOCTL_SET_MEDIA_STATUS, 721 if ( ! DeviceIoControl (handle, TAP_WIN_IOCTL_SET_MEDIA_STATUS,
658 &status, sizeof (status), 722 &status, sizeof (status),
659 &status, sizeof (status), &len, NULL)) 723 &status, sizeof (status), &len, NULL))
660 { 724 {
661 fprintf (stderr, "The TAP-Windows driver ignored our request to set the interface UP (TAP_WIN_IOCTL_SET_MEDIA_STATUS DeviceIoControl call)!\n"); 725 fprintf (stderr, "FATAL: TAP driver ignored request to UP interface (DeviceIoControl call)!\n");
662 return FALSE; 726 return FALSE;
663 } 727 }
664 728
@@ -699,113 +763,113 @@ attempt_read (struct io_facility * input_facility,
699 struct io_facility * output_facility) 763 struct io_facility * output_facility)
700{ 764{
701 switch (input_facility->facility_state) 765 switch (input_facility->facility_state)
702 {
703 case IOSTATE_READY:
704 { 766 {
705 if (!ResetEvent (input_facility->overlapped.hEvent)) 767 case IOSTATE_READY:
706 { 768 {
707 return FALSE; 769 if ( ! ResetEvent (input_facility->overlapped.hEvent))
708 } 770 {
709 input_facility->status = ReadFile (input_facility->handle,
710 input_facility->buffer,
711 MAX_SIZE,
712 &input_facility->buffer_size,
713 &input_facility->overlapped);
714
715 /* Check how the task is handled */
716 if (input_facility->status)
717 {/* async event processed immediately*/
718
719 /* reset event manually*/
720 if (!SetEvent (input_facility->overlapped.hEvent))
721 return FALSE;
722
723 /* we successfully read something from the TAP and now need to
724 * send it our via STDOUT. Is that possible at the moment? */
725 if ((IOSTATE_READY == output_facility->facility_state ||
726 IOSTATE_WAITING == output_facility->facility_state)
727 && 0 < input_facility->buffer_size)
728 { /* hand over this buffers content */
729 memcpy (output_facility->buffer,
730 input_facility->buffer,
731 MAX_SIZE);
732 output_facility->buffer_size = input_facility->buffer_size;
733 output_facility->facility_state = IOSTATE_READY;
734 }
735 else if (0 < input_facility->buffer_size)
736 { /* If we have have read our buffer, wait for our write-partner*/
737 input_facility->facility_state = IOSTATE_WAITING;
738 // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish?
739 }
740 }
741 else /* operation was either queued or failed*/
742 {
743 int err = GetLastError ();
744 if (ERROR_IO_PENDING == err)
745 { /* operation queued */
746 input_facility->facility_state = IOSTATE_QUEUED;
747 }
748 else
749 { /* error occurred, let the rest of the elements finish */
750 input_facility->path_open = FALSE;
751 input_facility->facility_state = IOSTATE_FAILED;
752 if (IOSTATE_WAITING == output_facility->facility_state)
753 output_facility->path_open = FALSE;
754
755 fprintf (stderr, "Fatal: Read from handle failed, allowing write to finish!\n");
756 }
757 }
758 }
759 return TRUE;
760 // We are queued and should check if the read has finished
761 case IOSTATE_QUEUED:
762 {
763 // there was an operation going on already, check if that has completed now.
764 input_facility->status = GetOverlappedResult (input_facility->handle,
765 &input_facility->overlapped,
766 &input_facility->buffer_size,
767 FALSE);
768 if (input_facility->status)
769 {/* successful return for a queued operation */
770 if (!ResetEvent (input_facility->overlapped.hEvent))
771 return FALSE; 771 return FALSE;
772 772 }
773 /* we successfully read something from the TAP and now need to 773 input_facility->status = ReadFile (input_facility->handle,
774 * send it our via STDOUT. Is that possible at the moment? */ 774 input_facility->buffer,
775 if ((IOSTATE_READY == output_facility->facility_state || 775 MAX_SIZE,
776 IOSTATE_WAITING == output_facility->facility_state) 776 &input_facility->buffer_size,
777 && 0 < input_facility->buffer_size) 777 &input_facility->overlapped);
778 { /* hand over this buffers content */ 778
779 memcpy (output_facility->buffer, 779 /* Check how the task is handled */
780 input_facility->buffer, 780 if (input_facility->status)
781 MAX_SIZE); 781 {/* async event processed immediately*/
782 output_facility->buffer_size = input_facility->buffer_size; 782
783 output_facility->facility_state = IOSTATE_READY; 783 /* reset event manually*/
784 input_facility->facility_state = IOSTATE_READY; 784 if ( ! SetEvent (input_facility->overlapped.hEvent))
785 } 785 return FALSE;
786 else if (0 < input_facility->buffer_size) 786
787 { /* If we have have read our buffer, wait for our write-partner*/ 787 /* we successfully read something from the TAP and now need to
788 input_facility->facility_state = IOSTATE_WAITING; 788 * send it our via STDOUT. Is that possible at the moment? */
789 // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish? 789 if ((IOSTATE_READY == output_facility->facility_state ||
790 } 790 IOSTATE_WAITING == output_facility->facility_state)
791 } 791 && 0 < input_facility->buffer_size)
792 else 792 { /* hand over this buffers content */
793 { /* operation still pending/queued or failed? */ 793 memcpy (output_facility->buffer,
794 int err = GetLastError (); 794 input_facility->buffer,
795 if (ERROR_IO_INCOMPLETE != err && ERROR_IO_PENDING != err) 795 MAX_SIZE);
796 { /* error occurred, let the rest of the elements finish */ 796 output_facility->buffer_size = input_facility->buffer_size;
797 input_facility->path_open = FALSE; 797 output_facility->facility_state = IOSTATE_READY;
798 input_facility->facility_state = IOSTATE_FAILED; 798 }
799 if (IOSTATE_WAITING == output_facility->facility_state) 799 else if (0 < input_facility->buffer_size)
800 output_facility->path_open = FALSE; 800 { /* If we have have read our buffer, wait for our write-partner*/
801 fprintf (stderr, "Fatal: Read from handle failed, allowing write to finish!\n"); 801 input_facility->facility_state = IOSTATE_WAITING;
802 } 802 // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish?
803 } 803 }
804 }
805 else /* operation was either queued or failed*/
806 {
807 int err = GetLastError ();
808 if (ERROR_IO_PENDING == err)
809 { /* operation queued */
810 input_facility->facility_state = IOSTATE_QUEUED;
811 }
812 else
813 { /* error occurred, let the rest of the elements finish */
814 input_facility->path_open = FALSE;
815 input_facility->facility_state = IOSTATE_FAILED;
816 if (IOSTATE_WAITING == output_facility->facility_state)
817 output_facility->path_open = FALSE;
818
819 fprintf (stderr, "FATAL: Read from handle failed, allowing write to finish!\n");
820 }
821 }
822 }
823 return TRUE;
824 // We are queued and should check if the read has finished
825 case IOSTATE_QUEUED:
826 {
827 // there was an operation going on already, check if that has completed now.
828 input_facility->status = GetOverlappedResult (input_facility->handle,
829 &input_facility->overlapped,
830 &input_facility->buffer_size,
831 FALSE);
832 if (input_facility->status)
833 {/* successful return for a queued operation */
834 if ( ! ResetEvent (input_facility->overlapped.hEvent))
835 return FALSE;
836
837 /* we successfully read something from the TAP and now need to
838 * send it our via STDOUT. Is that possible at the moment? */
839 if ((IOSTATE_READY == output_facility->facility_state ||
840 IOSTATE_WAITING == output_facility->facility_state)
841 && 0 < input_facility->buffer_size)
842 { /* hand over this buffers content */
843 memcpy (output_facility->buffer,
844 input_facility->buffer,
845 MAX_SIZE);
846 output_facility->buffer_size = input_facility->buffer_size;
847 output_facility->facility_state = IOSTATE_READY;
848 input_facility->facility_state = IOSTATE_READY;
849 }
850 else if (0 < input_facility->buffer_size)
851 { /* If we have have read our buffer, wait for our write-partner*/
852 input_facility->facility_state = IOSTATE_WAITING;
853 // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish?
854 }
855 }
856 else
857 { /* operation still pending/queued or failed? */
858 int err = GetLastError ();
859 if (ERROR_IO_INCOMPLETE != err && ERROR_IO_PENDING != err)
860 { /* error occurred, let the rest of the elements finish */
861 input_facility->path_open = FALSE;
862 input_facility->facility_state = IOSTATE_FAILED;
863 if (IOSTATE_WAITING == output_facility->facility_state)
864 output_facility->path_open = FALSE;
865 fprintf (stderr, "FATAL: Read from handle failed, allowing write to finish!\n");
866 }
867 }
868 }
869 return TRUE;
870 default:
871 return TRUE;
804 } 872 }
805 return TRUE;
806 default:
807 return TRUE;
808 }
809} 873}
810 874
811/** 875/**
@@ -824,7 +888,7 @@ attempt_write (struct io_facility * output_facility,
824 if (IOSTATE_READY == output_facility->facility_state 888 if (IOSTATE_READY == output_facility->facility_state
825 && output_facility->buffer_size > 0) 889 && output_facility->buffer_size > 0)
826 { 890 {
827 if (!ResetEvent (output_facility->overlapped.hEvent)) 891 if ( ! ResetEvent (output_facility->overlapped.hEvent))
828 { 892 {
829 return FALSE; 893 return FALSE;
830 } 894 }
@@ -841,7 +905,7 @@ attempt_write (struct io_facility * output_facility,
841 {/* async event processed immediately*/ 905 {/* async event processed immediately*/
842 906
843 /* reset event manually*/ 907 /* reset event manually*/
844 if (!SetEvent (output_facility->overlapped.hEvent)) 908 if ( ! SetEvent (output_facility->overlapped.hEvent))
845 return FALSE; 909 return FALSE;
846 910
847 /* we are now waiting for our buffer to be filled*/ 911 /* we are now waiting for our buffer to be filled*/
@@ -866,7 +930,7 @@ attempt_write (struct io_facility * output_facility,
866 { /* error occurred, close this path */ 930 { /* error occurred, close this path */
867 output_facility->path_open = FALSE; 931 output_facility->path_open = FALSE;
868 output_facility->facility_state = IOSTATE_FAILED; 932 output_facility->facility_state = IOSTATE_FAILED;
869 fprintf (stderr, "Fatal: Write to handle failed, exiting!\n"); 933 fprintf (stderr, "FATAL: Write to handle failed, exiting!\n");
870 } 934 }
871 } 935 }
872 936
@@ -881,7 +945,7 @@ attempt_write (struct io_facility * output_facility,
881 if (output_facility->status && 945 if (output_facility->status &&
882 output_facility->buffer_size_written == output_facility->buffer_size) 946 output_facility->buffer_size_written == output_facility->buffer_size)
883 {/* successful return for a queued operation */ 947 {/* successful return for a queued operation */
884 if (!ResetEvent (output_facility->overlapped.hEvent)) 948 if ( ! ResetEvent (output_facility->overlapped.hEvent))
885 return FALSE; 949 return FALSE;
886 950
887 /* we are now waiting for our buffer to be filled*/ 951 /* we are now waiting for our buffer to be filled*/
@@ -902,7 +966,7 @@ attempt_write (struct io_facility * output_facility,
902 { /* error occurred, close this path */ 966 { /* error occurred, close this path */
903 output_facility->path_open = FALSE; 967 output_facility->path_open = FALSE;
904 output_facility->facility_state = IOSTATE_FAILED; 968 output_facility->facility_state = IOSTATE_FAILED;
905 fprintf (stderr, "Fatal: Write to handle failed, exiting!\n"); 969 fprintf (stderr, "FATAL: Write to handle failed, exiting!\n");
906 } 970 }
907 } 971 }
908 } 972 }
@@ -963,11 +1027,11 @@ run (HANDLE tap_handle)
963 * DHCP and such are all features we will never use in gnunet afaik. 1027 * DHCP and such are all features we will never use in gnunet afaik.
964 * But for openvpn those are essential. 1028 * But for openvpn those are essential.
965 */ 1029 */
966 if (!tun_up (tap_handle)) 1030 if ( ! tun_up (tap_handle))
967 return; 1031 return;
968 1032
969 /* Initialize our overlapped IO structures*/ 1033 /* Initialize our overlapped IO structures*/
970 if (!(initialize_io_facility (&tap_read, TRUE, FALSE) 1034 if ( ! (initialize_io_facility (&tap_read, TRUE, FALSE)
971 && initialize_io_facility (&tap_write, FALSE, TRUE) 1035 && initialize_io_facility (&tap_write, FALSE, TRUE)
972 && initialize_io_facility (&std_in, TRUE, FALSE) 1036 && initialize_io_facility (&std_in, TRUE, FALSE)
973 && initialize_io_facility (&std_out, FALSE, TRUE))) 1037 && initialize_io_facility (&std_out, FALSE, TRUE)))
@@ -985,7 +1049,9 @@ run (HANDLE tap_handle)
985 if (FILE_TYPE_PIPE != GetFileType (parent_std_in_handle) || 1049 if (FILE_TYPE_PIPE != GetFileType (parent_std_in_handle) ||
986 FILE_TYPE_PIPE != GetFileType (parent_std_out_handle)) 1050 FILE_TYPE_PIPE != GetFileType (parent_std_out_handle))
987 { 1051 {
988 fprintf (stderr, "Fatal: stdin/stdout must be named pipes!\n"); 1052 fprintf (stderr, "ERROR: stdin/stdout must be named pipes!\n");
1053 printf("\nPress Enter to continue...");
1054 getchar();
989 goto teardown; 1055 goto teardown;
990 } 1056 }
991 1057
@@ -996,7 +1062,7 @@ run (HANDLE tap_handle)
996 1062
997 if (INVALID_HANDLE_VALUE == std_in.handle) 1063 if (INVALID_HANDLE_VALUE == std_in.handle)
998 { 1064 {
999 fprintf (stderr, "Fatal: Could not reopen stdin for in overlapped mode, has to be a named pipe!\n"); 1065 fprintf (stderr, "FATAL: Could not reopen stdin for in overlapped mode, has to be a named pipe!\n");
1000 goto teardown; 1066 goto teardown;
1001 } 1067 }
1002 1068
@@ -1007,7 +1073,7 @@ run (HANDLE tap_handle)
1007 1073
1008 if (INVALID_HANDLE_VALUE == std_out.handle) 1074 if (INVALID_HANDLE_VALUE == std_out.handle)
1009 { 1075 {
1010 fprintf (stderr, "Fatal: Could not reopen stdout for in overlapped mode, has to be a named pipe!\n"); 1076 fprintf (stderr, "FATAL: Could not reopen stdout for in overlapped mode, has to be a named pipe!\n");
1011 goto teardown; 1077 goto teardown;
1012 } 1078 }
1013 1079
@@ -1058,10 +1124,12 @@ main (int argc, char **argv)
1058 char hwid[LINE_LEN]; 1124 char hwid[LINE_LEN];
1059 HANDLE handle; 1125 HANDLE handle;
1060 int global_ret = 0; 1126 int global_ret = 0;
1127 boolean have_ip4=FALSE;
1128 boolean have_ip6=FALSE;
1061 1129
1062 if (6 != argc) 1130 if (6 != argc)
1063 { 1131 {
1064 fprintf (stderr, "Fatal: must supply 5 arguments!\n"); 1132 fprintf (stderr, "FATAL: must supply 5 arguments!\n");
1065 return 1; 1133 return 1;
1066 } 1134 }
1067 1135
@@ -1079,7 +1147,7 @@ main (int argc, char **argv)
1079 1147
1080 if (INVALID_HANDLE_VALUE == (handle = init_tun ())) 1148 if (INVALID_HANDLE_VALUE == (handle = init_tun ()))
1081 { 1149 {
1082 fprintf (stderr, "Fatal: could not initialize virtual-interface %s with IPv6 %s/%s and IPv4 %s/%s\n", 1150 fprintf (stderr, "FATAL: could not initialize virtual-interface %s with IPv6 %s/%s and IPv4 %s/%s\n",
1083 hwid, 1151 hwid,
1084 argv[2], 1152 argv[2],
1085 argv[3], 1153 argv[3],
@@ -1096,13 +1164,15 @@ main (int argc, char **argv)
1096 1164
1097 if ((prefix_len < 1) || (prefix_len > 127)) 1165 if ((prefix_len < 1) || (prefix_len > 127))
1098 { 1166 {
1099 fprintf (stderr, "Fatal: prefix_len out of range\n"); 1167 fprintf (stderr, "FATAL: prefix_len out of range\n");
1100 global_ret = -1; 1168 global_ret = -1;
1101 goto cleanup; 1169 goto cleanup;
1102 } 1170 }
1103 1171
1104 if (0 != (global_ret = set_address6 (address, prefix_len))) 1172 if (0 != (global_ret = set_address6 (address, prefix_len)))
1105 goto cleanup; 1173 goto cleanup;
1174
1175 have_ip6 = TRUE;
1106 } 1176 }
1107 1177
1108 if (0 != strcmp (argv[4], "-")) 1178 if (0 != strcmp (argv[4], "-"))
@@ -1112,12 +1182,22 @@ main (int argc, char **argv)
1112 1182
1113 if (0 != (global_ret = set_address4 (address, mask))) 1183 if (0 != (global_ret = set_address4 (address, mask)))
1114 goto cleanup; 1184 goto cleanup;
1185
1186 have_ip4 = TRUE;
1115 } 1187 }
1116 1188
1117 run (handle); 1189 run (handle);
1118 global_ret = 0; 1190 global_ret = 0;
1119cleanup: 1191cleanup:
1120 1192
1193 if (have_ip4){
1194 const char *address = argv[4];
1195 remove_address4(address);
1196 }
1197 if (have_ip6){
1198 const char *address = argv[2];
1199 remove_address6(address);
1200 }
1121 remove_interface (); 1201 remove_interface ();
1122 return global_ret; 1202 return global_ret;
1123} 1203}