Only read from TAP-Win32 if the device is enabled.
authorEtienne Dechamps <etienne@edechamps.fr>
Sat, 19 Jul 2014 15:05:23 +0000 (16:05 +0100)
committerEtienne Dechamps <etienne@edechamps.fr>
Sat, 19 Jul 2014 15:05:23 +0000 (16:05 +0100)
With newer TAP-Win32 versions (such as the experimental
tap-windows6 9.21.0), tinc is unable to read from the virtual network
device:

    Error while reading from (null) {23810A13-BCA9-44CE-94C6-9AEDFBF85736}: No such file or directory

This is because these new drivers apparently don't accept reads when
the device is not in the connected state (media status).

This commit fixes the issue by making sure we start reading no sooner
than when the device is enabled, and that we stop reading when the
device is disabled. This also makes the behavior somewhat cleaner,
because it doesn't make much sense to read from a disabled device
anyway.

src/mingw/device.c

index b6dffbc..2ef0064 100644 (file)
@@ -177,12 +177,6 @@ static bool setup_device(void) {
                overwrite_mac = 1;
        }
 
-       /* Start the tap reader */
-
-       io_add_event(&device_read_io, device_handle_read, NULL, CreateEvent(NULL, TRUE, FALSE, NULL));
-       device_read_overlapped.hEvent = device_read_io.event;
-       device_issue_read();
-
        device_info = "Windows tap device";
 
        logger(DEBUG_ALWAYS, LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
@@ -192,22 +186,29 @@ static bool setup_device(void) {
 
 static void enable_device(void) {
        logger(DEBUG_ALWAYS, LOG_INFO, "Enabling %s", device_info);
+
        ULONG status = 1;
        DWORD len;
        DeviceIoControl(device_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof status, &status, sizeof status, &len, NULL);
+
+       io_add_event(&device_read_io, device_handle_read, NULL, CreateEvent(NULL, TRUE, FALSE, NULL));
+       device_read_overlapped.hEvent = device_read_io.event;
+       device_issue_read();
 }
 
 static void disable_device(void) {
        logger(DEBUG_ALWAYS, LOG_INFO, "Disabling %s", device_info);
+
+       io_del(&device_read_io);
+       CancelIo(device_handle);
+       CloseHandle(device_read_overlapped.hEvent);
+
        ULONG status = 0;
        DWORD len;
        DeviceIoControl(device_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof status, &status, sizeof status, &len, NULL);
 }
 
 static void close_device(void) {
-       io_del(&device_read_io);
-       CancelIo(device_handle);
-       CloseHandle(device_read_overlapped.hEvent);
        CloseHandle(device_handle); device_handle = INVALID_HANDLE_VALUE;
 
        free(device); device = NULL;