📄 tap-win32.c
字号:
0, KEY_READ, &connection_key); if (status == ERROR_SUCCESS) { len = sizeof (name_data); status = RegQueryValueEx( connection_key, name_string, NULL, &name_type, name_data, &len); if (status != ERROR_SUCCESS || name_type != REG_SZ) { return -1; } else { if (is_tap_win32_dev(enum_name)) { snprintf(name, name_size, "%s", enum_name); if (actual_name) { if (strcmp(actual_name, "") != 0) { if (strcmp(name_data, actual_name) != 0) { RegCloseKey (connection_key); ++i; continue; } } else { snprintf(actual_name, actual_name_size, "%s", name_data); } } stop = 1; } } RegCloseKey (connection_key); } ++i; } RegCloseKey (control_net_key); if (stop == 0) return -1; return 0;}static int tap_win32_set_status(HANDLE handle, int status){ unsigned long len = 0; return DeviceIoControl(handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof (status), &status, sizeof (status), &len, NULL);}static void tap_win32_overlapped_init(tap_win32_overlapped_t* const overlapped, const HANDLE handle){ overlapped->handle = handle; overlapped->read_event = CreateEvent(NULL, FALSE, FALSE, NULL); overlapped->write_event = CreateEvent(NULL, FALSE, FALSE, NULL); overlapped->read_overlapped.Offset = 0; overlapped->read_overlapped.OffsetHigh = 0; overlapped->read_overlapped.hEvent = overlapped->read_event; overlapped->write_overlapped.Offset = 0; overlapped->write_overlapped.OffsetHigh = 0; overlapped->write_overlapped.hEvent = overlapped->write_event; InitializeCriticalSection(&overlapped->output_queue_cs); InitializeCriticalSection(&overlapped->free_list_cs); overlapped->output_queue_semaphore = CreateSemaphore( NULL, // default security attributes 0, // initial count TUN_MAX_BUFFER_COUNT, // maximum count NULL); // unnamed semaphore if(!overlapped->output_queue_semaphore) { fprintf(stderr, "error creating output queue semaphore!\n"); } overlapped->free_list_semaphore = CreateSemaphore( NULL, // default security attributes TUN_MAX_BUFFER_COUNT, // initial count TUN_MAX_BUFFER_COUNT, // maximum count NULL); // unnamed semaphore if(!overlapped->free_list_semaphore) { fprintf(stderr, "error creating free list semaphore!\n"); } overlapped->free_list = overlapped->output_queue_front = overlapped->output_queue_back = NULL; { unsigned index; for(index = 0; index < TUN_MAX_BUFFER_COUNT; index++) { tun_buffer_t* element = &overlapped->buffers[index]; element->next = overlapped->free_list; overlapped->free_list = element; } }}static int tap_win32_write(tap_win32_overlapped_t *overlapped, const void *buffer, unsigned long size){ unsigned long write_size; BOOL result; DWORD error; result = GetOverlappedResult( overlapped->handle, &overlapped->write_overlapped, &write_size, FALSE); if (!result && GetLastError() == ERROR_IO_INCOMPLETE) WaitForSingleObject(overlapped->write_event, INFINITE); result = WriteFile(overlapped->handle, buffer, size, &write_size, &overlapped->write_overlapped); if (!result) { switch (error = GetLastError()) { case ERROR_IO_PENDING: #ifndef TUN_ASYNCHRONOUS_WRITES WaitForSingleObject(overlapped->write_event, INFINITE);#endif break; default: return -1; } } return 0;}static DWORD WINAPI tap_win32_thread_entry(LPVOID param){ tap_win32_overlapped_t *overlapped = (tap_win32_overlapped_t*)param; unsigned long read_size; BOOL result; DWORD dwError; tun_buffer_t* buffer = get_buffer_from_free_list(overlapped); for (;;) { result = ReadFile(overlapped->handle, buffer->buffer, sizeof(buffer->buffer), &read_size, &overlapped->read_overlapped); if (!result) { dwError = GetLastError(); if (dwError == ERROR_IO_PENDING) { WaitForSingleObject(overlapped->read_event, INFINITE); result = GetOverlappedResult( overlapped->handle, &overlapped->read_overlapped, &read_size, FALSE); if (!result) {#if DEBUG_TAP_WIN32 LPVOID lpBuffer; dwError = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) & lpBuffer, 0, NULL ); fprintf(stderr, "Tap-Win32: Error GetOverlappedResult %d - %s\n", dwError, lpBuffer); LocalFree( lpBuffer );#endif } } else {#if DEBUG_TAP_WIN32 LPVOID lpBuffer; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) & lpBuffer, 0, NULL ); fprintf(stderr, "Tap-Win32: Error ReadFile %d - %s\n", dwError, lpBuffer); LocalFree( lpBuffer );#endif } } if(read_size > 0) { buffer->read_size = read_size; put_buffer_on_output_queue(overlapped, buffer); buffer = get_buffer_from_free_list(overlapped); } } return 0;}static int tap_win32_read(tap_win32_overlapped_t *overlapped, uint8_t **pbuf, int max_size){ int size = 0; tun_buffer_t* buffer = get_buffer_from_output_queue_immediate(overlapped); if(buffer != NULL) { *pbuf = buffer->buffer; size = (int)buffer->read_size; if(size > max_size) { size = max_size; } } return size;}static void tap_win32_free_buffer(tap_win32_overlapped_t *overlapped, char* pbuf) { tun_buffer_t* buffer = (tun_buffer_t*)pbuf; put_buffer_on_free_list(overlapped, buffer);}static int tap_win32_open(tap_win32_overlapped_t **phandle, const char *prefered_name){ char device_path[256]; char device_guid[0x100]; int rc; HANDLE handle; BOOL bret; char name_buffer[0x100] = {0, }; struct { unsigned long major; unsigned long minor; unsigned long debug; } version; LONG version_len; DWORD idThread; HANDLE hThread; if (prefered_name != NULL) snprintf(name_buffer, sizeof(name_buffer), "%s", prefered_name); rc = get_device_guid(device_guid, sizeof(device_guid), name_buffer, sizeof(name_buffer)); if (rc) return -1; snprintf (device_path, sizeof(device_path), "%s%s%s", USERMODEDEVICEDIR, device_guid, TAPSUFFIX); handle = CreateFile ( device_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0 ); if (handle == INVALID_HANDLE_VALUE) { return -1; } bret = DeviceIoControl(handle, TAP_IOCTL_GET_VERSION, &version, sizeof (version), &version, sizeof (version), &version_len, NULL); if (bret == FALSE) { CloseHandle(handle); return -1; } if (!tap_win32_set_status(handle, TRUE)) { return -1; } tap_win32_overlapped_init(&tap_overlapped, handle); *phandle = &tap_overlapped; hThread = CreateThread(NULL, 0, tap_win32_thread_entry, (LPVOID)&tap_overlapped, 0, &idThread); SetThreadPriority(hThread,THREAD_PRIORITY_TIME_CRITICAL); return 0;}/********************************************/ typedef struct TAPState { VLANClientState *vc; tap_win32_overlapped_t *handle; } TAPState;static TAPState *tap_win32_state = NULL;static void tap_receive(void *opaque, const uint8_t *buf, int size){ TAPState *s = opaque; tap_win32_write(s->handle, buf, size);}/* XXX: horrible, suppress this by using proper thread signaling */void tap_win32_poll(void){ TAPState *s = tap_win32_state; uint8_t *buf; int max_size = 4096; int size; if (!s) return; size = tap_win32_read(s->handle, &buf, max_size); if (size > 0) { qemu_send_packet(s->vc, buf, size); tap_win32_free_buffer(s->handle, buf); }}int tap_win32_init(VLANState *vlan, const char *ifname){ TAPState *s; s = qemu_mallocz(sizeof(TAPState)); if (!s) return -1; if (tap_win32_open(&s->handle, ifname) < 0) { printf("tap: Could not open '%s'\n", ifname); return -1; } s->vc = qemu_new_vlan_client(vlan, tap_receive, NULL, s); snprintf(s->vc->info_str, sizeof(s->vc->info_str), "tap: ifname=%s", ifname); tap_win32_state = s; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -