⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 skyeye_net_tap.c

📁 skyeye-1.2-RC7-3的源代码
💻 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 "arch/arm/common/armdefs.h"
#include <SDL/SDL.h>
#include <SDL/SDL_thread.h>
#include <SDL/SDL_mutex.h>
#undef WORD



#include <stdio.h>
#include <windows.h>

#include <ddk/ntapi.h>
#include <ddk/winddk.h>
#include <ddk/ntddk.h>

#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)

// Legacy TAP IOCTLs
#define OLD_TAP_CONTROL_CODE(request,method) \
  CTL_CODE (FILE_DEVICE_PHYSICAL_NETCARD | 8000, request, method, FILE_ANY_ACCESS)

#define OLD_TAP_IOCTL_GET_VERSION       OLD_TAP_CONTROL_CODE (3, 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 SYSDEVICEDIR      "\\Device\\"
#define USERDEVICEDIR     "\\DosDevices\\Global\\"
#define TAPSUFFIX         ".tap"

#define BUFFER_SIZE	65536
#define READ_SIZE	16384
#define ERRORMSG_SIZE	1024

#define printm(s...)	printf("[TAP-WIN32]: "s)
#define bool int
#define true 1
#define false 0

HANDLE		mFile;
unsigned char	mBuf[BUFFER_SIZE];
DWORD		mBuflen;
OVERLAPPED	mOverlapped;
#define TAP_WIN32_MIN_MAJOR 7
#define TAP_WIN32_MIN_MINOR 1
	
	
	
	

static void GetErrorString(char *out, DWORD error) 
{
	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
    		  	NULL,
    			error,
    			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    			(LPTSTR) out,
    			ERRORMSG_SIZE,
    			NULL);
}


static bool 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) {
		printm("Error opening registry key: %s\n", ADAPTER_KEY);
		return false;
	}

	while (true) {
		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) {
			printm("Error enumerating registry subkeys of key: %s\n",
				ADAPTER_KEY);
			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) {
			printm("Error opening registry key: %s\n", unit_string); 
			return false;
		} else {
			len = sizeof (component_id);
			status = RegQueryValueEx(unit_key, component_id_string, NULL, &data_type, (BYTE *)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, (BYTE *)net_cfg_instance_id,	&len);

				if (status == ERROR_SUCCESS && data_type == REG_SZ) {
					if (!strncmp(component_id, "tap", 3)
						&& !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;
	bool stop = false;

	status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &control_net_key);

	if (status != ERROR_SUCCESS) {
		printm("Error opening registry key: %s", NETWORK_CONNECTIONS_KEY);
		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) {
			printm("Error enumerating registry subkeys of key: %s", NETWORK_CONNECTIONS_KEY);
			return 1;
		}

		snprintf(connection_string, sizeof(connection_string), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, enum_name);
		status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, connection_string, 0, KEY_READ, &connection_key);

		if (status == ERROR_SUCCESS) {
			len = sizeof (name_data);
			status = RegQueryValueEx(connection_key, name_string, NULL, &name_type, (BYTE *)name_data, &len);

			if (status != ERROR_SUCCESS || name_type != REG_SZ) {
				printm("Error opening registry key: %s\\%s\\%s", NETWORK_CONNECTIONS_KEY, connection_string, name_string);
			        return 1;
			} else {
				if (is_tap_win32_dev(enum_name)) {
					printm("Found TAP device named '%s'\n", name_data);
					snprintf(name, name_size, "%s", enum_name);
					if (actual_name)
						ht_snprintf(actual_name, actual_name_size, "%s", name_data);
					stop = true;
				}
			}
			RegCloseKey(connection_key);
		}
		++i;
	}
	RegCloseKey(control_net_key);

	if (!stop)
		return 1;

	return 0; 
}

bool tap_set_status(ULONG status)
{
	DWORD len = 0;
	bool ret;
	ret = DeviceIoControl(mFile, TAP_IOCTL_SET_MEDIA_STATUS,
				&status, sizeof (status),
				&status, sizeof (status), &len, NULL);
	if (!ret) {
		char errmsg[ERRORMSG_SIZE];
		GetErrorString(errmsg, GetLastError());
		printm("Failed: %s\n", errmsg);
	}
	return ret;
}

int initDevice()
{
	char device_path[256];
	char device_guid[0x100];
	int rc;
	HANDLE handle = NULL;

	printm("Enumerating TAP devices...\n");
	rc = get_device_guid(device_guid, sizeof device_guid, NULL, 0);
	if (rc != 0) {
		printm("Could not locate any installed TAP-WIN32 devices.");
	}

	//Open Windows TAP-Win32 adapter
	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 || handle == NULL) {
		printm("Opening TAP connection failed");
	}

	mFile = handle;
	mOverlapped.Offset = 0;
	mOverlapped.OffsetHigh = 0;
	mOverlapped.hEvent = CreateEvent(NULL, TRUE, false, NULL);
	
	//check TAP driver version against our minimum supported version
	{
    		ULONG info[3];
    		ULONG len;
    		info[0] = info[1] = info[2] = 0;
    		if (DeviceIoControl(handle, TAP_IOCTL_GET_VERSION, 
	    			&info, sizeof (info), 
	    			&info, sizeof (info), &len, NULL)) {
			printm("Driver Version %d.%d\n",
	     			(int) info[0],
	     			(int) info[1]);
      		} else {
      			if (DeviceIoControl(handle, OLD_TAP_IOCTL_GET_VERSION, 
	    			&info, sizeof (info), 
	    			&info, sizeof (info), &len, NULL)) {
			printm("Driver Version %d.%d %s.\n",
	     			(int) info[0],
	     			(int) info[1],
		     		(info[2] ? "(DEBUG) " : ""));

      			} else {
				char errmsg[ERRORMSG_SIZE];
				GetErrorString(errmsg, GetLastError());
				printm("Could not get driver version info: %s\n", errmsg);
			}
		}
    		if (!(info[0] > TAP_WIN32_MIN_MAJOR || (info[0] == TAP_WIN32_MIN_MAJOR && info[1] >= TAP_WIN32_MIN_MINOR))) {
      			printm("ERROR:  This version of PearPC requires a TAP-Win32 driver that is at least version %d.%d\n"
      						"Please install an updated version from http://prdownloads.sourceforge.net/openvpn/openvpn-2.0_beta2-install.exe\n",
			   			TAP_WIN32_MIN_MAJOR,
	   					TAP_WIN32_MIN_MINOR);
		}
  	}
  	
  	//connect our virtual cat5 cable to the TAP device
	if (!tap_set_status(TRUE)) {
		if (CloseHandle(handle) != 1) {
			printm("Error closing handle.\n");
		}
		printm("Setting Media Status to connected failed (handle is %d)\n", handle);
	}
	return 0;
}





int shutdownDevice()
{
	printm("Setting Media Status to disconnected.\n");
	if (!tap_set_status(false)) {
		printm("Error disconnecting media.\n");
	}
	printm("Closing TAP-WIN32 handle.\n");
	CloseHandle(mFile);
	mFile = INVALID_HANDLE_VALUE;
	return 0;
}


int recvPacket(void *buf, int size)
{
	if (mBuflen > size) {
		// no partial packets. drop it.
		mBuflen = 0;
		return 0;
	}
	memcpy(buf, mBuf, mBuflen);
	
	int ret = mBuflen;
	mBuflen = 0;
	return ret;
}


int waitRecvPacket()
{
	DWORD status;
	mOverlapped.Offset = 0;
	mOverlapped.OffsetHigh = 0;
	ResetEvent(mOverlapped.hEvent);
	status = ReadFile(mFile, mBuf, READ_SIZE, &mBuflen, &mOverlapped);
	if (!status) {
		DWORD e = GetLastError();
		if (e == ERROR_IO_PENDING) {
			WaitForSingleObject(mOverlapped.hEvent, INFINITE);
			if (!GetOverlappedResult(mFile, &mOverlapped, &mBuflen, FALSE)) {
				printm("You should never see this error\n");
			}
		} else {
			char errmsg[ERRORMSG_SIZE];
			GetErrorString(errmsg, e);
			printm("Bad read error: %s\n", errmsg);

			return EIO;
		}
	}
	return 0;
}

int sendPacket(void *buf, int size)
{
	DWORD written;
	BOOL ret;
	OVERLAPPED wrov = {0};
	ret = WriteFile(mFile, buf, size, &written, &wrov);

	
	if (!ret) {
		char errmsg[ERRORMSG_SIZE];
		GetErrorString(errmsg, GetLastError());
		printm("Sending of %d bytes failed (%d bytes sent): %s\n", size, written, errmsg);
	}
	return written;
}


static SDL_sem * net_sem = NULL;
static int net_readed = 0;
int net_thread(void * par)
{
		int n = 0;
    while(1)
    {
        if(SDL_SemWait(net_sem) != -1)
        {
            if( net_readed == 0)
            {
               n = waitRecvPacket();
               if(n == 0)
               {     	  	
               		net_readed = 1;
               }
             }
            SDL_SemPost(net_sem);
        }
    }
}



int
tap_open (struct net_device *net_dev)
{
	initDevice();
	static first_run = 1;
	if(first_run == 1)
	{
		first_run = 0;
		net_sem = SDL_CreateSemaphore(1);
		SDL_CreateThread(net_thread, NULL);                       
	}
	return 0;
}

int
tap_close (struct net_device *net_dev)
{
    printf("Setting Media Status to disconnected.\n");
    printf("we are not expecting this !!!\n");
    shutdownDevice();
    return 0;
}

int
tap_read (struct net_device *net_dev, void *buf, size_t count)
{
		int n = 0;
		if (SDL_SemTryWait(net_sem)==0) 
		{
       if(net_readed == 1)
				{
					n = recvPacket(buf,count);
					net_readed = 0;
				}
				SDL_SemPost(net_sem);
		}
		return n;
}

int
tap_write (struct net_device *net_dev, void *buf, size_t count)
{
	int n = sendPacket(buf, count);
	return n;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -