diff options
Diffstat (limited to 'src/vpn/gnunet-helper-vpn-windows.c')
-rw-r--r-- | src/vpn/gnunet-helper-vpn-windows.c | 382 |
1 files changed, 297 insertions, 85 deletions
diff --git a/src/vpn/gnunet-helper-vpn-windows.c b/src/vpn/gnunet-helper-vpn-windows.c index 05a0aeeff..619eb4226 100644 --- a/src/vpn/gnunet-helper-vpn-windows.c +++ b/src/vpn/gnunet-helper-vpn-windows.c | |||
@@ -71,12 +71,7 @@ | |||
71 | * Hardware ID used in the inf-file. | 71 | * Hardware ID used in the inf-file. |
72 | * This might change over time, as openvpn advances their driver | 72 | * This might change over time, as openvpn advances their driver |
73 | */ | 73 | */ |
74 | #define HARDWARE_ID "TAP0901" | 74 | #define HARDWARE_ID "tap0901" |
75 | |||
76 | /** | ||
77 | * Component ID if our driver | ||
78 | */ | ||
79 | #define TAP_WIN_COMPONENT_ID "tap0901" | ||
80 | 75 | ||
81 | /** | 76 | /** |
82 | * Minimum major-id of the driver version we can work with | 77 | * Minimum major-id of the driver version we can work with |
@@ -142,31 +137,66 @@ static char device_guid[256]; | |||
142 | */ | 137 | */ |
143 | struct io_facility | 138 | struct io_facility |
144 | { | 139 | { |
145 | HANDLE handle; | 140 | /** |
146 | 141 | * The mode the state machine associated with this object is in. IOSTATE_* | |
147 | BOOL path_open; // BOOL is winbool, NOT boolean! | 142 | */ |
148 | int facility_state; | 143 | int facility_state; |
149 | BOOL status; | ||
150 | 144 | ||
145 | /** | ||
146 | * If the path is open or blocked in general (used for quickly checking) | ||
147 | */ | ||
148 | BOOL path_open; // BOOL is winbool (int), NOT boolean (unsigned char)! | ||
149 | |||
150 | /** | ||
151 | * Windows Object-Handle (used for accessing TAP and STDIN/STDOUT) | ||
152 | */ | ||
153 | HANDLE handle; | ||
154 | |||
155 | /** | ||
156 | * Overlaped IO structure used for asynchronous IO in windows. | ||
157 | */ | ||
151 | OVERLAPPED overlapped; | 158 | OVERLAPPED overlapped; |
159 | |||
160 | /** | ||
161 | * Buffer for reading things to and writing from... | ||
162 | */ | ||
163 | unsigned char buffer[MAX_SIZE]; | ||
164 | |||
165 | /** | ||
166 | * How much of this buffer was used when reading or how much data can be written | ||
167 | */ | ||
152 | DWORD buffer_size; | 168 | DWORD buffer_size; |
169 | |||
170 | /** | ||
171 | * Amount of data written, is compared to buffer_size. | ||
172 | */ | ||
153 | DWORD buffer_size_written; | 173 | DWORD buffer_size_written; |
154 | unsigned char buffer[MAX_SIZE]; | ||
155 | }; | 174 | }; |
156 | 175 | ||
157 | /** | 176 | /** |
158 | * Operlapped IO states for facility objects | 177 | * Operlapped IO states for facility objects |
178 | * overlapped I/O has failed, stop processing | ||
179 | */ | ||
180 | #define IOSTATE_FAILED -1 | ||
181 | /** | ||
182 | * overlapped I/O is ready for work | ||
159 | */ | 183 | */ |
160 | #define IOSTATE_FAILED -1 /* overlapped I/O has failed, stop processing */ | 184 | #define IOSTATE_READY 0 |
161 | #define IOSTATE_READY 0 /* overlapped I/O is ready for work */ | 185 | /** |
162 | #define IOSTATE_QUEUED 1 /* overlapped I/O has been queued */ | 186 | * overlapped I/O has been queued |
163 | #define IOSTATE_WAITING 3 /* overlapped I/O has finished, but is waiting for it's write-partner */ | 187 | */ |
188 | #define IOSTATE_QUEUED 1 | ||
189 | /** | ||
190 | * overlapped I/O has finished, but is waiting for it's write-partner | ||
191 | */ | ||
192 | #define IOSTATE_WAITING 3 | ||
164 | 193 | ||
165 | /** | 194 | /** |
166 | * ReOpenFile is only available as of XP SP2 and 2003 SP1 | 195 | * ReOpenFile is only available as of XP SP2 and 2003 SP1 |
167 | */ | 196 | */ |
168 | WINBASEAPI HANDLE WINAPI ReOpenFile (HANDLE, DWORD, DWORD, DWORD); | 197 | WINBASEAPI HANDLE WINAPI ReOpenFile (HANDLE, DWORD, DWORD, DWORD); |
169 | 198 | ||
199 | |||
170 | /** | 200 | /** |
171 | * Wrapper for executing a shellcommand in windows. | 201 | * Wrapper for executing a shellcommand in windows. |
172 | * | 202 | * |
@@ -194,6 +224,7 @@ execute_shellcommand (const char *command) | |||
194 | return _pclose (pipe); | 224 | return _pclose (pipe); |
195 | } | 225 | } |
196 | 226 | ||
227 | |||
197 | /** | 228 | /** |
198 | * @brief Sets the IPv6-Address given in address on the interface dev | 229 | * @brief Sets the IPv6-Address given in address on the interface dev |
199 | * | 230 | * |
@@ -236,6 +267,7 @@ set_address6 (const char *address, unsigned long prefix_len) | |||
236 | return ret; | 267 | return ret; |
237 | } | 268 | } |
238 | 269 | ||
270 | |||
239 | /** | 271 | /** |
240 | * @brief Removes the IPv6-Address given in address from the interface dev | 272 | * @brief Removes the IPv6-Address given in address from the interface dev |
241 | * | 273 | * |
@@ -248,7 +280,7 @@ remove_address6 (const char *address) | |||
248 | { | 280 | { |
249 | char command[LINE_LEN]; | 281 | char command[LINE_LEN]; |
250 | int ret = EINVAL; | 282 | int ret = EINVAL; |
251 | 283 | ||
252 | // sanity checking was already done in set_address6 | 284 | // sanity checking was already done in set_address6 |
253 | /* | 285 | /* |
254 | * prepare the command | 286 | * prepare the command |
@@ -312,6 +344,7 @@ set_address4 (const char *address, const char *mask) | |||
312 | return ret; | 344 | return ret; |
313 | } | 345 | } |
314 | 346 | ||
347 | |||
315 | /** | 348 | /** |
316 | * @brief Removes the IPv4-Address given in address from the interface dev | 349 | * @brief Removes the IPv4-Address given in address from the interface dev |
317 | * | 350 | * |
@@ -324,7 +357,7 @@ remove_address4 (const char *address) | |||
324 | { | 357 | { |
325 | char command[LINE_LEN]; | 358 | char command[LINE_LEN]; |
326 | int ret = EINVAL; | 359 | int ret = EINVAL; |
327 | 360 | ||
328 | // sanity checking was already done in set_address4 | 361 | // sanity checking was already done in set_address4 |
329 | 362 | ||
330 | /* | 363 | /* |
@@ -343,6 +376,7 @@ remove_address4 (const char *address) | |||
343 | fprintf (stderr, "FATAL: removing IPv4 address failed: %s\n", strerror (ret)); | 376 | fprintf (stderr, "FATAL: removing IPv4 address failed: %s\n", strerror (ret)); |
344 | } | 377 | } |
345 | 378 | ||
379 | |||
346 | /** | 380 | /** |
347 | * Setup a new virtual interface to use for tunneling. | 381 | * Setup a new virtual interface to use for tunneling. |
348 | * | 382 | * |
@@ -391,7 +425,7 @@ setup_interface () | |||
391 | /** | 425 | /** |
392 | * Bootstrap our device info using the drivers inf-file | 426 | * Bootstrap our device info using the drivers inf-file |
393 | */ | 427 | */ |
394 | if ( ! SetupDiGetINFClassA (inf_file_path, | 428 | if (!SetupDiGetINFClassA (inf_file_path, |
395 | &class_guid, | 429 | &class_guid, |
396 | class_name, sizeof (class_name) / sizeof (char), | 430 | class_name, sizeof (class_name) / sizeof (char), |
397 | NULL)) | 431 | NULL)) |
@@ -406,7 +440,7 @@ setup_interface () | |||
406 | return FALSE; | 440 | return FALSE; |
407 | 441 | ||
408 | DeviceNode.cbSize = sizeof (SP_DEVINFO_DATA); | 442 | DeviceNode.cbSize = sizeof (SP_DEVINFO_DATA); |
409 | if ( ! SetupDiCreateDeviceInfoA (DeviceInfo, | 443 | if (!SetupDiCreateDeviceInfoA (DeviceInfo, |
410 | class_name, | 444 | class_name, |
411 | &class_guid, | 445 | &class_guid, |
412 | NULL, | 446 | NULL, |
@@ -416,7 +450,7 @@ setup_interface () | |||
416 | return FALSE; | 450 | return FALSE; |
417 | 451 | ||
418 | /* Deploy all the information collected into the registry */ | 452 | /* Deploy all the information collected into the registry */ |
419 | if ( ! SetupDiSetDeviceRegistryPropertyA (DeviceInfo, | 453 | if (!SetupDiSetDeviceRegistryPropertyA (DeviceInfo, |
420 | &DeviceNode, | 454 | &DeviceNode, |
421 | SPDRP_HARDWAREID, | 455 | SPDRP_HARDWAREID, |
422 | (LPBYTE) hwidlist, | 456 | (LPBYTE) hwidlist, |
@@ -424,14 +458,14 @@ setup_interface () | |||
424 | return FALSE; | 458 | return FALSE; |
425 | 459 | ||
426 | /* Install our new class(=device) into the system */ | 460 | /* Install our new class(=device) into the system */ |
427 | if ( ! SetupDiCallClassInstaller (DIF_REGISTERDEVICE, | 461 | if (!SetupDiCallClassInstaller (DIF_REGISTERDEVICE, |
428 | DeviceInfo, | 462 | DeviceInfo, |
429 | &DeviceNode)) | 463 | &DeviceNode)) |
430 | return FALSE; | 464 | return FALSE; |
431 | 465 | ||
432 | /* This system call tends to take a while (several seconds!) on | 466 | /* This system call tends to take a while (several seconds!) on |
433 | "modern" Windoze systems */ | 467 | "modern" Windoze systems */ |
434 | if ( ! UpdateDriverForPlugAndPlayDevicesA (NULL, | 468 | if (!UpdateDriverForPlugAndPlayDevicesA (NULL, |
435 | secondary_hwid, | 469 | secondary_hwid, |
436 | inf_file_path, | 470 | inf_file_path, |
437 | INSTALLFLAG_FORCE | INSTALLFLAG_NONINTERACTIVE, | 471 | INSTALLFLAG_FORCE | INSTALLFLAG_NONINTERACTIVE, |
@@ -441,6 +475,7 @@ setup_interface () | |||
441 | return TRUE; | 475 | return TRUE; |
442 | } | 476 | } |
443 | 477 | ||
478 | |||
444 | /** | 479 | /** |
445 | * Remove our new virtual interface to use for tunneling. | 480 | * Remove our new virtual interface to use for tunneling. |
446 | * This function must be called AFTER setup_interface! | 481 | * This function must be called AFTER setup_interface! |
@@ -463,7 +498,7 @@ remove_interface () | |||
463 | * 1. Prepare our existing device information set, and place the | 498 | * 1. Prepare our existing device information set, and place the |
464 | * uninstall related information into the structure | 499 | * uninstall related information into the structure |
465 | */ | 500 | */ |
466 | if ( ! SetupDiSetClassInstallParamsA (DeviceInfo, | 501 | if (!SetupDiSetClassInstallParamsA (DeviceInfo, |
467 | (PSP_DEVINFO_DATA) & DeviceNode, | 502 | (PSP_DEVINFO_DATA) & DeviceNode, |
468 | &remove.ClassInstallHeader, | 503 | &remove.ClassInstallHeader, |
469 | sizeof (remove))) | 504 | sizeof (remove))) |
@@ -471,7 +506,7 @@ remove_interface () | |||
471 | /* | 506 | /* |
472 | * 2. Uninstall the virtual interface using the class installer | 507 | * 2. Uninstall the virtual interface using the class installer |
473 | */ | 508 | */ |
474 | if ( ! SetupDiCallClassInstaller (DIF_REMOVE, | 509 | if (!SetupDiCallClassInstaller (DIF_REMOVE, |
475 | DeviceInfo, | 510 | DeviceInfo, |
476 | (PSP_DEVINFO_DATA) & DeviceNode)) | 511 | (PSP_DEVINFO_DATA) & DeviceNode)) |
477 | return FALSE; | 512 | return FALSE; |
@@ -481,6 +516,7 @@ remove_interface () | |||
481 | return TRUE; | 516 | return TRUE; |
482 | } | 517 | } |
483 | 518 | ||
519 | |||
484 | /** | 520 | /** |
485 | * Do all the lookup necessary to retrieve the inteface's actual name | 521 | * Do all the lookup necessary to retrieve the inteface's actual name |
486 | * off the registry. | 522 | * off the registry. |
@@ -527,7 +563,7 @@ resolve_interface_name () | |||
527 | /* Of course there is a multitude of entries here, with arbitrary names, | 563 | /* Of course there is a multitude of entries here, with arbitrary names, |
528 | * thus we need to iterate through there. | 564 | * thus we need to iterate through there. |
529 | */ | 565 | */ |
530 | while ( ! retval) | 566 | while (!retval) |
531 | { | 567 | { |
532 | char instance_key[256]; | 568 | char instance_key[256]; |
533 | char query_key [256]; | 569 | char query_key [256]; |
@@ -622,6 +658,7 @@ cleanup: | |||
622 | return retval; | 658 | return retval; |
623 | } | 659 | } |
624 | 660 | ||
661 | |||
625 | static boolean | 662 | static boolean |
626 | check_tapw32_version (HANDLE handle) | 663 | check_tapw32_version (HANDLE handle) |
627 | { | 664 | { |
@@ -650,6 +687,7 @@ check_tapw32_version (HANDLE handle) | |||
650 | return TRUE; | 687 | return TRUE; |
651 | } | 688 | } |
652 | 689 | ||
690 | |||
653 | /** | 691 | /** |
654 | * Creates a tun-interface called dev; | 692 | * Creates a tun-interface called dev; |
655 | * | 693 | * |
@@ -661,13 +699,13 @@ init_tun () | |||
661 | char device_path[256]; | 699 | char device_path[256]; |
662 | HANDLE handle; | 700 | HANDLE handle; |
663 | 701 | ||
664 | if ( ! setup_interface ()) | 702 | if (!setup_interface ()) |
665 | { | 703 | { |
666 | errno = ENODEV; | 704 | errno = ENODEV; |
667 | return INVALID_HANDLE_VALUE; | 705 | return INVALID_HANDLE_VALUE; |
668 | } | 706 | } |
669 | 707 | ||
670 | if ( ! resolve_interface_name ()) | 708 | if (!resolve_interface_name ()) |
671 | { | 709 | { |
672 | errno = ENODEV; | 710 | errno = ENODEV; |
673 | return INVALID_HANDLE_VALUE; | 711 | return INVALID_HANDLE_VALUE; |
@@ -696,7 +734,7 @@ init_tun () | |||
696 | } | 734 | } |
697 | 735 | ||
698 | /* get driver version info */ | 736 | /* get driver version info */ |
699 | if ( ! check_tapw32_version (handle)) | 737 | if (!check_tapw32_version (handle)) |
700 | { | 738 | { |
701 | CloseHandle (handle); | 739 | CloseHandle (handle); |
702 | return INVALID_HANDLE_VALUE; | 740 | return INVALID_HANDLE_VALUE; |
@@ -707,6 +745,7 @@ init_tun () | |||
707 | return handle; | 745 | return handle; |
708 | } | 746 | } |
709 | 747 | ||
748 | |||
710 | /** | 749 | /** |
711 | * Brings a TAP device up and sets it to connected state. | 750 | * Brings a TAP device up and sets it to connected state. |
712 | * | 751 | * |
@@ -718,9 +757,9 @@ tun_up (HANDLE handle) | |||
718 | { | 757 | { |
719 | ULONG status = TRUE; | 758 | ULONG status = TRUE; |
720 | DWORD len; | 759 | DWORD len; |
721 | if ( ! DeviceIoControl (handle, TAP_WIN_IOCTL_SET_MEDIA_STATUS, | 760 | if (!DeviceIoControl (handle, TAP_WIN_IOCTL_SET_MEDIA_STATUS, |
722 | &status, sizeof (status), | 761 | &status, sizeof (status), |
723 | &status, sizeof (status), &len, NULL)) | 762 | &status, sizeof (status), &len, NULL)) |
724 | { | 763 | { |
725 | fprintf (stderr, "FATAL: TAP driver ignored request to UP interface (DeviceIoControl call)!\n"); | 764 | fprintf (stderr, "FATAL: TAP driver ignored request to UP interface (DeviceIoControl call)!\n"); |
726 | return FALSE; | 765 | return FALSE; |
@@ -733,6 +772,7 @@ tun_up (HANDLE handle) | |||
733 | 772 | ||
734 | } | 773 | } |
735 | 774 | ||
775 | |||
736 | /** | 776 | /** |
737 | * Attempts to read off an input facility (tap or named pipe) in overlapped mode. | 777 | * Attempts to read off an input facility (tap or named pipe) in overlapped mode. |
738 | * | 778 | * |
@@ -759,29 +799,30 @@ tun_up (HANDLE handle) | |||
759 | * @return false if an event reset was impossible (OS error), else true | 799 | * @return false if an event reset was impossible (OS error), else true |
760 | */ | 800 | */ |
761 | static boolean | 801 | static boolean |
762 | attempt_read (struct io_facility * input_facility, | 802 | attempt_read_tap (struct io_facility * input_facility, |
763 | struct io_facility * output_facility) | 803 | struct io_facility * output_facility) |
764 | { | 804 | { |
765 | switch (input_facility->facility_state) | 805 | switch (input_facility->facility_state) |
766 | { | 806 | { |
767 | case IOSTATE_READY: | 807 | case IOSTATE_READY: |
768 | { | 808 | { |
769 | if ( ! ResetEvent (input_facility->overlapped.hEvent)) | 809 | BOOL status; // BOOL is winbool, NOT boolean! |
810 | if (!ResetEvent (input_facility->overlapped.hEvent)) | ||
770 | { | 811 | { |
771 | return FALSE; | 812 | return FALSE; |
772 | } | 813 | } |
773 | input_facility->status = ReadFile (input_facility->handle, | 814 | status = ReadFile (input_facility->handle, |
774 | input_facility->buffer, | 815 | input_facility->buffer + sizeof (struct GNUNET_MessageHeader), |
775 | MAX_SIZE, | 816 | sizeof (input_facility->buffer) - sizeof (struct GNUNET_MessageHeader), |
776 | &input_facility->buffer_size, | 817 | &input_facility->buffer_size, |
777 | &input_facility->overlapped); | 818 | &input_facility->overlapped); |
778 | 819 | ||
779 | /* Check how the task is handled */ | 820 | /* Check how the task is handled */ |
780 | if (input_facility->status) | 821 | if (status) |
781 | {/* async event processed immediately*/ | 822 | {/* async event processed immediately*/ |
782 | 823 | ||
783 | /* reset event manually*/ | 824 | /* reset event manually*/ |
784 | if ( ! SetEvent (input_facility->overlapped.hEvent)) | 825 | if (!SetEvent (input_facility->overlapped.hEvent)) |
785 | return FALSE; | 826 | return FALSE; |
786 | 827 | ||
787 | /* we successfully read something from the TAP and now need to | 828 | /* we successfully read something from the TAP and now need to |
@@ -792,7 +833,161 @@ attempt_read (struct io_facility * input_facility, | |||
792 | { /* hand over this buffers content */ | 833 | { /* hand over this buffers content */ |
793 | memcpy (output_facility->buffer, | 834 | memcpy (output_facility->buffer, |
794 | input_facility->buffer, | 835 | input_facility->buffer, |
795 | MAX_SIZE); | 836 | sizeof (input_facility->buffer)); |
837 | output_facility->buffer_size = input_facility->buffer_size; | ||
838 | output_facility->facility_state = IOSTATE_READY; | ||
839 | } | ||
840 | else if (0 < input_facility->buffer_size) | ||
841 | { /* If we have have read our buffer, wait for our write-partner*/ | ||
842 | input_facility->facility_state = IOSTATE_WAITING; | ||
843 | // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish? | ||
844 | } | ||
845 | } | ||
846 | else /* operation was either queued or failed*/ | ||
847 | { | ||
848 | int err = GetLastError (); | ||
849 | if (ERROR_IO_PENDING == err) | ||
850 | { /* operation queued */ | ||
851 | input_facility->facility_state = IOSTATE_QUEUED; | ||
852 | } | ||
853 | else | ||
854 | { /* error occurred, let the rest of the elements finish */ | ||
855 | input_facility->path_open = FALSE; | ||
856 | input_facility->facility_state = IOSTATE_FAILED; | ||
857 | if (IOSTATE_WAITING == output_facility->facility_state) | ||
858 | output_facility->path_open = FALSE; | ||
859 | |||
860 | fprintf (stderr, "FATAL: Read from handle failed, allowing write to finish!\n"); | ||
861 | } | ||
862 | } | ||
863 | } | ||
864 | return TRUE; | ||
865 | // We are queued and should check if the read has finished | ||
866 | case IOSTATE_QUEUED: | ||
867 | { | ||
868 | BOOL status; // BOOL is winbool, NOT boolean! | ||
869 | |||
870 | // there was an operation going on already, check if that has completed now. | ||
871 | status = GetOverlappedResult (input_facility->handle, | ||
872 | &input_facility->overlapped, | ||
873 | &input_facility->buffer_size, | ||
874 | FALSE); | ||
875 | if (status) | ||
876 | {/* successful return for a queued operation */ | ||
877 | if (!ResetEvent (input_facility->overlapped.hEvent)) | ||
878 | return FALSE; | ||
879 | |||
880 | /* we successfully read something from the TAP and now need to | ||
881 | * send it our via STDOUT. Is that possible at the moment? */ | ||
882 | if ((IOSTATE_READY == output_facility->facility_state || | ||
883 | IOSTATE_WAITING == output_facility->facility_state) | ||
884 | && 0 < input_facility->buffer_size) | ||
885 | { /* hand over this buffers content */ | ||
886 | memcpy (output_facility->buffer, | ||
887 | input_facility->buffer, | ||
888 | input_facility->buffer_size); | ||
889 | output_facility->buffer_size = input_facility->buffer_size; | ||
890 | output_facility->facility_state = IOSTATE_READY; | ||
891 | input_facility->facility_state = IOSTATE_READY; | ||
892 | } | ||
893 | else if (0 < input_facility->buffer_size) | ||
894 | { /* If we have have read our buffer, wait for our write-partner*/ | ||
895 | input_facility->facility_state = IOSTATE_WAITING; | ||
896 | // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish? | ||
897 | } | ||
898 | } | ||
899 | else | ||
900 | { /* operation still pending/queued or failed? */ | ||
901 | int err = GetLastError (); | ||
902 | if (ERROR_IO_INCOMPLETE != err && ERROR_IO_PENDING != err) | ||
903 | { /* error occurred, let the rest of the elements finish */ | ||
904 | input_facility->path_open = FALSE; | ||
905 | input_facility->facility_state = IOSTATE_FAILED; | ||
906 | if (IOSTATE_WAITING == output_facility->facility_state) | ||
907 | output_facility->path_open = FALSE; | ||
908 | fprintf (stderr, "FATAL: Read from handle failed, allowing write to finish!\n"); | ||
909 | } | ||
910 | } | ||
911 | } | ||
912 | return TRUE; | ||
913 | default: | ||
914 | return TRUE; | ||
915 | } | ||
916 | } | ||
917 | |||
918 | /** | ||
919 | * Attempts to read off an input facility (tap or named pipe) in overlapped mode. | ||
920 | * | ||
921 | * 1. | ||
922 | * If the input facility is in IOSTATE_READY, it will issue a new read operation to the | ||
923 | * input handle. Then it goes into IOSTATE_QUEUED state. | ||
924 | * In case the read succeeded instantly the input facility enters 3. | ||
925 | * | ||
926 | * 2. | ||
927 | * If the input facility is in IOSTATE_QUEUED state, it will check if the queued read has finished already. | ||
928 | * If it has finished, go to state 3. | ||
929 | * If it has failed, set IOSTATE_FAILED | ||
930 | * | ||
931 | * 3. | ||
932 | * If the facility is finished with ready | ||
933 | * The read-buffer is copied to the output buffer, except for the GNUNET_MessageHeader. | ||
934 | * The input facility enters state IOSTATE_READY | ||
935 | * The output facility enters state IOSTATE_READY | ||
936 | * If the output facility is in state IOSTATE_QUEUED, the input facility enters IOSTATE_WAITING | ||
937 | * | ||
938 | * IOSTATE_WAITING is reset by the output facility, once it has completed. | ||
939 | * | ||
940 | * @param input_facility input named pipe or file to work with. | ||
941 | * @param output_facility output pipe or file to hand over data to. | ||
942 | * @return false if an event reset was impossible (OS error), else true | ||
943 | */ | ||
944 | static boolean | ||
945 | attempt_read_stdin (struct io_facility * input_facility, | ||
946 | struct io_facility * output_facility) | ||
947 | { | ||
948 | switch (input_facility->facility_state) | ||
949 | { | ||
950 | case IOSTATE_READY: | ||
951 | { | ||
952 | BOOL status; // BOOL is winbool, NOT boolean! | ||
953 | if (!ResetEvent (input_facility->overlapped.hEvent)) | ||
954 | { | ||
955 | return FALSE; | ||
956 | } | ||
957 | status = ReadFile (input_facility->handle, | ||
958 | input_facility->buffer, | ||
959 | sizeof (input_facility->buffer), | ||
960 | &input_facility->buffer_size, | ||
961 | &input_facility->overlapped); | ||
962 | |||
963 | /* Check how the task is handled */ | ||
964 | if (status && (0 < input_facility->buffer_size)) | ||
965 | {/* async event processed immediately*/ | ||
966 | struct GNUNET_MessageHeader *hdr; | ||
967 | |||
968 | /* reset event manually*/ | ||
969 | if (!SetEvent (input_facility->overlapped.hEvent)) | ||
970 | return FALSE; | ||
971 | |||
972 | hdr = (struct GNUNET_MessageHeader *) input_facility->buffer; | ||
973 | if (ntohs (hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER || | ||
974 | ntohs (hdr->size) > sizeof (input_facility->buffer)) | ||
975 | { | ||
976 | fprintf (stderr, "WARNING: Protocol violation, got GNUnet Message type %h, size %h!\n", ntohs (hdr->type), ntohs (hdr->size)); | ||
977 | input_facility->facility_state = IOSTATE_READY; | ||
978 | return TRUE; | ||
979 | } | ||
980 | //if (ntohs (hdr->size) > input_facility->buffer_size ); | ||
981 | // TODO: add support for partial read | ||
982 | |||
983 | /* we successfully read something from the TAP and now need to | ||
984 | * send it our via STDOUT. Is that possible at the moment? */ | ||
985 | if (IOSTATE_READY == output_facility->facility_state || | ||
986 | IOSTATE_WAITING == output_facility->facility_state) | ||
987 | { /* hand over this buffers content */ | ||
988 | memcpy (output_facility->buffer, | ||
989 | input_facility->buffer, | ||
990 | sizeof (input_facility->buffer)); | ||
796 | output_facility->buffer_size = input_facility->buffer_size; | 991 | output_facility->buffer_size = input_facility->buffer_size; |
797 | output_facility->facility_state = IOSTATE_READY; | 992 | output_facility->facility_state = IOSTATE_READY; |
798 | } | 993 | } |
@@ -801,6 +996,15 @@ attempt_read (struct io_facility * input_facility, | |||
801 | input_facility->facility_state = IOSTATE_WAITING; | 996 | input_facility->facility_state = IOSTATE_WAITING; |
802 | // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish? | 997 | // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish? |
803 | } | 998 | } |
999 | |||
1000 | input_facility->facility_state = IOSTATE_READY; | ||
1001 | } | ||
1002 | else if (status && 0 >= input_facility->buffer_size) | ||
1003 | { | ||
1004 | if (!SetEvent (input_facility->overlapped.hEvent)) | ||
1005 | return FALSE; | ||
1006 | |||
1007 | input_facility->facility_state = IOSTATE_READY; | ||
804 | } | 1008 | } |
805 | else /* operation was either queued or failed*/ | 1009 | else /* operation was either queued or failed*/ |
806 | { | 1010 | { |
@@ -824,14 +1028,16 @@ attempt_read (struct io_facility * input_facility, | |||
824 | // We are queued and should check if the read has finished | 1028 | // We are queued and should check if the read has finished |
825 | case IOSTATE_QUEUED: | 1029 | case IOSTATE_QUEUED: |
826 | { | 1030 | { |
1031 | BOOL status; // BOOL is winbool, NOT boolean! | ||
1032 | |||
827 | // there was an operation going on already, check if that has completed now. | 1033 | // there was an operation going on already, check if that has completed now. |
828 | input_facility->status = GetOverlappedResult (input_facility->handle, | 1034 | status = GetOverlappedResult (input_facility->handle, |
829 | &input_facility->overlapped, | 1035 | &input_facility->overlapped, |
830 | &input_facility->buffer_size, | 1036 | &input_facility->buffer_size, |
831 | FALSE); | 1037 | FALSE); |
832 | if (input_facility->status) | 1038 | if (status) |
833 | {/* successful return for a queued operation */ | 1039 | {/* successful return for a queued operation */ |
834 | if ( ! ResetEvent (input_facility->overlapped.hEvent)) | 1040 | if (!ResetEvent (input_facility->overlapped.hEvent)) |
835 | return FALSE; | 1041 | return FALSE; |
836 | 1042 | ||
837 | /* we successfully read something from the TAP and now need to | 1043 | /* we successfully read something from the TAP and now need to |
@@ -842,7 +1048,7 @@ attempt_read (struct io_facility * input_facility, | |||
842 | { /* hand over this buffers content */ | 1048 | { /* hand over this buffers content */ |
843 | memcpy (output_facility->buffer, | 1049 | memcpy (output_facility->buffer, |
844 | input_facility->buffer, | 1050 | input_facility->buffer, |
845 | MAX_SIZE); | 1051 | input_facility->buffer_size); |
846 | output_facility->buffer_size = input_facility->buffer_size; | 1052 | output_facility->buffer_size = input_facility->buffer_size; |
847 | output_facility->facility_state = IOSTATE_READY; | 1053 | output_facility->facility_state = IOSTATE_READY; |
848 | input_facility->facility_state = IOSTATE_READY; | 1054 | input_facility->facility_state = IOSTATE_READY; |
@@ -872,6 +1078,7 @@ attempt_read (struct io_facility * input_facility, | |||
872 | } | 1078 | } |
873 | } | 1079 | } |
874 | 1080 | ||
1081 | |||
875 | /** | 1082 | /** |
876 | * Attempts to write to an output facility (tap or named pipe) in overlapped mode. | 1083 | * Attempts to write to an output facility (tap or named pipe) in overlapped mode. |
877 | * | 1084 | * |
@@ -888,24 +1095,26 @@ attempt_write (struct io_facility * output_facility, | |||
888 | if (IOSTATE_READY == output_facility->facility_state | 1095 | if (IOSTATE_READY == output_facility->facility_state |
889 | && output_facility->buffer_size > 0) | 1096 | && output_facility->buffer_size > 0) |
890 | { | 1097 | { |
891 | if ( ! ResetEvent (output_facility->overlapped.hEvent)) | 1098 | BOOL status; // BOOL is winbool, NOT boolean! |
1099 | |||
1100 | if (!ResetEvent (output_facility->overlapped.hEvent)) | ||
892 | { | 1101 | { |
893 | return FALSE; | 1102 | return FALSE; |
894 | } | 1103 | } |
895 | 1104 | ||
896 | output_facility->status = WriteFile (output_facility->handle, | 1105 | status = WriteFile (output_facility->handle, |
897 | output_facility->buffer, | 1106 | output_facility->buffer, |
898 | output_facility->buffer_size, | 1107 | output_facility->buffer_size, |
899 | &output_facility->buffer_size_written, | 1108 | &output_facility->buffer_size_written, |
900 | &output_facility->overlapped); | 1109 | &output_facility->overlapped); |
901 | 1110 | ||
902 | /* Check how the task is handled */ | 1111 | /* Check how the task is handled */ |
903 | if (output_facility->status && | 1112 | if (status && |
904 | output_facility->buffer_size_written == output_facility->buffer_size) | 1113 | output_facility->buffer_size_written == output_facility->buffer_size) |
905 | {/* async event processed immediately*/ | 1114 | {/* async event processed immediately*/ |
906 | 1115 | ||
907 | /* reset event manually*/ | 1116 | /* reset event manually*/ |
908 | if ( ! SetEvent (output_facility->overlapped.hEvent)) | 1117 | if (!SetEvent (output_facility->overlapped.hEvent)) |
909 | return FALSE; | 1118 | return FALSE; |
910 | 1119 | ||
911 | /* we are now waiting for our buffer to be filled*/ | 1120 | /* we are now waiting for our buffer to be filled*/ |
@@ -937,15 +1146,16 @@ attempt_write (struct io_facility * output_facility, | |||
937 | } | 1146 | } |
938 | else if (IOSTATE_QUEUED == output_facility->facility_state) | 1147 | else if (IOSTATE_QUEUED == output_facility->facility_state) |
939 | { | 1148 | { |
1149 | BOOL status; // BOOL is winbool, NOT boolean! | ||
940 | // there was an operation going on already, check if that has completed now. | 1150 | // there was an operation going on already, check if that has completed now. |
941 | output_facility->status = GetOverlappedResult (output_facility->handle, | 1151 | status = GetOverlappedResult (output_facility->handle, |
942 | &output_facility->overlapped, | 1152 | &output_facility->overlapped, |
943 | &output_facility->buffer_size_written, | 1153 | &output_facility->buffer_size_written, |
944 | FALSE); | 1154 | FALSE); |
945 | if (output_facility->status && | 1155 | if (status && |
946 | output_facility->buffer_size_written == output_facility->buffer_size) | 1156 | output_facility->buffer_size_written == output_facility->buffer_size) |
947 | {/* successful return for a queued operation */ | 1157 | {/* successful return for a queued operation */ |
948 | if ( ! ResetEvent (output_facility->overlapped.hEvent)) | 1158 | if (!ResetEvent (output_facility->overlapped.hEvent)) |
949 | return FALSE; | 1159 | return FALSE; |
950 | 1160 | ||
951 | /* we are now waiting for our buffer to be filled*/ | 1161 | /* we are now waiting for our buffer to be filled*/ |
@@ -974,6 +1184,7 @@ attempt_write (struct io_facility * output_facility, | |||
974 | return TRUE; | 1184 | return TRUE; |
975 | } | 1185 | } |
976 | 1186 | ||
1187 | |||
977 | /** | 1188 | /** |
978 | * Initialize a overlapped structure | 1189 | * Initialize a overlapped structure |
979 | * | 1190 | * |
@@ -984,14 +1195,13 @@ attempt_write (struct io_facility * output_facility, | |||
984 | */ | 1195 | */ |
985 | static boolean | 1196 | static boolean |
986 | initialize_io_facility (struct io_facility * elem, | 1197 | initialize_io_facility (struct io_facility * elem, |
987 | BOOL initial_state, | 1198 | int initial_state, |
988 | BOOL signaled) | 1199 | BOOL signaled) |
989 | { | 1200 | { |
990 | 1201 | ||
991 | elem->path_open = TRUE; | 1202 | elem->path_open = TRUE; |
992 | elem->status = initial_state; | ||
993 | elem->handle = INVALID_HANDLE_VALUE; | 1203 | elem->handle = INVALID_HANDLE_VALUE; |
994 | elem->facility_state = 0; | 1204 | elem->facility_state = initial_state; |
995 | elem->buffer_size = 0; | 1205 | elem->buffer_size = 0; |
996 | elem->overlapped.hEvent = CreateEvent (NULL, TRUE, signaled, NULL); | 1206 | elem->overlapped.hEvent = CreateEvent (NULL, TRUE, signaled, NULL); |
997 | if (NULL == elem->overlapped.hEvent) | 1207 | if (NULL == elem->overlapped.hEvent) |
@@ -1000,6 +1210,7 @@ initialize_io_facility (struct io_facility * elem, | |||
1000 | return TRUE; | 1210 | return TRUE; |
1001 | } | 1211 | } |
1002 | 1212 | ||
1213 | |||
1003 | /** | 1214 | /** |
1004 | * Start forwarding to and from the tunnel. | 1215 | * Start forwarding to and from the tunnel. |
1005 | * | 1216 | * |
@@ -1027,14 +1238,14 @@ run (HANDLE tap_handle) | |||
1027 | * DHCP and such are all features we will never use in gnunet afaik. | 1238 | * DHCP and such are all features we will never use in gnunet afaik. |
1028 | * But for openvpn those are essential. | 1239 | * But for openvpn those are essential. |
1029 | */ | 1240 | */ |
1030 | if ( ! tun_up (tap_handle)) | 1241 | if (!tun_up (tap_handle)) |
1031 | return; | 1242 | return; |
1032 | 1243 | ||
1033 | /* Initialize our overlapped IO structures*/ | 1244 | /* Initialize our overlapped IO structures*/ |
1034 | if ( ! (initialize_io_facility (&tap_read, TRUE, FALSE) | 1245 | if (!(initialize_io_facility (&tap_read, IOSTATE_READY, FALSE) |
1035 | && initialize_io_facility (&tap_write, FALSE, TRUE) | 1246 | && initialize_io_facility (&tap_write, IOSTATE_WAITING, TRUE) |
1036 | && initialize_io_facility (&std_in, TRUE, FALSE) | 1247 | && initialize_io_facility (&std_in, IOSTATE_READY, FALSE) |
1037 | && initialize_io_facility (&std_out, FALSE, TRUE))) | 1248 | && initialize_io_facility (&std_out, IOSTATE_WAITING, TRUE))) |
1038 | goto teardown_final; | 1249 | goto teardown_final; |
1039 | 1250 | ||
1040 | /* Handles for STDIN and STDOUT */ | 1251 | /* Handles for STDIN and STDOUT */ |
@@ -1050,8 +1261,6 @@ run (HANDLE tap_handle) | |||
1050 | FILE_TYPE_PIPE != GetFileType (parent_std_out_handle)) | 1261 | FILE_TYPE_PIPE != GetFileType (parent_std_out_handle)) |
1051 | { | 1262 | { |
1052 | fprintf (stderr, "ERROR: stdin/stdout must be named pipes!\n"); | 1263 | fprintf (stderr, "ERROR: stdin/stdout must be named pipes!\n"); |
1053 | printf("\nPress Enter to continue..."); | ||
1054 | getchar(); | ||
1055 | goto teardown; | 1264 | goto teardown; |
1056 | } | 1265 | } |
1057 | 1266 | ||
@@ -1080,19 +1289,19 @@ run (HANDLE tap_handle) | |||
1080 | while (std_out.path_open || tap_write.path_open) | 1289 | while (std_out.path_open || tap_write.path_open) |
1081 | { | 1290 | { |
1082 | /* perform READ from stdin if possible */ | 1291 | /* perform READ from stdin if possible */ |
1083 | if (std_in.path_open && tap_write.path_open && !attempt_read (&std_in, &tap_write)) | 1292 | if (std_in.path_open && tap_write.path_open && (!attempt_read_stdin (&std_in, &tap_write))) |
1084 | break; | 1293 | break; |
1085 | 1294 | ||
1086 | /* perform READ from tap if possible */ | 1295 | /* perform READ from tap if possible */ |
1087 | if (tap_read.path_open && std_out.path_open && !attempt_read (&tap_read, &std_out)) | 1296 | if (tap_read.path_open && std_out.path_open && (!attempt_read_tap (&tap_read, &std_out))) |
1088 | break; | 1297 | break; |
1089 | 1298 | ||
1090 | /* perform WRITE to tap if possible */ | 1299 | /* perform WRITE to tap if possible */ |
1091 | if (tap_write.path_open && !attempt_write (&tap_write, &std_in)) | 1300 | if (tap_write.path_open && (!attempt_write (&tap_write, &std_in))) |
1092 | break; | 1301 | break; |
1093 | 1302 | ||
1094 | /* perform WRITE to STDOUT if possible */ | 1303 | /* perform WRITE to STDOUT if possible */ |
1095 | if (std_out.path_open && !attempt_write (&std_out, &tap_read)) | 1304 | if (std_out.path_open && (!attempt_write (&std_out, &tap_read))) |
1096 | break; | 1305 | break; |
1097 | } | 1306 | } |
1098 | 1307 | ||
@@ -1107,6 +1316,7 @@ teardown_final: | |||
1107 | CloseHandle (tap_handle); | 1316 | CloseHandle (tap_handle); |
1108 | } | 1317 | } |
1109 | 1318 | ||
1319 | |||
1110 | /** | 1320 | /** |
1111 | * Open VPN tunnel interface. | 1321 | * Open VPN tunnel interface. |
1112 | * | 1322 | * |
@@ -1124,8 +1334,8 @@ main (int argc, char **argv) | |||
1124 | char hwid[LINE_LEN]; | 1334 | char hwid[LINE_LEN]; |
1125 | HANDLE handle; | 1335 | HANDLE handle; |
1126 | int global_ret = 0; | 1336 | int global_ret = 0; |
1127 | boolean have_ip4=FALSE; | 1337 | boolean have_ip4 = FALSE; |
1128 | boolean have_ip6=FALSE; | 1338 | boolean have_ip6 = FALSE; |
1129 | 1339 | ||
1130 | if (6 != argc) | 1340 | if (6 != argc) |
1131 | { | 1341 | { |
@@ -1171,7 +1381,7 @@ main (int argc, char **argv) | |||
1171 | 1381 | ||
1172 | if (0 != (global_ret = set_address6 (address, prefix_len))) | 1382 | if (0 != (global_ret = set_address6 (address, prefix_len))) |
1173 | goto cleanup; | 1383 | goto cleanup; |
1174 | 1384 | ||
1175 | have_ip6 = TRUE; | 1385 | have_ip6 = TRUE; |
1176 | } | 1386 | } |
1177 | 1387 | ||
@@ -1182,7 +1392,7 @@ main (int argc, char **argv) | |||
1182 | 1392 | ||
1183 | if (0 != (global_ret = set_address4 (address, mask))) | 1393 | if (0 != (global_ret = set_address4 (address, mask))) |
1184 | goto cleanup; | 1394 | goto cleanup; |
1185 | 1395 | ||
1186 | have_ip4 = TRUE; | 1396 | have_ip4 = TRUE; |
1187 | } | 1397 | } |
1188 | 1398 | ||
@@ -1190,13 +1400,15 @@ main (int argc, char **argv) | |||
1190 | global_ret = 0; | 1400 | global_ret = 0; |
1191 | cleanup: | 1401 | cleanup: |
1192 | 1402 | ||
1193 | if (have_ip4){ | 1403 | if (have_ip4) |
1404 | { | ||
1194 | const char *address = argv[4]; | 1405 | const char *address = argv[4]; |
1195 | remove_address4(address); | 1406 | remove_address4 (address); |
1196 | } | 1407 | } |
1197 | if (have_ip6){ | 1408 | if (have_ip6) |
1409 | { | ||
1198 | const char *address = argv[2]; | 1410 | const char *address = argv[2]; |
1199 | remove_address6(address); | 1411 | remove_address6 (address); |
1200 | } | 1412 | } |
1201 | remove_interface (); | 1413 | remove_interface (); |
1202 | return global_ret; | 1414 | return global_ret; |