* Should we print (interesting|debug) messages that can happen during
* normal operation?
*/
-#define DEBUG GNUNET_NO
+//#define DEBUG GNUNET_YES
/**
* Maximum size of a GNUnet message (GNUNET_SERVER_MAX_MESSAGE_SIZE)
* Hardware ID used in the inf-file.
* This might change over time, as openvpn advances their driver
*/
-#define HARDWARE_ID "TAP0901"
-
-/**
- * Component ID if our driver
- */
-#define TAP_WIN_COMPONENT_ID "tap0901"
+#define HARDWARE_ID "tap0901"
/**
* Minimum major-id of the driver version we can work with
*/
static char device_guid[256];
+
+/**
+ * Possible states of an IO facility.
+ */
+enum IO_State
+{
+
+ /**
+ * overlapped I/O is ready for work
+ */
+ IOSTATE_READY = 0,
+
+ /**
+ * overlapped I/O has been queued
+ */
+ IOSTATE_QUEUED,
+
+ /**
+ * overlapped I/O has finished, but is waiting for it's write-partner
+ */
+ IOSTATE_WAITING,
+
+ /**
+ * there is a full buffer waiting
+ */
+ IOSTATE_RESUME,
+
+ /**
+ * Operlapped IO states for facility objects
+ * overlapped I/O has failed, stop processing
+ */
+ IOSTATE_FAILED
+
+};
+
+
/**
* A IO Object + read/writebuffer + buffer-size for windows asynchronous IO handling
*/
struct io_facility
{
- HANDLE handle;
+ /**
+ * The mode the state machine associated with this object is in.
+ */
+ enum IO_State facility_state;
- BOOL path_open; // BOOL is winbool, NOT boolean!
- int facility_state;
- BOOL status;
+ /**
+ * If the path is open or blocked in general (used for quickly checking)
+ */
+ BOOL path_open; // BOOL is winbool (int), NOT boolean (unsigned char)!
+
+ /**
+ * Windows Object-Handle (used for accessing TAP and STDIN/STDOUT)
+ */
+ HANDLE handle;
+ /**
+ * Overlaped IO structure used for asynchronous IO in windows.
+ */
OVERLAPPED overlapped;
+
+ /**
+ * Buffer for reading things to and writing from...
+ */
+ unsigned char buffer[MAX_SIZE];
+
+ /**
+ * How much of this buffer was used when reading or how much data can be written
+ */
DWORD buffer_size;
+
+ /**
+ * Amount of data written, is compared to buffer_size.
+ */
DWORD buffer_size_written;
- unsigned char buffer[MAX_SIZE];
};
-/**
- * Operlapped IO states for facility objects
- */
-#define IOSTATE_FAILED -1 /* overlapped I/O has failed, stop processing */
-#define IOSTATE_READY 0 /* overlapped I/O is ready for work */
-#define IOSTATE_QUEUED 1 /* overlapped I/O has been queued */
-#define IOSTATE_WAITING 3 /* overlapped I/O has finished, but is waiting for it's write-partner */
-
/**
* ReOpenFile is only available as of XP SP2 and 2003 SP1
*/
WINBASEAPI HANDLE WINAPI ReOpenFile (HANDLE, DWORD, DWORD, DWORD);
+
/**
* Wrapper for executing a shellcommand in windows.
*
{
FILE *pipe;
- if (NULL == command ||
- NULL == (pipe = _popen (command, "rt")))
+ if ( (NULL == command) ||
+ (NULL == (pipe = _popen (command, "rt"))) )
return EINVAL;
-#ifdef TESTING
+#ifdef DEBUG
fprintf (stderr, "DEBUG: Command output: \n");
char output[LINE_LEN];
while (NULL != fgets (output, sizeof (output), pipe))
return _pclose (pipe);
}
+
/**
* @brief Sets the IPv6-Address given in address on the interface dev
*
return ret;
}
+
/**
* @brief Removes the IPv6-Address given in address from the interface dev
*
{
char command[LINE_LEN];
int ret = EINVAL;
-
+
// sanity checking was already done in set_address6
/*
* prepare the command
return ret;
}
+
/**
* @brief Removes the IPv4-Address given in address from the interface dev
*
{
char command[LINE_LEN];
int ret = EINVAL;
-
+
// sanity checking was already done in set_address4
/*
fprintf (stderr, "FATAL: removing IPv4 address failed: %s\n", strerror (ret));
}
+
/**
* Setup a new virtual interface to use for tunneling.
*
* @return: TRUE if setup was successful, else FALSE
*/
-static boolean
+static BOOL
setup_interface ()
{
/*
/**
* Bootstrap our device info using the drivers inf-file
*/
- if ( ! SetupDiGetINFClassA (inf_file_path,
+ if (!SetupDiGetINFClassA (inf_file_path,
&class_guid,
class_name, sizeof (class_name) / sizeof (char),
NULL))
return FALSE;
DeviceNode.cbSize = sizeof (SP_DEVINFO_DATA);
- if ( ! SetupDiCreateDeviceInfoA (DeviceInfo,
+ if (!SetupDiCreateDeviceInfoA (DeviceInfo,
class_name,
&class_guid,
NULL,
return FALSE;
/* Deploy all the information collected into the registry */
- if ( ! SetupDiSetDeviceRegistryPropertyA (DeviceInfo,
+ if (!SetupDiSetDeviceRegistryPropertyA (DeviceInfo,
&DeviceNode,
SPDRP_HARDWAREID,
(LPBYTE) hwidlist,
return FALSE;
/* Install our new class(=device) into the system */
- if ( ! SetupDiCallClassInstaller (DIF_REGISTERDEVICE,
+ if (!SetupDiCallClassInstaller (DIF_REGISTERDEVICE,
DeviceInfo,
&DeviceNode))
return FALSE;
/* This system call tends to take a while (several seconds!) on
"modern" Windoze systems */
- if ( ! UpdateDriverForPlugAndPlayDevicesA (NULL,
+ if (!UpdateDriverForPlugAndPlayDevicesA (NULL,
secondary_hwid,
inf_file_path,
INSTALLFLAG_FORCE | INSTALLFLAG_NONINTERACTIVE,
return TRUE;
}
+
/**
* Remove our new virtual interface to use for tunneling.
* This function must be called AFTER setup_interface!
*
* @return: TRUE if destruction was successful, else FALSE
*/
-static boolean
+static BOOL
remove_interface ()
{
SP_REMOVEDEVICE_PARAMS remove;
* 1. Prepare our existing device information set, and place the
* uninstall related information into the structure
*/
- if ( ! SetupDiSetClassInstallParamsA (DeviceInfo,
+ if (!SetupDiSetClassInstallParamsA (DeviceInfo,
(PSP_DEVINFO_DATA) & DeviceNode,
&remove.ClassInstallHeader,
sizeof (remove)))
/*
* 2. Uninstall the virtual interface using the class installer
*/
- if ( ! SetupDiCallClassInstaller (DIF_REMOVE,
+ if (!SetupDiCallClassInstaller (DIF_REMOVE,
DeviceInfo,
(PSP_DEVINFO_DATA) & DeviceNode))
return FALSE;
return TRUE;
}
+
/**
* Do all the lookup necessary to retrieve the inteface's actual name
* off the registry.
*
* @return: TRUE if we were able to lookup the interface's name, else FALSE
*/
-static boolean
+static BOOL
resolve_interface_name ()
{
SP_DEVINFO_LIST_DETAIL_DATA device_details;
DWORD len;
int i = 0;
int retrys;
- boolean retval = FALSE;
+ BOOL retval = FALSE;
char adapter[] = INTERFACE_REGISTRY_LOCATION;
/* We can obtain the PNP instance ID from our setupapi handle */
/* Of course there is a multitude of entries here, with arbitrary names,
* thus we need to iterate through there.
*/
- while ( ! retval)
+ while (!retval)
{
char instance_key[256];
char query_key [256];
return retval;
}
-static boolean
+
+/**
+ * Determines the version of the installed TAP32 driver and checks if it's sufficiently new for GNUNET
+ *
+ * @param handle the handle to our tap device
+ * @return TRUE if the version is sufficient, else FALSE
+ */
+static BOOL
check_tapw32_version (HANDLE handle)
{
ULONG version[3];
if (DeviceIoControl (handle, TAP_WIN_IOCTL_GET_VERSION,
&version, sizeof (version),
&version, sizeof (version), &len, NULL))
- {
fprintf (stderr, "INFO: TAP-Windows Driver Version %d.%d %s\n",
(int) version[0],
(int) version[1],
(version[2] ? "(DEBUG)" : ""));
- }
- if (version[0] != TAP_WIN_MIN_MAJOR || version[1] < TAP_WIN_MIN_MINOR)
- {
+ if (version[0] != TAP_WIN_MIN_MAJOR || version[1] < TAP_WIN_MIN_MINOR){
fprintf (stderr, "FATAL: This version of gnunet requires a TAP-Windows driver that is at least version %d.%d!\n",
TAP_WIN_MIN_MAJOR,
TAP_WIN_MIN_MINOR);
return FALSE;
}
+
return TRUE;
}
+
/**
* Creates a tun-interface called dev;
*
char device_path[256];
HANDLE handle;
- if ( ! setup_interface ())
+ if (! setup_interface ())
{
errno = ENODEV;
return INVALID_HANDLE_VALUE;
}
- if ( ! resolve_interface_name ())
+ if (!resolve_interface_name ())
{
errno = ENODEV;
return INVALID_HANDLE_VALUE;
}
/* get driver version info */
- if ( ! check_tapw32_version (handle))
+ if (!check_tapw32_version (handle))
{
CloseHandle (handle);
return INVALID_HANDLE_VALUE;
return handle;
}
+
/**
* Brings a TAP device up and sets it to connected state.
*
* @param handle the handle to our TAP device
* @return True if the operation succeeded, else false
*/
-static boolean
+static BOOL
tun_up (HANDLE handle)
{
ULONG status = TRUE;
DWORD len;
- if ( ! DeviceIoControl (handle, TAP_WIN_IOCTL_SET_MEDIA_STATUS,
- &status, sizeof (status),
- &status, sizeof (status), &len, NULL))
+ if (!DeviceIoControl (handle, TAP_WIN_IOCTL_SET_MEDIA_STATUS,
+ &status, sizeof (status),
+ &status, sizeof (status), &len, NULL))
{
fprintf (stderr, "FATAL: TAP driver ignored request to UP interface (DeviceIoControl call)!\n");
return FALSE;
}
+
/**
* Attempts to read off an input facility (tap or named pipe) in overlapped mode.
*
* @param output_facility output pipe or file to hand over data to.
* @return false if an event reset was impossible (OS error), else true
*/
-static boolean
-attempt_read (struct io_facility * input_facility,
- struct io_facility * output_facility)
+static BOOL
+attempt_read_tap (struct io_facility * input_facility,
+ struct io_facility * output_facility)
{
+ struct GNUNET_MessageHeader * hdr;
+ unsigned short size;
+ BOOL status;
+
switch (input_facility->facility_state)
{
case IOSTATE_READY:
- {
- if ( ! ResetEvent (input_facility->overlapped.hEvent))
+ {
+ if (!ResetEvent (input_facility->overlapped.hEvent))
{
return FALSE;
}
- input_facility->status = ReadFile (input_facility->handle,
- input_facility->buffer,
- MAX_SIZE,
- &input_facility->buffer_size,
- &input_facility->overlapped);
+
+ input_facility->buffer_size = 0;
+ status = ReadFile (input_facility->handle,
+ input_facility->buffer,
+ sizeof (input_facility->buffer) - sizeof (struct GNUNET_MessageHeader),
+ &input_facility->buffer_size,
+ &input_facility->overlapped);
/* Check how the task is handled */
- if (input_facility->status)
+ if (status)
{/* async event processed immediately*/
/* reset event manually*/
- if ( ! SetEvent (input_facility->overlapped.hEvent))
+ if (!SetEvent (input_facility->overlapped.hEvent))
return FALSE;
/* we successfully read something from the TAP and now need to
if ((IOSTATE_READY == output_facility->facility_state ||
IOSTATE_WAITING == output_facility->facility_state)
&& 0 < input_facility->buffer_size)
- { /* hand over this buffers content */
- memcpy (output_facility->buffer,
+ { /* hand over this buffers content and apply message header for gnunet */
+ hdr = (struct GNUNET_MessageHeader *) output_facility->buffer;
+ size = input_facility->buffer_size + sizeof (struct GNUNET_MessageHeader);
+
+ memcpy (output_facility->buffer + sizeof (struct GNUNET_MessageHeader),
input_facility->buffer,
- MAX_SIZE);
- output_facility->buffer_size = input_facility->buffer_size;
+ input_facility->buffer_size);
+
+ output_facility->buffer_size = size;
+ hdr->size = htons (size);
+ hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
output_facility->facility_state = IOSTATE_READY;
}
else if (0 < input_facility->buffer_size)
case IOSTATE_QUEUED:
{
// there was an operation going on already, check if that has completed now.
- input_facility->status = GetOverlappedResult (input_facility->handle,
- &input_facility->overlapped,
- &input_facility->buffer_size,
- FALSE);
- if (input_facility->status)
+ status = GetOverlappedResult (input_facility->handle,
+ &input_facility->overlapped,
+ &input_facility->buffer_size,
+ FALSE);
+ if (status)
{/* successful return for a queued operation */
- if ( ! ResetEvent (input_facility->overlapped.hEvent))
+ if (!ResetEvent (input_facility->overlapped.hEvent))
return FALSE;
/* we successfully read something from the TAP and now need to
if ((IOSTATE_READY == output_facility->facility_state ||
IOSTATE_WAITING == output_facility->facility_state)
&& 0 < input_facility->buffer_size)
- { /* hand over this buffers content */
- memcpy (output_facility->buffer,
+ { /* hand over this buffers content and apply message header for gnunet */
+ hdr = (struct GNUNET_MessageHeader *) output_facility->buffer;
+ size = input_facility->buffer_size + sizeof (struct GNUNET_MessageHeader);
+
+ memcpy (output_facility->buffer + sizeof (struct GNUNET_MessageHeader),
input_facility->buffer,
- MAX_SIZE);
- output_facility->buffer_size = input_facility->buffer_size;
+ input_facility->buffer_size);
+
+ output_facility->buffer_size = size;
+ hdr->size = htons(size);
+ hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
output_facility->facility_state = IOSTATE_READY;
input_facility->facility_state = IOSTATE_READY;
}
}
}
return TRUE;
+ case IOSTATE_RESUME:
+ hdr = (struct GNUNET_MessageHeader *) output_facility->buffer;
+ size = input_facility->buffer_size + sizeof (struct GNUNET_MessageHeader);
+
+ memcpy (output_facility->buffer + sizeof (struct GNUNET_MessageHeader),
+ input_facility->buffer,
+ input_facility->buffer_size);
+
+ output_facility->buffer_size = size;
+ hdr->size = htons (size);
+ hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
+ output_facility->facility_state = IOSTATE_READY;
+ input_facility->facility_state = IOSTATE_READY;
+ return TRUE;
+ default:
+ return TRUE;
+ }
+}
+
+/**
+ * Attempts to read off an input facility (tap or named pipe) in overlapped mode.
+ *
+ * 1.
+ * If the input facility is in IOSTATE_READY, it will issue a new read operation to the
+ * input handle. Then it goes into IOSTATE_QUEUED state.
+ * In case the read succeeded instantly the input facility enters 3.
+ *
+ * 2.
+ * If the input facility is in IOSTATE_QUEUED state, it will check if the queued read has finished already.
+ * If it has finished, go to state 3.
+ * If it has failed, set IOSTATE_FAILED
+ *
+ * 3.
+ * If the facility is finished with ready
+ * The read-buffer is copied to the output buffer, except for the GNUNET_MessageHeader.
+ * The input facility enters state IOSTATE_READY
+ * The output facility enters state IOSTATE_READY
+ * If the output facility is in state IOSTATE_QUEUED, the input facility enters IOSTATE_WAITING
+ *
+ * IOSTATE_WAITING is reset by the output facility, once it has completed.
+ *
+ * @param input_facility input named pipe or file to work with.
+ * @param output_facility output pipe or file to hand over data to.
+ * @return false if an event reset was impossible (OS error), else true
+ */
+static BOOL
+attempt_read_stdin (struct io_facility * input_facility,
+ struct io_facility * output_facility)
+{
+ struct GNUNET_MessageHeader * hdr;
+ BOOL status;
+ switch (input_facility->facility_state)
+ {
+ case IOSTATE_READY:
+ {
+ if (!ResetEvent (input_facility->overlapped.hEvent))
+ return FALSE;
+ input_facility->buffer_size = 0;
+ status = ReadFile (input_facility->handle,
+ input_facility->buffer,
+ sizeof (input_facility->buffer),
+ &input_facility->buffer_size,
+ &input_facility->overlapped);
+
+ /* Check how the task is handled */
+ if (status && (sizeof (struct GNUNET_MessageHeader) < input_facility->buffer_size))
+ {/* async event processed immediately*/
+ hdr = (struct GNUNET_MessageHeader *) input_facility->buffer;
+
+ /* reset event manually*/
+ if (!SetEvent (input_facility->overlapped.hEvent))
+ return FALSE;
+
+ if (ntohs (hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER ||
+ ntohs (hdr->size) > sizeof (input_facility->buffer))
+ {
+ fprintf (stderr, "WARNING: Protocol violation, got GNUnet Message type %h, size %h!\n", ntohs (hdr->type), ntohs (hdr->size));
+ input_facility->facility_state = IOSTATE_READY;
+ return TRUE;
+ }
+ if (ntohs (hdr->size) > input_facility->buffer_size);
+ // TODO: add support for partial read
+
+ /* we successfully read something from the TAP and now need to
+ * send it our via STDOUT. Is that possible at the moment? */
+ if (sizeof (struct GNUNET_MessageHeader) < input_facility->buffer_size)
+ {
+ if (IOSTATE_READY == output_facility->facility_state ||
+ IOSTATE_WAITING == output_facility->facility_state)
+ {
+ /* hand over this buffers content and strip gnunet message header */
+ memcpy (output_facility->buffer + sizeof (struct GNUNET_MessageHeader),
+ input_facility->buffer,
+ input_facility->buffer_size - sizeof (struct GNUNET_MessageHeader));
+ output_facility->buffer_size = input_facility->buffer_size - sizeof (struct GNUNET_MessageHeader);
+ output_facility->facility_state = IOSTATE_READY;
+
+ }
+ else if (IOSTATE_QUEUED == output_facility->facility_state)
+ /* If we have have read our buffer, wait for our write-partner*/
+ input_facility->facility_state = IOSTATE_WAITING;
+ // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish?
+ }
+ }
+ else if (status && 0 >= input_facility->buffer_size)
+ {
+ if (!SetEvent (input_facility->overlapped.hEvent))
+ return FALSE;
+
+ input_facility->facility_state = IOSTATE_READY;
+ }
+ else /* operation was either queued or failed*/
+ {
+ int err = GetLastError ();
+ if (ERROR_IO_PENDING == err)
+ { /* operation queued */
+ input_facility->facility_state = IOSTATE_QUEUED;
+ }
+ else
+ { /* error occurred, let the rest of the elements finish */
+ input_facility->path_open = FALSE;
+ input_facility->facility_state = IOSTATE_FAILED;
+ if (IOSTATE_WAITING == output_facility->facility_state)
+ output_facility->path_open = FALSE;
+
+ fprintf (stderr, "FATAL: Read from handle failed, allowing write to finish!\n");
+ }
+ }
+ }
+ return TRUE;
+ // We are queued and should check if the read has finished
+ case IOSTATE_QUEUED:
+ {
+ // there was an operation going on already, check if that has completed now.
+ status = GetOverlappedResult (input_facility->handle,
+ &input_facility->overlapped,
+ &input_facility->buffer_size,
+ FALSE);
+ if (status)
+ {/* successful return for a queued operation */
+ hdr = (struct GNUNET_MessageHeader *) input_facility->buffer;
+
+ if (!ResetEvent (input_facility->overlapped.hEvent))
+ return FALSE;
+
+ if (ntohs (hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER ||
+ ntohs (hdr->size) > sizeof (input_facility->buffer))
+ {
+ fprintf (stderr, "WARNING: Protocol violation, got GNUnet Message type %h, size %h!\n", ntohs (hdr->type), ntohs (hdr->size));
+ input_facility->facility_state = IOSTATE_READY;
+ return TRUE;
+ }
+ if (ntohs (hdr->size) > input_facility->buffer_size );
+ // TODO: add support for partial read
+
+ /* we successfully read something from the TAP and now need to
+ * send it our via STDOUT. Is that possible at the moment? */
+ if ((IOSTATE_READY == output_facility->facility_state ||
+ IOSTATE_WAITING == output_facility->facility_state)
+ && sizeof(struct GNUNET_MessageHeader) < input_facility->buffer_size)
+ { /* hand over this buffers content and strip gnunet message header */
+ memcpy (output_facility->buffer + sizeof(struct GNUNET_MessageHeader),
+ input_facility->buffer,
+ input_facility->buffer_size - sizeof(struct GNUNET_MessageHeader));
+ output_facility->buffer_size = input_facility->buffer_size - sizeof(struct GNUNET_MessageHeader);
+ output_facility->facility_state = IOSTATE_READY;
+ input_facility->facility_state = IOSTATE_READY;
+ }
+ else if (sizeof(struct GNUNET_MessageHeader) < input_facility->buffer_size)
+ { /* If we have have read our buffer, wait for our write-partner*/
+ input_facility->facility_state = IOSTATE_WAITING;
+ // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish?
+ }
+ else if (sizeof(struct GNUNET_MessageHeader) >= input_facility->buffer_size)
+ input_facility->facility_state = IOSTATE_READY;
+ }
+ else
+ { /* operation still pending/queued or failed? */
+ int err = GetLastError ();
+ if (ERROR_IO_INCOMPLETE != err && ERROR_IO_PENDING != err)
+ { /* error occurred, let the rest of the elements finish */
+ input_facility->path_open = FALSE;
+ input_facility->facility_state = IOSTATE_FAILED;
+ if (IOSTATE_WAITING == output_facility->facility_state)
+ output_facility->path_open = FALSE;
+ fprintf (stderr, "FATAL: Read from handle failed, allowing write to finish!\n");
+ }
+ }
+ }
+ return TRUE;
+ case IOSTATE_RESUME: /* Our buffer was filled already but our write facility was busy. */
+ memcpy (output_facility->buffer + sizeof (struct GNUNET_MessageHeader),
+ input_facility->buffer,
+ input_facility->buffer_size - sizeof (struct GNUNET_MessageHeader));
+ output_facility->buffer_size = input_facility->buffer_size - sizeof (struct GNUNET_MessageHeader);
+ output_facility->facility_state = IOSTATE_READY;
+ input_facility->facility_state = IOSTATE_READY;
+ return TRUE;
default:
return TRUE;
}
* @param input_facility input named pipe or file to work with.
* @return false if an event reset was impossible (OS error), else true
*/
-static boolean
+static BOOL
attempt_write (struct io_facility * output_facility,
struct io_facility * input_facility)
{
- if (IOSTATE_READY == output_facility->facility_state
- && output_facility->buffer_size > 0)
+ BOOL status;
+
+ switch (output_facility->facility_state)
{
- if ( ! ResetEvent (output_facility->overlapped.hEvent))
- {
- return FALSE;
- }
+ case IOSTATE_READY:
+
+ if (!ResetEvent (output_facility->overlapped.hEvent))
+ return FALSE;
- output_facility->status = WriteFile (output_facility->handle,
- output_facility->buffer,
- output_facility->buffer_size,
- &output_facility->buffer_size_written,
- &output_facility->overlapped);
+ output_facility->buffer_size_written = 0;
+ status = WriteFile (output_facility->handle,
+ output_facility->buffer,
+ output_facility->buffer_size,
+ &output_facility->buffer_size_written,
+ &output_facility->overlapped);
- /* Check how the task is handled */
- if (output_facility->status &&
+ /* Check how the task was handled */
+ if (status &&
output_facility->buffer_size_written == output_facility->buffer_size)
{/* async event processed immediately*/
/* reset event manually*/
- if ( ! SetEvent (output_facility->overlapped.hEvent))
+ if (!SetEvent (output_facility->overlapped.hEvent))
return FALSE;
/* we are now waiting for our buffer to be filled*/
/* we successfully wrote something and now need to reset our reader */
if (IOSTATE_WAITING == input_facility->facility_state)
- input_facility->facility_state = IOSTATE_READY;
+ input_facility->facility_state = IOSTATE_RESUME;
else if (IOSTATE_FAILED == input_facility->facility_state)
output_facility->path_open = FALSE;
}
fprintf (stderr, "FATAL: Write to handle failed, exiting!\n");
}
}
-
- }
- else if (IOSTATE_QUEUED == output_facility->facility_state)
- {
+ return TRUE;
+ case IOSTATE_QUEUED:
// there was an operation going on already, check if that has completed now.
- output_facility->status = GetOverlappedResult (output_facility->handle,
- &output_facility->overlapped,
- &output_facility->buffer_size_written,
- FALSE);
- if (output_facility->status &&
+ status = GetOverlappedResult (output_facility->handle,
+ &output_facility->overlapped,
+ &output_facility->buffer_size_written,
+ FALSE);
+ if (status &&
output_facility->buffer_size_written == output_facility->buffer_size)
{/* successful return for a queued operation */
- if ( ! ResetEvent (output_facility->overlapped.hEvent))
+ if (!ResetEvent (output_facility->overlapped.hEvent))
return FALSE;
/* we are now waiting for our buffer to be filled*/
/* we successfully wrote something and now need to reset our reader */
if (IOSTATE_WAITING == input_facility->facility_state)
- input_facility->facility_state = IOSTATE_READY;
+ input_facility->facility_state = IOSTATE_RESUME;
else if (IOSTATE_FAILED == input_facility->facility_state)
output_facility->path_open = FALSE;
}
fprintf (stderr, "FATAL: Write to handle failed, exiting!\n");
}
}
+ default:
+ return TRUE;
}
-
- return TRUE;
}
+
/**
* Initialize a overlapped structure
*
* @param signaled if the hEvent created should default to signaled or not
* @return true on success, else false
*/
-static boolean
+static BOOL
initialize_io_facility (struct io_facility * elem,
- BOOL initial_state,
+ int initial_state,
BOOL signaled)
{
-
elem->path_open = TRUE;
- elem->status = initial_state;
elem->handle = INVALID_HANDLE_VALUE;
- elem->facility_state = 0;
+ elem->facility_state = initial_state;
elem->buffer_size = 0;
elem->overlapped.hEvent = CreateEvent (NULL, TRUE, signaled, NULL);
if (NULL == elem->overlapped.hEvent)
return TRUE;
}
+
/**
* Start forwarding to and from the tunnel.
*
* DHCP and such are all features we will never use in gnunet afaik.
* But for openvpn those are essential.
*/
- if ( ! tun_up (tap_handle))
+ if (!tun_up (tap_handle))
return;
/* Initialize our overlapped IO structures*/
- if ( ! (initialize_io_facility (&tap_read, TRUE, FALSE)
- && initialize_io_facility (&tap_write, FALSE, TRUE)
- && initialize_io_facility (&std_in, TRUE, FALSE)
- && initialize_io_facility (&std_out, FALSE, TRUE)))
+ if (!(initialize_io_facility (&tap_read, IOSTATE_READY, FALSE)
+ && initialize_io_facility (&tap_write, IOSTATE_WAITING, TRUE)
+ && initialize_io_facility (&std_in, IOSTATE_READY, FALSE)
+ && initialize_io_facility (&std_out, IOSTATE_WAITING, TRUE)))
goto teardown_final;
/* Handles for STDIN and STDOUT */
tap_read.handle = tap_handle;
tap_write.handle = tap_handle;
+#ifdef DEBUG_TO_CONSOLE
+ /* Debug output to console STDIN/STDOUT*/
+ std_in.handle = parent_std_in_handle;
+ std_out.handle = parent_std_out_handle;
+#else
+
/*
* Find out the types of our handles.
* This part is a problem, because in windows we need to handle files,
FILE_TYPE_PIPE != GetFileType (parent_std_out_handle))
{
fprintf (stderr, "ERROR: stdin/stdout must be named pipes!\n");
- printf("\nPress Enter to continue...");
- getchar();
goto teardown;
}
fprintf (stderr, "FATAL: Could not reopen stdout for in overlapped mode, has to be a named pipe!\n");
goto teardown;
}
-
+#endif
+
while (std_out.path_open || tap_write.path_open)
{
/* perform READ from stdin if possible */
- if (std_in.path_open && tap_write.path_open && !attempt_read (&std_in, &tap_write))
+ if (std_in.path_open && (!attempt_read_stdin (&std_in, &tap_write)))
break;
/* perform READ from tap if possible */
- if (tap_read.path_open && std_out.path_open && !attempt_read (&tap_read, &std_out))
+ if (tap_read.path_open && (!attempt_read_tap (&tap_read, &std_out)))
break;
/* perform WRITE to tap if possible */
- if (tap_write.path_open && !attempt_write (&tap_write, &std_in))
+ if (tap_write.path_open && (!attempt_write (&tap_write, &std_in)))
break;
/* perform WRITE to STDOUT if possible */
- if (std_out.path_open && !attempt_write (&std_out, &tap_read))
+ if (std_out.path_open && (!attempt_write (&std_out, &tap_read)))
break;
}
CloseHandle (tap_handle);
}
+
/**
* Open VPN tunnel interface.
*
* @param argc must be 6
* @param argv 0: binary name (gnunet-helper-vpn)
- * 1: tunnel interface name (gnunet-vpn)
+ * 1: tunnel interface prefix (gnunet-vpn)
* 2: IPv6 address (::1), "-" to disable
* 3: IPv6 netmask length in bits (64), ignored if #2 is "-"
* 4: IPv4 address (1.2.3.4), "-" to disable
char hwid[LINE_LEN];
HANDLE handle;
int global_ret = 0;
- boolean have_ip4=FALSE;
- boolean have_ip6=FALSE;
+ BOOL have_ip4 = FALSE;
+ BOOL have_ip6 = FALSE;
if (6 != argc)
{
- fprintf (stderr, "FATAL: must supply 5 arguments!\n");
+ fprintf (stderr, "FATAL: must supply 5 arguments!\nUsage:\ngnunet-helper-vpn <if name prefix> <address6 or \"-\"> <netbits6> <address4 or \"-\"> <netmask4>\n", argv[0]);
return 1;
}
if (0 != (global_ret = set_address6 (address, prefix_len)))
goto cleanup;
-
+
have_ip6 = TRUE;
}
if (0 != (global_ret = set_address4 (address, mask)))
goto cleanup;
-
+
have_ip4 = TRUE;
}
global_ret = 0;
cleanup:
- if (have_ip4){
+ if (have_ip4)
+ {
const char *address = argv[4];
- remove_address4(address);
+ remove_address4 (address);
}
- if (have_ip6){
+ if (have_ip6)
+ {
const char *address = argv[2];
- remove_address6(address);
+ remove_address6 (address);
}
remove_interface ();
return global_ret;