/*
device.c -- Interaction with Windows tap driver in a MinGW environment
Copyright (C) 2002-2005 Ivo Timmermans,
- 2002-2013 Guus Sliepen <guus@tinc-vpn.org>
+ 2002-2014 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
device_read_overlapped.Offset = 0;
device_read_overlapped.OffsetHigh = 0;
- int status = ReadFile(device_handle, (void *)device_read_packet.data, MTU, NULL, &device_read_overlapped);
+ int status;
+ for (;;) {
+ DWORD len;
+ status = ReadFile(device_handle, (void *)device_read_packet.data, MTU, &len, &device_read_overlapped);
+ if (!status) {
+ if (GetLastError() != ERROR_IO_PENDING)
+ logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
+ device, strerror(errno));
+ break;
+ }
- if(!status && GetLastError() != ERROR_IO_PENDING) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
- device, strerror(errno));
+ device_read_packet.len = len;
+ device_read_packet.priority = 0;
+ route(myself, &device_read_packet);
}
}
io_del(&device_read_io);
CancelIo(device_handle);
+
+ /* According to MSDN, CancelIo() does not necessarily wait for the operation to complete.
+ To prevent race conditions, make sure the operation is complete
+ before we close the event it's referencing. */
+
+ DWORD len;
+ if(!GetOverlappedResult(device_handle, &device_read_overlapped, &len, TRUE) && GetLastError() != ERROR_OPERATION_ABORTED)
+ logger(DEBUG_ALWAYS, LOG_ERR, "Could not wait for %s %s read to cancel: %s", device_info, device, winerror(GetLastError()));
+
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);
}
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
packet->len, device_info);
- if(!WriteFile(device_handle, packet->data, packet->len, &outlen, &overlapped)) {
+ if(!WriteFile(device_handle, DATA(packet), packet->len, &outlen, &overlapped)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info, device, winerror(GetLastError()));
return false;
}