📄 tap-win32.c
字号:
/* * TAP-Win32 -- A kernel driver to provide virtual tap device functionality * on Windows. Originally derived from the CIPE-Win32 * project by Damion K. Wilson, with extensive modifications by * James Yonan. * * All source code which derives from the CIPE-Win32 project is * Copyright (C) Damion K. Wilson, 2003, and is released under the * GPL version 2 (see below). * * All other source code is Copyright (C) James Yonan, 2003-2004, * and is released under the GPL version 2 (see below). * * 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 * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program (see the file COPYING included with this * distribution); if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include "vl.h"#include <stdio.h>#include <windows.h>/* NOTE: PCIBus is redefined in winddk.h */#define PCIBus _PCIBus#include <ddk/ntapi.h>#include <ddk/winddk.h>#include <ddk/ntddk.h>#undef PCIBus//=============// TAP IOCTLs//=============#define TAP_CONTROL_CODE(request,method) \ CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED)#define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED)#define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE (3, METHOD_BUFFERED)#define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE (4, METHOD_BUFFERED)#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED)#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE (6, METHOD_BUFFERED)#define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE (7, METHOD_BUFFERED)#define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE (8, METHOD_BUFFERED)#define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE (9, METHOD_BUFFERED)//=================// Registry keys//=================#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"//======================// Filesystem prefixes//======================#define USERMODEDEVICEDIR "\\\\.\\Global\\"#define TAPSUFFIX ".tap"//======================// Compile time configuration//======================//#define DEBUG_TAP_WIN32 1#define TUN_ASYNCHRONOUS_WRITES 1#define TUN_BUFFER_SIZE 1560#define TUN_MAX_BUFFER_COUNT 32/* * The data member "buffer" must be the first element in the tun_buffer * structure. See the function, tap_win32_free_buffer. */typedef struct tun_buffer_s { unsigned char buffer [TUN_BUFFER_SIZE]; unsigned long read_size; struct tun_buffer_s* next;} tun_buffer_t;typedef struct tap_win32_overlapped { HANDLE handle; HANDLE read_event; HANDLE write_event; HANDLE output_queue_semaphore; HANDLE free_list_semaphore; CRITICAL_SECTION output_queue_cs; CRITICAL_SECTION free_list_cs; OVERLAPPED read_overlapped; OVERLAPPED write_overlapped; tun_buffer_t buffers[TUN_MAX_BUFFER_COUNT]; tun_buffer_t* free_list; tun_buffer_t* output_queue_front; tun_buffer_t* output_queue_back;} tap_win32_overlapped_t;static tap_win32_overlapped_t tap_overlapped;static tun_buffer_t* get_buffer_from_free_list(tap_win32_overlapped_t* const overlapped) { tun_buffer_t* buffer = NULL; WaitForSingleObject(overlapped->free_list_semaphore, INFINITE); EnterCriticalSection(&overlapped->free_list_cs); buffer = overlapped->free_list;// assert(buffer != NULL); overlapped->free_list = buffer->next; LeaveCriticalSection(&overlapped->free_list_cs); buffer->next = NULL; return buffer;}static void put_buffer_on_free_list(tap_win32_overlapped_t* const overlapped, tun_buffer_t* const buffer){ EnterCriticalSection(&overlapped->free_list_cs); buffer->next = overlapped->free_list; overlapped->free_list = buffer; LeaveCriticalSection(&overlapped->free_list_cs); ReleaseSemaphore(overlapped->free_list_semaphore, 1, NULL);}static tun_buffer_t* get_buffer_from_output_queue(tap_win32_overlapped_t* const overlapped, const int block) { tun_buffer_t* buffer = NULL; DWORD result, timeout = block ? INFINITE : 0L; // Non-blocking call result = WaitForSingleObject(overlapped->output_queue_semaphore, timeout); switch (result) { // The semaphore object was signaled. case WAIT_OBJECT_0: EnterCriticalSection(&overlapped->output_queue_cs); buffer = overlapped->output_queue_front; overlapped->output_queue_front = buffer->next; if(overlapped->output_queue_front == NULL) { overlapped->output_queue_back = NULL; } LeaveCriticalSection(&overlapped->output_queue_cs); break; // Semaphore was nonsignaled, so a time-out occurred. case WAIT_TIMEOUT: // Cannot open another window. break; } return buffer;}static tun_buffer_t* get_buffer_from_output_queue_immediate (tap_win32_overlapped_t* const overlapped) { return get_buffer_from_output_queue(overlapped, 0);}static void put_buffer_on_output_queue(tap_win32_overlapped_t* const overlapped, tun_buffer_t* const buffer){ EnterCriticalSection(&overlapped->output_queue_cs); if(overlapped->output_queue_front == NULL && overlapped->output_queue_back == NULL) { overlapped->output_queue_front = overlapped->output_queue_back = buffer; } else { buffer->next = NULL; overlapped->output_queue_back->next = buffer; overlapped->output_queue_back = buffer; } LeaveCriticalSection(&overlapped->output_queue_cs); ReleaseSemaphore(overlapped->output_queue_semaphore, 1, NULL);}static int is_tap_win32_dev(const char *guid){ HKEY netcard_key; LONG status; DWORD len; int i = 0; status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, ADAPTER_KEY, 0, KEY_READ, &netcard_key); if (status != ERROR_SUCCESS) { return FALSE; } for (;;) { char enum_name[256]; char unit_string[256]; HKEY unit_key; char component_id_string[] = "ComponentId"; char component_id[256]; char net_cfg_instance_id_string[] = "NetCfgInstanceId"; char net_cfg_instance_id[256]; DWORD data_type; len = sizeof (enum_name); status = RegEnumKeyEx( netcard_key, i, enum_name, &len, NULL, NULL, NULL, NULL); if (status == ERROR_NO_MORE_ITEMS) break; else if (status != ERROR_SUCCESS) { return FALSE; } snprintf (unit_string, sizeof(unit_string), "%s\\%s", ADAPTER_KEY, enum_name); status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, unit_string, 0, KEY_READ, &unit_key); if (status != ERROR_SUCCESS) { return FALSE; } else { len = sizeof (component_id); status = RegQueryValueEx( unit_key, component_id_string, NULL, &data_type, component_id, &len); if (!(status != ERROR_SUCCESS || data_type != REG_SZ)) { len = sizeof (net_cfg_instance_id); status = RegQueryValueEx( unit_key, net_cfg_instance_id_string, NULL, &data_type, net_cfg_instance_id, &len); if (status == ERROR_SUCCESS && data_type == REG_SZ) { if (/* !strcmp (component_id, TAP_COMPONENT_ID) &&*/ !strcmp (net_cfg_instance_id, guid)) { RegCloseKey (unit_key); RegCloseKey (netcard_key); return TRUE; } } } RegCloseKey (unit_key); } ++i; } RegCloseKey (netcard_key); return FALSE;}static int get_device_guid( char *name, int name_size, char *actual_name, int actual_name_size){ LONG status; HKEY control_net_key; DWORD len; int i = 0; int stop = 0; status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &control_net_key); if (status != ERROR_SUCCESS) { return -1; } while (!stop) { char enum_name[256]; char connection_string[256]; HKEY connection_key; char name_data[256]; DWORD name_type; const char name_string[] = "Name"; len = sizeof (enum_name); status = RegEnumKeyEx( control_net_key, i, enum_name, &len, NULL, NULL, NULL, NULL); if (status == ERROR_NO_MORE_ITEMS) break; else if (status != ERROR_SUCCESS) { return -1; } snprintf(connection_string, sizeof(connection_string), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, enum_name); status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, connection_string,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -