Tap driver basically builds in VS2012... fork of tap-windows from OpenVPN (compatible license).

This commit is contained in:
Adam Ierymenko 2013-08-23 17:39:21 -04:00
parent b6248c7cb7
commit e2effbd1ce
29 changed files with 6762 additions and 200 deletions

2
.gitignore vendored
View File

@ -16,3 +16,5 @@ mac-tap/tuntap/tap.kext
*.log
*.opensdf
*.user
/Win8Release
/vsprojects/TapDriver/Win8Release

View File

@ -3,6 +3,13 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SelfTest", "vsprojects\SelfTest\SelfTest.vcxproj", "{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TapDriver", "vsprojects\TapDriver\TapDriver.vcxproj", "{689210B1-467C-4850-BB7D-2E10D5B4A3DA}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TapDriver Package", "vsprojects\TapDriver Package\TapDriver Package.vcxproj", "{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}"
ProjectSection(ProjectDependencies) = postProject
{689210B1-467C-4850-BB7D-2E10D5B4A3DA} = {689210B1-467C-4850-BB7D-2E10D5B4A3DA}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@ -53,6 +60,102 @@ Global
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Release|Win32.Build.0 = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Release|Win32.Deploy.0 = Release|Win32
{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}.Win8 Release|x64.ActiveCfg = Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|Win32.ActiveCfg = Win7 Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|Win32.Build.0 = Win7 Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|Win32.Deploy.0 = Win7 Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|x64.ActiveCfg = Win7 Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|x64.Build.0 = Win7 Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Debug|x64.Deploy.0 = Win7 Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|Win32.ActiveCfg = Win8 Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|Win32.Build.0 = Win8 Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|Win32.Deploy.0 = Win8 Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|x64.ActiveCfg = Win8 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|x64.Build.0 = Win8 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Release|x64.Deploy.0 = Win8 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|Win32.ActiveCfg = Vista Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|Win32.Build.0 = Vista Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|Win32.Deploy.0 = Vista Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|x64.ActiveCfg = Vista Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|x64.Build.0 = Vista Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Debug|x64.Deploy.0 = Vista Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|Win32.ActiveCfg = Vista Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|Win32.Build.0 = Vista Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|Win32.Deploy.0 = Vista Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|x64.ActiveCfg = Vista Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|x64.Build.0 = Vista Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Vista Release|x64.Deploy.0 = Vista Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|Win32.ActiveCfg = Win7 Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|Win32.Build.0 = Win7 Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|Win32.Deploy.0 = Win7 Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|x64.ActiveCfg = Win7 Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|x64.Build.0 = Win7 Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Debug|x64.Deploy.0 = Win7 Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Release|Win32.ActiveCfg = Win7 Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Release|Win32.Build.0 = Win7 Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Release|Win32.Deploy.0 = Win7 Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Release|x64.ActiveCfg = Win7 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Release|x64.Build.0 = Win7 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win7 Release|x64.Deploy.0 = Win7 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|Win32.ActiveCfg = Win8 Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|Win32.Build.0 = Win8 Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|Win32.Deploy.0 = Win8 Debug|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|x64.ActiveCfg = Win8 Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|x64.Build.0 = Win8 Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Debug|x64.Deploy.0 = Win8 Debug|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|Win32.ActiveCfg = Win8 Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|Win32.Build.0 = Win8 Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|Win32.Deploy.0 = Win8 Release|Win32
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|x64.ActiveCfg = Win8 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|x64.Build.0 = Win8 Release|x64
{689210B1-467C-4850-BB7D-2E10D5B4A3DA}.Win8 Release|x64.Deploy.0 = Win8 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Debug|Win32.ActiveCfg = Win7 Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Debug|Win32.Build.0 = Win7 Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Debug|Win32.Deploy.0 = Win7 Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Debug|x64.ActiveCfg = Win7 Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Debug|x64.Build.0 = Win7 Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Debug|x64.Deploy.0 = Win7 Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Release|Win32.ActiveCfg = Win8 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Release|Win32.Build.0 = Win8 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Release|Win32.Deploy.0 = Win8 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Release|x64.ActiveCfg = Win8 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Release|x64.Build.0 = Win8 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Release|x64.Deploy.0 = Win8 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Debug|Win32.ActiveCfg = Vista Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Debug|Win32.Build.0 = Vista Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Debug|Win32.Deploy.0 = Vista Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Debug|x64.ActiveCfg = Vista Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Debug|x64.Build.0 = Vista Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Debug|x64.Deploy.0 = Vista Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Release|Win32.ActiveCfg = Vista Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Release|Win32.Build.0 = Vista Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Release|Win32.Deploy.0 = Vista Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Release|x64.ActiveCfg = Vista Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Release|x64.Build.0 = Vista Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Vista Release|x64.Deploy.0 = Vista Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Debug|Win32.ActiveCfg = Win7 Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Debug|Win32.Build.0 = Win7 Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Debug|Win32.Deploy.0 = Win7 Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Debug|x64.ActiveCfg = Win7 Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Debug|x64.Build.0 = Win7 Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Debug|x64.Deploy.0 = Win7 Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Release|Win32.ActiveCfg = Win7 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Release|Win32.Build.0 = Win7 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Release|Win32.Deploy.0 = Win7 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Release|x64.ActiveCfg = Win7 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Release|x64.Build.0 = Win7 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win7 Release|x64.Deploy.0 = Win7 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Debug|Win32.ActiveCfg = Win8 Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Debug|Win32.Build.0 = Win8 Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Debug|Win32.Deploy.0 = Win8 Debug|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Debug|x64.ActiveCfg = Win8 Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Debug|x64.Build.0 = Win8 Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Debug|x64.Deploy.0 = Win8 Debug|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Release|Win32.ActiveCfg = Win8 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Release|Win32.Build.0 = Win8 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Release|Win32.Deploy.0 = Win8 Release|Win32
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Release|x64.ActiveCfg = Win8 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Release|x64.Build.0 = Win8 Release|x64
{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}.Win8 Release|x64.Deploy.0 = Win8 Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -677,10 +677,14 @@ void EthernetTap::threadMain()
#endif // __UNIX_LIKE__ //////////////////////////////////////////////////////
#ifdef __WINDOWS__
//////////////////////////////////////////////////////////////////////////////
#include <queue>
#ifdef __WINDOWS__ ///////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <WinSock2.h>
#include <Windows.h>
#include <iphlpapi.h>
@ -691,165 +695,6 @@ void EthernetTap::threadMain()
namespace ZeroTier {
/* Background thread that handles I/O to/from all running
* EthernetTap instances using WinPcap -- this must be
* managed from a single thread because of the need to
* "reboot" npf every time a new interface is added. */
class _WinEthernetTapPcapIOThread
{
public:
_WinEthernetTapPcapIOThread()
{
scManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if (scManager == NULL)
fprintf(stderr,"ZeroTier One: WARNING: unable to OpenSCManager(), tap will have issues with new devices!\r\n");
updateSem = CreateSemaphore(NULL,0,1,NULL); // binary
run = true;
needReload = false;
thread = Thread::start(this);
}
~_WinEthernetTapPcapIOThread()
{
run = false;
needReload = false;
ReleaseSemaphore(updateSem,1,NULL);
Thread::join(thread);
CloseHandle(updateSem);
if (scManager != NULL)
CloseServiceHandle(scManager);
}
void threadMain()
throw()
{
HANDLE *objects = new HANDLE[1];
objects[0] = updateSem;
DWORD numObjects = 1;
for(;;) {
if (!run) {
delete [] objects;
return;
}
printf("waiting on: %d\r\n",(int)numObjects);
WaitForMultipleObjects(numObjects,objects,FALSE,INFINITE);
{
Mutex::Lock _l(taps_m);
for(std::list<EthernetTap *>::iterator tapptr(taps.begin());tapptr!=taps.end();++tapptr) {
EthernetTap *tap = *tapptr;
if (tap->_pcap) {
{
Mutex::Lock _l2(tap->_injectPending_m);
while (!tap->_injectPending.empty()) {
pcap_sendpacket(tap->_pcap,(const u_char *)(tap->_injectPending.front().first.data),tap->_injectPending.front().second);
tap->_injectPending.pop();
}
}
printf("dispatch: %s\r\n",tap->_myDeviceInstanceId.c_str());
pcap_dispatch(tap->_pcap,-1,&EthernetTap::_pcapHandler,(u_char *)tap);
}
}
if (needReload) {
// Close all taps and restart WinPcap driver to scan for possible new
// interfaces... yuck. This is done because WinPcap does not support
// hot plug, so if we've added a new loopback adapter it won't show
// up without this full system refresh.
needReload = false;
for(std::list<EthernetTap *>::iterator tapptr(taps.begin());tapptr!=taps.end();++tapptr) {
if ((*tapptr)->_pcap) {
pcap_close((*tapptr)->_pcap);
(*tapptr)->_pcap = (pcap_t *)0;
}
}
if (scManager != NULL) {
Thread::sleep(250);
SC_HANDLE npfService = OpenServiceA(scManager,"npf",SERVICE_ALL_ACCESS);
if (npfService != NULL) {
SERVICE_STATUS sstatus;
memset(&sstatus,0,sizeof(SERVICE_STATUS));
ControlService(npfService,SERVICE_CONTROL_STOP,&sstatus);
printf("service restart\r\n");
CloseServiceHandle(npfService);
}
Thread::sleep(250);
}
delete [] objects;
objects = new HANDLE[taps.size() + 1];
objects[0] = updateSem;
numObjects = 1;
pcap_if_t *alldevs;
char pcaperrbuf[PCAP_ERRBUF_SIZE+1];
if (pcap_findalldevs(&alldevs,pcaperrbuf) != -1) {
for(std::list<EthernetTap *>::iterator tapptr(taps.begin());tapptr!=taps.end();++tapptr) {
EthernetTap *tap = *tapptr;
pcap_if_t *mydev = (pcap_if_t *)0;
for(mydev=alldevs;(mydev);mydev=mydev->next) {
if (strstr(mydev->name,tap->_myDeviceInstanceId.c_str()))
break;
}
if (mydev) {
tap->_pcap = pcap_open_live(mydev->name,65535,1,0,pcaperrbuf);
pcap_setnonblock(tap->_pcap,1,pcaperrbuf);
if (tap->_pcap) {
printf("pcap opened: %s\r\n",mydev->name);
objects[numObjects++] = pcap_getevent(tap->_pcap);
}
} else {
tap->_pcap = (pcap_t *)0;
}
}
pcap_freealldevs(alldevs);
}
}
}
if (!run) {
delete [] objects;
return;
}
}
}
inline void addTap(EthernetTap *t)
{
Mutex::Lock _l(taps_m);
taps.push_back(t);
needReload = true;
ReleaseSemaphore(updateSem,1,NULL);
}
inline void removeTap(EthernetTap *t)
{
Mutex::Lock _l(taps_m);
for(std::list<EthernetTap *>::iterator tapptr(taps.begin());tapptr!=taps.end();++tapptr) {
if (*tapptr == t) {
taps.erase(tapptr);
break;
}
}
needReload = true;
ReleaseSemaphore(updateSem,1,NULL);
}
std::list<EthernetTap *> taps;
Mutex taps_m;
SC_HANDLE scManager;
HANDLE updateSem;
volatile bool run;
volatile bool needReload;
Thread thread;
};
static _WinEthernetTapPcapIOThread _pcapIoThread;
static Mutex _systemTapInitLock;
EthernetTap::EthernetTap(
@ -864,20 +709,20 @@ EthernetTap::EthernetTap(
_mtu(mtu),
_r(renv),
_handler(handler),
_arg(arg),
_pcap((pcap_t *)0)
_arg(arg)
{
char subkeyName[1024];
char subkeyClass[1024];
char data[1024];
char subkeyName[4096];
char subkeyClass[4096];
char data[4096];
Mutex::Lock _l(_systemTapInitLock); // only do one at a time, process-wide
Mutex::Lock _l(_systemTapInitLock); // only init one tap at a time, process-wide
HKEY nwAdapters;
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",0,KEY_READ|KEY_WRITE,&nwAdapters) != ERROR_SUCCESS)
throw std::runtime_error("unable to open registry key for network adapter enumeration");
std::set<std::string> existingDeviceInstances;
std::string mySubkeyName;
// Enumerate all Microsoft Loopback Adapter instances and look for one
// that matches our tag.
@ -913,6 +758,7 @@ EthernetTap::EthernetTap(
dataLen = sizeof(data);
if (RegGetValueA(nwAdapters,subkeyName,"NetCfgInstanceId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
_myDeviceInstanceId = instanceId;
mySubkeyName = subkeyName;
subkeyIndex = -1; // break outer loop
}
}
@ -971,6 +817,7 @@ EthernetTap::EthernetTap(
if (existingDeviceInstances.count(std::string(data,dataLen)) == 0) {
RegSetKeyValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",REG_SZ,tag,strlen(tag)+1);
_myDeviceInstanceId.assign(data,dataLen);
mySubkeyName = subkeyName;
subkeyIndex = -1; // break outer loop
}
}
@ -981,20 +828,27 @@ EthernetTap::EthernetTap(
}
}
if (_myDeviceInstanceId.length() > 0) {
char tmps[4096];
sprintf_s(tmps,"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",(unsigned int)mac.data[0],(unsigned int)mac.data[1],(unsigned int)mac.data[2],(unsigned int)mac.data[3],(unsigned int)mac.data[4],(unsigned int)mac.data[5]);
RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"NetworkAddress",REG_SZ,tmps,strlen(tmps)+1);
DWORD tmp = mtu;
RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"MTU",REG_DWORD,(LPCVOID)&tmp,sizeof(tmp));
tmp = 0;
RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"EnableDHCP",REG_DWORD,(LPCVOID)&tmp,sizeof(tmp));
RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"DriverDesc",REG_SZ,"ZeroTier One Virtual LAN",25);
}
RegCloseKey(nwAdapters);
if (_myDeviceInstanceId.length() == 0)
throw std::runtime_error("unable to create new loopback adapter for tap");
// pcap is opened and managed by the pcap I/O thread
_pcapIoThread.addTap(this);
//Thread::start(this);
}
EthernetTap::~EthernetTap()
{
_pcapIoThread.removeTap(this);
if (_pcap)
pcap_close(_pcap);
}
void EthernetTap::whack()
@ -1026,7 +880,7 @@ void EthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const
memcpy(d + 14,data,len);
}
ReleaseSemaphore(_pcapIoThread.updateSem,1,NULL);
//ReleaseSemaphore(_pcapIoThread.updateSem,1,NULL);
}
std::string EthernetTap::deviceName() const
@ -1040,13 +894,11 @@ bool EthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups)
return false;
}
void EthernetTap::_pcapHandler(u_char *user,const struct pcap_pkthdr *pkt_header,const u_char *pkt_data)
void EthernetTap::threadMain()
throw()
{
printf("got packet: %d\r\n",(int)pkt_header->len);
if (pkt_header->len > 14)
((EthernetTap *)user)->_handler(((EthernetTap *)user)->_arg,MAC(pkt_data + 6),MAC(pkt_data),Utils::ntoh(*((const uint16_t *)(pkt_data + 12))),Buffer<4096>(pkt_data + 14,pkt_header->len - 14));
}
} // namespace ZeroTier
#endif // __WINDOWS__
#endif // __WINDOWS__ ////////////////////////////////////////////////////////

View File

@ -43,33 +43,21 @@
#include "InetAddress.hpp"
#include "MAC.hpp"
#include "Mutex.hpp"
#include "Condition.hpp"
#include "MulticastGroup.hpp"
#include "Thread.hpp"
#include "Buffer.hpp"
#include "Array.hpp"
#ifdef __WINDOWS__
#include <pcap/pcap.h>
#include <pcap/bpf.h>
#include <Win32-Extensions.h>
#endif
namespace ZeroTier {
class RuntimeEnvironment;
#ifdef __WINDOWS__
class _WinEthernetTapPcapIOThread;
#endif
/**
* System ethernet tap device
*/
class EthernetTap
{
#ifdef __WINDOWS__
friend class _WinEthernetTapPcapIOThread;
#endif
public:
/**
* Construct a new TAP device
@ -189,13 +177,11 @@ public:
*/
bool updateMulticastGroups(std::set<MulticastGroup> &groups);
#ifdef __UNIX_LIKE__
/**
* Thread main method; do not call elsewhere
*/
void threadMain()
throw();
#endif
private:
const MAC _mac;
@ -217,11 +203,10 @@ private:
#endif
#ifdef __WINDOWS__
pcap_t *_pcap;
std::string _myDeviceInstanceId;
std::queue< std::pair< Array<char,ZT_IF_MTU + 32>,unsigned int > > _injectPending;
Mutex _injectPending_m;
static void _pcapHandler(u_char *user,const struct pcap_pkthdr *pkt_header,const u_char *pkt_data);
Condition _injectPending_c;
#endif
};

View File

@ -408,18 +408,19 @@ int _tmain(int argc, _TCHAR* argv[])
int main(int argc,char **argv)
#endif
{
/* For testing windows tap
///* For testing windows tap
try {
RuntimeEnvironment renv;
renv.homePath = "C:";
EthernetTap tap(&renv,"test12345",MAC(),2800,NULL,NULL);
EthernetTap tap(&renv,"test12345",MAC(0x32),2800,NULL,NULL);
Thread::sleep(100000000);
} catch (std::exception &exc) {
std::cout << exc.what() << std::endl;
return 0;
}
*/
//*/
/*
int r = 0;
_initLibCrypto();
@ -435,4 +436,5 @@ int main(int argc,char **argv)
std::cout << std::endl << "SOMETHING FAILED!" << std::endl;
return r;
*/
}

View File

@ -69,14 +69,14 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)\ext\bin\libcrypto\include;$(SolutionDir)\ext\bin\winpcap-devel\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)\ext\bin\libcrypto\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>wsock32.lib;ws2_32.lib;iphlpapi.lib;$(SolutionDir)\ext\bin\libcrypto\win32-vs2012\libeay32.lib;$(SolutionDir)\ext\bin\winpcap-devel\lib\wpcap.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>wsock32.lib;ws2_32.lib;iphlpapi.lib;$(SolutionDir)\ext\bin\libcrypto\win32-vs2012\libeay32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
</ItemDefinitionGroup>

View File

@ -0,0 +1,155 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Win8 Debug|Win32">
<Configuration>Win8 Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Win8 Release|Win32">
<Configuration>Win8 Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Win7 Debug|Win32">
<Configuration>Win7 Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Win7 Release|Win32">
<Configuration>Win7 Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Vista Debug|Win32">
<Configuration>Vista Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Vista Release|Win32">
<Configuration>Vista Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Win8 Debug|x64">
<Configuration>Win8 Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Win8 Release|x64">
<Configuration>Win8 Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Win7 Debug|x64">
<Configuration>Win7 Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Win7 Release|x64">
<Configuration>Win7 Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Vista Debug|x64">
<Configuration>Vista Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Vista Release|x64">
<Configuration>Vista Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{FDA1DD8D-1D56-4BC1-B402-FCC0B550D946}</ProjectGuid>
<TemplateGuid>{4605da2c-74a5-4865-98e1-152ef136825f}</TemplateGuid>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
<Configuration>Win8 Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
</PropertyGroup>
<PropertyGroup Label="Globals">
<RootNamespace>TapDriver_Package</RootNamespace>
<VCTargetsPath Condition="'$(VCTargetsPath11)' != '' and '$(VisualStudioVersion)' == '11.0'">$(VCTargetsPath11)</VCTargetsPath>
</PropertyGroup>
<PropertyGroup Label="PropertySheets">
<PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
<ConfigurationType>Utility</ConfigurationType>
<DriverType>Package</DriverType>
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|Win32'" Label="Configuration">
<TargetVersion>Windows8</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'" Label="Configuration">
<TargetVersion>Windows8</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win7 Debug|Win32'" Label="Configuration">
<TargetVersion>Windows7</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win7 Release|Win32'" Label="Configuration">
<TargetVersion>Windows7</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Vista Debug|Win32'" Label="Configuration">
<TargetVersion>Vista</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Vista Release|Win32'" Label="Configuration">
<TargetVersion>Vista</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|x64'" Label="Configuration">
<TargetVersion>Windows8</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Release|x64'" Label="Configuration">
<TargetVersion>Windows8</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win7 Debug|x64'" Label="Configuration">
<TargetVersion>Windows7</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win7 Release|x64'" Label="Configuration">
<TargetVersion>Windows7</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Vista Debug|x64'" Label="Configuration">
<TargetVersion>Vista</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Vista Release|x64'" Label="Configuration">
<TargetVersion>Vista</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup>
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<EnableDeployment>False</EnableDeployment>
<RemoveDriver>True</RemoveDriver>
<HardwareIdString />
<CommandLine />
<DeployFiles />
<EnableVerifier>False</EnableVerifier>
<AllDrivers>False</AllDrivers>
<VerifyProjectOutput>True</VerifyProjectOutput>
<VerifyDrivers />
<VerifyFlags>133563</VerifyFlags>
<PackageDir>$(OutDir)TapDriver Package</PackageDir>
</PropertyGroup>
<ItemDefinitionGroup>
</ItemDefinitionGroup>
<ItemGroup>
<FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TapDriver\TapDriver.vcxproj">
<Project>{689210b1-467c-4850-bb7d-2e10d5b4a3da}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Driver Files">
<UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier>
<Extensions>inf;inv;inx;mof;mc;</Extensions>
</Filter>
</ItemGroup>
</Project>

View File

@ -0,0 +1,91 @@
;
; TapDriver.inf
;
[Version]
Signature="$WINDOWS NT$"
Class=Sample ; TODO: edit Class
ClassGuid={78A1C341-4539-11d3-B88D-00C04FAD5171} ; TODO: edit ClassGuid
Provider=%ManufacturerName%
CatalogFile=TapDriver.cat
DriverVer= ; TODO: set DriverVer in stampinf property pages
[DestinationDirs]
DefaultDestDir = 12
; ================= Class section =====================
[ClassInstall32]
Addreg=SampleClassReg
[SampleClassReg]
HKR,,,0,%ClassName%
HKR,,Icon,,-5
[SourceDisksNames]
1 = %DiskName%,,,""
[SourceDisksFiles]
TapDriver.sys = 1,,
;*****************************************
; Install Section
;*****************************************
[Manufacturer]
%ManufacturerName%=Standard,NT$ARCH$
[Standard.NT$ARCH$]
%TapDriver.DeviceDesc%=TapDriver_Device, Root\TapDriver ; TODO: edit hw-id
[TapDriver_Device.NT]
CopyFiles=Drivers_Dir
[Drivers_Dir]
TapDriver.sys
;-------------- Service installation
[TapDriver_Device.NT.Services]
AddService = TapDriver,%SPSVCINST_ASSOCSERVICE%, TapDriver_Service_Inst
; -------------- TapDriver driver install sections
[TapDriver_Service_Inst]
DisplayName = %TapDriver.SVCDESC%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %12%\TapDriver.sys
LoadOrderGroup = Extended Base
;
;--- TapDriver_Device Coinstaller installation ------
;
[DestinationDirs]
TapDriver_Device_CoInstaller_CopyFiles = 11
[TapDriver_Device.NT.CoInstallers]
AddReg=TapDriver_Device_CoInstaller_AddReg
CopyFiles=TapDriver_Device_CoInstaller_CopyFiles
[TapDriver_Device_CoInstaller_AddReg]
HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller"
[TapDriver_Device_CoInstaller_CopyFiles]
WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll
[SourceDisksFiles]
WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames
[TapDriver_Device.NT.Wdf]
KmdfService = TapDriver, TapDriver_wdfsect
[TapDriver_wdfsect]
KmdfLibraryVersion = $KMDFVERSION$
[Strings]
SPSVCINST_ASSOCSERVICE= 0x00000002
ManufacturerName="" ; TODO: add ManufacturerName
ClassName="Samples" ; TODO: edit ClassName
DiskName = "TapDriver Installation Disk"
TapDriver.DeviceDesc = "TapDriver Device"
TapDriver.SVCDESC = "TapDriver Service"

View File

@ -0,0 +1,183 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Win8 Debug|Win32">
<Configuration>Win8 Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Win8 Release|Win32">
<Configuration>Win8 Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Win7 Debug|Win32">
<Configuration>Win7 Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Win7 Release|Win32">
<Configuration>Win7 Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Vista Debug|Win32">
<Configuration>Vista Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Vista Release|Win32">
<Configuration>Vista Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Win8 Debug|x64">
<Configuration>Win8 Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Win8 Release|x64">
<Configuration>Win8 Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Win7 Debug|x64">
<Configuration>Win7 Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Win7 Release|x64">
<Configuration>Win7 Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Vista Debug|x64">
<Configuration>Vista Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Vista Release|x64">
<Configuration>Vista Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{689210B1-467C-4850-BB7D-2E10D5B4A3DA}</ProjectGuid>
<TemplateGuid>{1bc93793-694f-48fe-9372-81e2b05556fd}</TemplateGuid>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
<Configuration>Win8 Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
</PropertyGroup>
<PropertyGroup Label="Globals">
<RootNamespace>TapDriver</RootNamespace>
<VCTargetsPath Condition="'$(VCTargetsPath11)' != '' and '$(VisualStudioVersion)' == '11.0'">$(VCTargetsPath11)</VCTargetsPath>
</PropertyGroup>
<PropertyGroup Label="PropertySheets">
<PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|Win32'" Label="Configuration">
<TargetVersion>Windows8</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'" Label="Configuration">
<TargetVersion>Windows8</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win7 Debug|Win32'" Label="Configuration">
<TargetVersion>Windows7</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win7 Release|Win32'" Label="Configuration">
<TargetVersion>Windows7</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Vista Debug|Win32'" Label="Configuration">
<TargetVersion>Vista</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Vista Release|Win32'" Label="Configuration">
<TargetVersion>Vista</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|x64'" Label="Configuration">
<TargetVersion>Windows8</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Release|x64'" Label="Configuration">
<TargetVersion>Windows8</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win7 Debug|x64'" Label="Configuration">
<TargetVersion>Windows7</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win7 Release|x64'" Label="Configuration">
<TargetVersion>Windows7</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Vista Debug|x64'" Label="Configuration">
<TargetVersion>Vista</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Vista Release|x64'" Label="Configuration">
<TargetVersion>Vista</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup>
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<WppEnabled>false</WppEnabled>
<WppScanConfigurationData Condition="'%(ClCompile. ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
<WppKernelMode>true</WppKernelMode>
<WarningLevel Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'">Level2</WarningLevel>
<TreatWarningAsError Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'">false</TreatWarningAsError>
</ClCompile>
<Link>
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'">C:\WinDDK\7600.16385.1\lib\wnet\i386\ndis.lib;C:\WinDDK\7600.16385.1\lib\wnet\i386\ntstrsafe.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Inf Include="TapDriver.inf" />
</ItemGroup>
<ItemGroup>
<FilesToPackage Include="$(TargetPath)" />
<FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dhcp.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="error.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="instance.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="macinfo.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="mem.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="tapdrvr.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="config.h" />
<ClInclude Include="constants.h" />
<ClInclude Include="dhcp.h" />
<ClInclude Include="endian.h" />
<ClInclude Include="error.h" />
<ClInclude Include="lock.h" />
<ClInclude Include="macinfo.h" />
<ClInclude Include="proto.h" />
<ClInclude Include="prototypes.h" />
<ClInclude Include="tap-windows.h" />
<ClInclude Include="types.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Driver Files">
<UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier>
<Extensions>inf;inv;inx;mof;mc;</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<Inf Include="TapDriver.inf">
<Filter>Driver Files</Filter>
</Inf>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dhcp.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="error.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="instance.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="macinfo.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mem.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="tapdrvr.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="constants.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="dhcp.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="endian.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="error.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="lock.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="macinfo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="proto.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="prototypes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="tap-windows.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="types.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="config.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,12 @@
#define PRODUCT_NAME "ZeroTier One Ethernet Tap"
#define PRODUCT_VERSION "1.0.0"
#define PRODUCT_VERSION_RESOURCE 1,0,0,1
#define PRODUCT_TAP_WIN_COMPONENT_ID "ztTap100"
#define PRODUCT_TAP_WIN_MAJOR 1
#define PRODUCT_TAP_WIN_MINOR 0
#define PRODUCT_TAP_WIN_PROVIDER "ZeroTier Networks"
#define PRODUCT_TAP_WIN_DEVICE_DESCRIPTION PRODUCT_NAME
#define PRODUCT_TAP_WIN_RELDATE "8/1/2013"
#define TAP_DRIVER_MAJOR_VERSION PRODUCT_TAP_WIN_MAJOR
#define TAP_DRIVER_MINOR_VERSION PRODUCT_TAP_WIN_MINOR

View File

@ -0,0 +1,52 @@
/*
* TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows.
*
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
*
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
* 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 version 2
* as published by the Free Software Foundation.
*
* 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
*/
//====================================================================
// Product and Version public settings
//====================================================================
#define PRODUCT_STRING PRODUCT_TAP_DEVICE_DESCRIPTION
#define TAP_NDIS_MAJOR_VERSION 5
#define TAP_NDIS_MINOR_VERSION 0
//===========================================================
// Driver constants
//===========================================================
#define ETHERNET_HEADER_SIZE (sizeof (ETH_HEADER))
#define ETHERNET_MTU 2800 // ZeroTier One MTU
#define ETHERNET_PACKET_SIZE (ETHERNET_MTU + ETHERNET_HEADER_SIZE)
#define DEFAULT_PACKET_LOOKAHEAD (ETHERNET_PACKET_SIZE)
#define NIC_MAX_MCAST_LIST 32 // Max length of multicast address list
#define MINIMUM_MTU 576 // USE TCP Minimum MTU
#define MAXIMUM_MTU 65536 // IP maximum MTU
#define PACKET_QUEUE_SIZE 64 // tap -> userspace queue size
#define IRP_QUEUE_SIZE 16 // max number of simultaneous i/o operations from userspace
#define INJECT_QUEUE_SIZE 16 // DHCP/ARP -> tap injection queue
#define TAP_LITTLE_ENDIAN // affects ntohs, htonl, etc. functions

599
vsprojects/TapDriver/dhcp.c Normal file
View File

@ -0,0 +1,599 @@
/*
* TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows.
*
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
*
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
* 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 version 2
* as published by the Free Software Foundation.
*
* 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
*/
//=========================
// Code to set DHCP options
//=========================
VOID
SetDHCPOpt (DHCPMsg *m, void *data, unsigned int len)
{
if (!m->overflow)
{
if (m->optlen + len <= DHCP_OPTIONS_BUFFER_SIZE)
{
if (len)
{
NdisMoveMemory (m->msg.options + m->optlen, data, len);
m->optlen += len;
}
}
else
{
m->overflow = TRUE;
}
}
}
VOID
SetDHCPOpt0 (DHCPMsg *msg, int type)
{
DHCPOPT0 opt;
opt.type = (UCHAR) type;
SetDHCPOpt (msg, &opt, sizeof (opt));
}
VOID
SetDHCPOpt8 (DHCPMsg *msg, int type, ULONG data)
{
DHCPOPT8 opt;
opt.type = (UCHAR) type;
opt.len = sizeof (opt.data);
opt.data = (UCHAR) data;
SetDHCPOpt (msg, &opt, sizeof (opt));
}
VOID
SetDHCPOpt32 (DHCPMsg *msg, int type, ULONG data)
{
DHCPOPT32 opt;
opt.type = (UCHAR) type;
opt.len = sizeof (opt.data);
opt.data = data;
SetDHCPOpt (msg, &opt, sizeof (opt));
}
//==============
// Checksum code
//==============
USHORT
ip_checksum (const UCHAR *buf, const int len_ip_header)
{
USHORT word16;
ULONG sum = 0;
int i;
// make 16 bit words out of every two adjacent 8 bit words in the packet
// and add them up
for (i = 0; i < len_ip_header - 1; i += 2) {
word16 = ((buf[i] << 8) & 0xFF00) + (buf[i+1] & 0xFF);
sum += (ULONG) word16;
}
// take only 16 bits out of the 32 bit sum and add up the carries
while (sum >> 16)
sum = (sum & 0xFFFF) + (sum >> 16);
// one's complement the result
return ((USHORT) ~sum);
}
USHORT
udp_checksum (const UCHAR *buf,
const int len_udp,
const UCHAR *src_addr,
const UCHAR *dest_addr)
{
USHORT word16;
ULONG sum = 0;
int i;
// make 16 bit words out of every two adjacent 8 bit words and
// calculate the sum of all 16 bit words
for (i = 0; i < len_udp; i += 2){
word16 = ((buf[i] << 8) & 0xFF00) + ((i + 1 < len_udp) ? (buf[i+1] & 0xFF) : 0);
sum += word16;
}
// add the UDP pseudo header which contains the IP source and destination addresses
for (i = 0; i < 4; i += 2){
word16 =((src_addr[i] << 8) & 0xFF00) + (src_addr[i+1] & 0xFF);
sum += word16;
}
for (i = 0; i < 4; i += 2){
word16 =((dest_addr[i] << 8) & 0xFF00) + (dest_addr[i+1] & 0xFF);
sum += word16;
}
// the protocol number and the length of the UDP packet
sum += (USHORT) IPPROTO_UDP + (USHORT) len_udp;
// keep only the last 16 bits of the 32 bit calculated sum and add the carries
while (sum >> 16)
sum = (sum & 0xFFFF) + (sum >> 16);
// Take the one's complement of sum
return ((USHORT) ~sum);
}
//================================
// Set IP and UDP packet checksums
//================================
VOID
SetChecksumDHCPMsg (DHCPMsg *m)
{
// Set IP checksum
m->msg.pre.ip.check = htons (ip_checksum ((UCHAR *) &m->msg.pre.ip, sizeof (IPHDR)));
// Set UDP Checksum
m->msg.pre.udp.check = htons (udp_checksum ((UCHAR *) &m->msg.pre.udp,
sizeof (UDPHDR) + sizeof (DHCP) + m->optlen,
(UCHAR *)&m->msg.pre.ip.saddr,
(UCHAR *)&m->msg.pre.ip.daddr));
}
//===================
// DHCP message tests
//===================
int
GetDHCPMessageType (const DHCP *dhcp, const int optlen)
{
const UCHAR *p = (UCHAR *) (dhcp + 1);
int i;
for (i = 0; i < optlen; ++i)
{
const UCHAR type = p[i];
const int room = optlen - i - 1;
if (type == DHCP_END) // didn't find what we were looking for
return -1;
else if (type == DHCP_PAD) // no-operation
;
else if (type == DHCP_MSG_TYPE) // what we are looking for
{
if (room >= 2)
{
if (p[i+1] == 1) // message length should be 1
return p[i+2]; // return message type
}
return -1;
}
else // some other message
{
if (room >= 1)
{
const int len = p[i+1]; // get message length
i += (len + 1); // advance to next message
}
}
}
return -1;
}
BOOLEAN
DHCPMessageOurs (const TapAdapterPointer p_Adapter,
const ETH_HEADER *eth,
const IPHDR *ip,
const UDPHDR *udp,
const DHCP *dhcp)
{
// Must be UDPv4 protocol
if (!(eth->proto == htons (ETH_P_IP) && ip->protocol == IPPROTO_UDP))
return FALSE;
// Source MAC must be our adapter
if (!MAC_EQUAL (eth->src, p_Adapter->m_MAC))
return FALSE;
// Dest MAC must be either broadcast or our virtual DHCP server
if (!(MAC_EQUAL (eth->dest, p_Adapter->m_MAC_Broadcast)
|| MAC_EQUAL (eth->dest, p_Adapter->m_dhcp_server_mac)))
return FALSE;
// Port numbers must be correct
if (!(udp->dest == htons (BOOTPS_PORT)
&& udp->source == htons (BOOTPC_PORT)))
return FALSE;
// Hardware address must be MAC addr sized
if (!(dhcp->hlen == sizeof (MACADDR)))
return FALSE;
// Hardware address must match our adapter
if (!MAC_EQUAL (eth->src, dhcp->chaddr))
return FALSE;
return TRUE;
}
//=====================================================
// Build all of DHCP packet except for DHCP options.
// Assume that *p has been zeroed before we are called.
//=====================================================
VOID
BuildDHCPPre (const TapAdapterPointer a,
DHCPPre *p,
const ETH_HEADER *eth,
const IPHDR *ip,
const UDPHDR *udp,
const DHCP *dhcp,
const int optlen,
const int type)
{
// Should we broadcast or direct to a specific MAC / IP address?
const BOOLEAN broadcast = (type == DHCPNAK
|| MAC_EQUAL (eth->dest, a->m_MAC_Broadcast));
// Build ethernet header
COPY_MAC (p->eth.src, a->m_dhcp_server_mac);
if (broadcast)
COPY_MAC (p->eth.dest, a->m_MAC_Broadcast);
else
COPY_MAC (p->eth.dest, eth->src);
p->eth.proto = htons (ETH_P_IP);
// Build IP header
p->ip.version_len = (4 << 4) | (sizeof (IPHDR) >> 2);
p->ip.tos = 0;
p->ip.tot_len = htons (sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP) + optlen);
p->ip.id = 0;
p->ip.frag_off = 0;
p->ip.ttl = 16;
p->ip.protocol = IPPROTO_UDP;
p->ip.check = 0;
p->ip.saddr = a->m_dhcp_server_ip;
if (broadcast)
p->ip.daddr = ~0;
else
p->ip.daddr = a->m_dhcp_addr;
// Build UDP header
p->udp.source = htons (BOOTPS_PORT);
p->udp.dest = htons (BOOTPC_PORT);
p->udp.len = htons (sizeof (UDPHDR) + sizeof (DHCP) + optlen);
p->udp.check = 0;
// Build DHCP response
p->dhcp.op = BOOTREPLY;
p->dhcp.htype = 1;
p->dhcp.hlen = sizeof (MACADDR);
p->dhcp.hops = 0;
p->dhcp.xid = dhcp->xid;
p->dhcp.secs = 0;
p->dhcp.flags = 0;
p->dhcp.ciaddr = 0;
if (type == DHCPNAK)
p->dhcp.yiaddr = 0;
else
p->dhcp.yiaddr = a->m_dhcp_addr;
p->dhcp.siaddr = a->m_dhcp_server_ip;
p->dhcp.giaddr = 0;
COPY_MAC (p->dhcp.chaddr, eth->src);
p->dhcp.magic = htonl (0x63825363);
}
//=============================
// Build specific DHCP messages
//=============================
VOID
SendDHCPMsg (const TapAdapterPointer a,
const int type,
const ETH_HEADER *eth,
const IPHDR *ip,
const UDPHDR *udp,
const DHCP *dhcp)
{
DHCPMsg *pkt;
if (!(type == DHCPOFFER || type == DHCPACK || type == DHCPNAK))
{
DEBUGP (("[TAP] SendDHCPMsg: Bad DHCP type: %d\n", type));
return;
}
pkt = (DHCPMsg *) MemAlloc (sizeof (DHCPMsg), TRUE);
if (pkt)
{
//-----------------------
// Build DHCP options
//-----------------------
// Message Type
SetDHCPOpt8 (pkt, DHCP_MSG_TYPE, type);
// Server ID
SetDHCPOpt32 (pkt, DHCP_SERVER_ID, a->m_dhcp_server_ip);
if (type == DHCPOFFER || type == DHCPACK)
{
// Lease Time
SetDHCPOpt32 (pkt, DHCP_LEASE_TIME, htonl (a->m_dhcp_lease_time));
// Netmask
SetDHCPOpt32 (pkt, DHCP_NETMASK, a->m_dhcp_netmask);
// Other user-defined options
SetDHCPOpt (pkt,
a->m_dhcp_user_supplied_options_buffer,
a->m_dhcp_user_supplied_options_buffer_len);
}
// End
SetDHCPOpt0 (pkt, DHCP_END);
if (!DHCPMSG_OVERFLOW (pkt))
{
// The initial part of the DHCP message (not including options) gets built here
BuildDHCPPre (a,
&pkt->msg.pre,
eth,
ip,
udp,
dhcp,
DHCPMSG_LEN_OPT (pkt),
type);
SetChecksumDHCPMsg (pkt);
DUMP_PACKET ("DHCPMsg",
DHCPMSG_BUF (pkt),
DHCPMSG_LEN_FULL (pkt));
// Return DHCP response to kernel
InjectPacketDeferred (a,
DHCPMSG_BUF (pkt),
DHCPMSG_LEN_FULL (pkt));
}
else
{
DEBUGP (("[TAP] SendDHCPMsg: DHCP buffer overflow\n"));
}
MemFree (pkt, sizeof (DHCPMsg));
}
}
//===================================================================
// Handle a BOOTPS packet produced by the local system to
// resolve the address/netmask of this adapter.
// If we are in TAP_WIN_IOCTL_CONFIG_DHCP_MASQ mode, reply
// to the message. Return TRUE if we processed the passed
// message, so that downstream stages can ignore it.
//===================================================================
BOOLEAN
ProcessDHCP (TapAdapterPointer p_Adapter,
const ETH_HEADER *eth,
const IPHDR *ip,
const UDPHDR *udp,
const DHCP *dhcp,
int optlen)
{
int msg_type;
// Sanity check IP header
if (!(ntohs (ip->tot_len) == sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP) + optlen
&& (ntohs (ip->frag_off) & IP_OFFMASK) == 0))
return TRUE;
// Does this message belong to us?
if (!DHCPMessageOurs (p_Adapter, eth, ip, udp, dhcp))
return FALSE;
msg_type = GetDHCPMessageType (dhcp, optlen);
// Drop non-BOOTREQUEST messages
if (dhcp->op != BOOTREQUEST)
return TRUE;
// Drop any messages except DHCPDISCOVER or DHCPREQUEST
if (!(msg_type == DHCPDISCOVER || msg_type == DHCPREQUEST))
return TRUE;
// Should we reply with DHCPOFFER, DHCPACK, or DHCPNAK?
if (msg_type == DHCPREQUEST
&& ((dhcp->ciaddr && dhcp->ciaddr != p_Adapter->m_dhcp_addr)
|| !p_Adapter->m_dhcp_received_discover
|| p_Adapter->m_dhcp_bad_requests >= BAD_DHCPREQUEST_NAK_THRESHOLD))
SendDHCPMsg (p_Adapter,
DHCPNAK,
eth, ip, udp, dhcp);
else
SendDHCPMsg (p_Adapter,
(msg_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK),
eth, ip, udp, dhcp);
// Remember if we received a DHCPDISCOVER
if (msg_type == DHCPDISCOVER)
p_Adapter->m_dhcp_received_discover = TRUE;
// Is this a bad DHCPREQUEST?
if (msg_type == DHCPREQUEST && dhcp->ciaddr && dhcp->ciaddr != p_Adapter->m_dhcp_addr)
++p_Adapter->m_dhcp_bad_requests;
return TRUE;
}
#if DBG
const char *
message_op_text (int op)
{
switch (op)
{
case BOOTREQUEST:
return "BOOTREQUEST";
case BOOTREPLY:
return "BOOTREPLY";
default:
return "???";
}
}
const char *
message_type_text (int type)
{
switch (type)
{
case DHCPDISCOVER:
return "DHCPDISCOVER";
case DHCPOFFER:
return "DHCPOFFER";
case DHCPREQUEST:
return "DHCPREQUEST";
case DHCPDECLINE:
return "DHCPDECLINE";
case DHCPACK:
return "DHCPACK";
case DHCPNAK:
return "DHCPNAK";
case DHCPRELEASE:
return "DHCPRELEASE";
case DHCPINFORM:
return "DHCPINFORM";
default:
return "???";
}
}
const char *
port_name (int port)
{
switch (port)
{
case BOOTPS_PORT:
return "BOOTPS";
case BOOTPC_PORT:
return "BOOTPC";
default:
return "unknown";
}
}
VOID
DumpDHCP (const ETH_HEADER *eth,
const IPHDR *ip,
const UDPHDR *udp,
const DHCP *dhcp,
const int optlen)
{
DEBUGP ((" %s", message_op_text (dhcp->op)));
DEBUGP ((" %s ", message_type_text (GetDHCPMessageType (dhcp, optlen))));
PrIP (ip->saddr);
DEBUGP ((":%s[", port_name (ntohs (udp->source))));
PrMac (eth->src);
DEBUGP (("] -> "));
PrIP (ip->daddr);
DEBUGP ((":%s[", port_name (ntohs (udp->dest))));
PrMac (eth->dest);
DEBUGP (("]"));
if (dhcp->ciaddr)
{
DEBUGP ((" ci="));
PrIP (dhcp->ciaddr);
}
if (dhcp->yiaddr)
{
DEBUGP ((" yi="));
PrIP (dhcp->yiaddr);
}
if (dhcp->siaddr)
{
DEBUGP ((" si="));
PrIP (dhcp->siaddr);
}
if (dhcp->hlen == sizeof (MACADDR))
{
DEBUGP ((" ch="));
PrMac (dhcp->chaddr);
}
DEBUGP ((" xid=0x%08x", ntohl (dhcp->xid)));
if (ntohl (dhcp->magic) != 0x63825363)
DEBUGP ((" ma=0x%08x", ntohl (dhcp->magic)));
if (dhcp->htype != 1)
DEBUGP ((" htype=%d", dhcp->htype));
if (dhcp->hops)
DEBUGP ((" hops=%d", dhcp->hops));
if (ntohs (dhcp->secs))
DEBUGP ((" secs=%d", ntohs (dhcp->secs)));
if (ntohs (dhcp->flags))
DEBUGP ((" flags=0x%04x", ntohs (dhcp->flags)));
// extra stuff
if (ip->version_len != 0x45)
DEBUGP ((" vl=0x%02x", ip->version_len));
if (ntohs (ip->tot_len) != sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP) + optlen)
DEBUGP ((" tl=%d", ntohs (ip->tot_len)));
if (ntohs (udp->len) != sizeof (UDPHDR) + sizeof (DHCP) + optlen)
DEBUGP ((" ul=%d", ntohs (udp->len)));
if (ip->tos)
DEBUGP ((" tos=0x%02x", ip->tos));
if (ntohs (ip->id))
DEBUGP ((" id=0x%04x", ntohs (ip->id)));
if (ntohs (ip->frag_off))
DEBUGP ((" frag_off=0x%04x", ntohs (ip->frag_off)));
DEBUGP ((" ttl=%d", ip->ttl));
DEBUGP ((" ic=0x%04x [0x%04x]", ntohs (ip->check),
ip_checksum ((UCHAR*)ip, sizeof (IPHDR))));
DEBUGP ((" uc=0x%04x [0x%04x/%d]", ntohs (udp->check),
udp_checksum ((UCHAR *) udp,
sizeof (UDPHDR) + sizeof (DHCP) + optlen,
(UCHAR *) &ip->saddr,
(UCHAR *) &ip->daddr),
optlen));
// Options
{
const UCHAR *opt = (UCHAR *) (dhcp + 1);
int i;
DEBUGP ((" OPT"));
for (i = 0; i < optlen; ++i)
{
const UCHAR data = opt[i];
DEBUGP ((".%d", data));
}
}
}
#endif /* DBG */

164
vsprojects/TapDriver/dhcp.h Normal file
View File

@ -0,0 +1,164 @@
/*
* TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows.
*
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
*
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
* 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 version 2
* as published by the Free Software Foundation.
*
* 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
*/
#pragma pack(1)
//===================================================
// How many bad DHCPREQUESTs do we receive before we
// return a NAK?
//
// A bad DHCPREQUEST is defined to be one where the
// requestor doesn't know its IP address.
//===================================================
#define BAD_DHCPREQUEST_NAK_THRESHOLD 3
//==============================================
// Maximum number of DHCP options bytes supplied
//==============================================
#define DHCP_USER_SUPPLIED_OPTIONS_BUFFER_SIZE 256
#define DHCP_OPTIONS_BUFFER_SIZE 256
//===================================
// UDP port numbers of DHCP messages.
//===================================
#define BOOTPS_PORT 67
#define BOOTPC_PORT 68
//===========================
// The DHCP message structure
//===========================
typedef struct {
# define BOOTREQUEST 1
# define BOOTREPLY 2
UCHAR op; /* message op */
UCHAR htype; /* hardware address type (e.g. '1' = 10Mb Ethernet) */
UCHAR hlen; /* hardware address length (e.g. '6' for 10Mb Ethernet) */
UCHAR hops; /* client sets to 0, may be used by relay agents */
ULONG xid; /* transaction ID, chosen by client */
USHORT secs; /* seconds since request process began, set by client */
USHORT flags;
ULONG ciaddr; /* client IP address, client sets if known */
ULONG yiaddr; /* 'your' IP address -- server's response to client */
ULONG siaddr; /* server IP address */
ULONG giaddr; /* relay agent IP address */
UCHAR chaddr[16]; /* client hardware address */
UCHAR sname[64]; /* optional server host name */
UCHAR file[128]; /* boot file name */
ULONG magic; /* must be 0x63825363 (network order) */
} DHCP;
typedef struct {
ETH_HEADER eth;
IPHDR ip;
UDPHDR udp;
DHCP dhcp;
} DHCPPre;
typedef struct {
DHCPPre pre;
UCHAR options[DHCP_OPTIONS_BUFFER_SIZE];
} DHCPFull;
typedef struct {
unsigned int optlen;
BOOLEAN overflow;
DHCPFull msg;
} DHCPMsg;
//===================
// Macros for DHCPMSG
//===================
#define DHCPMSG_LEN_BASE(p) (sizeof (DHCPPre))
#define DHCPMSG_LEN_OPT(p) ((p)->optlen)
#define DHCPMSG_LEN_FULL(p) (DHCPMSG_LEN_BASE(p) + DHCPMSG_LEN_OPT(p))
#define DHCPMSG_BUF(p) ((UCHAR*) &(p)->msg)
#define DHCPMSG_OVERFLOW(p) ((p)->overflow)
//========================================
// structs to hold individual DHCP options
//========================================
typedef struct {
UCHAR type;
} DHCPOPT0;
typedef struct {
UCHAR type;
UCHAR len;
UCHAR data;
} DHCPOPT8;
typedef struct {
UCHAR type;
UCHAR len;
ULONG data;
} DHCPOPT32;
#pragma pack()
//==================
// DHCP Option types
//==================
#define DHCP_MSG_TYPE 53 /* message type (u8) */
#define DHCP_PARM_REQ 55 /* parameter request list: c1 (u8), ... */
#define DHCP_CLIENT_ID 61 /* client ID: type (u8), i1 (u8), ... */
#define DHCP_IP 50 /* requested IP addr (u32) */
#define DHCP_NETMASK 1 /* subnet mask (u32) */
#define DHCP_LEASE_TIME 51 /* lease time sec (u32) */
#define DHCP_RENEW_TIME 58 /* renewal time sec (u32) */
#define DHCP_REBIND_TIME 59 /* rebind time sec (u32) */
#define DHCP_SERVER_ID 54 /* server ID: IP addr (u32) */
#define DHCP_PAD 0
#define DHCP_END 255
//====================
// DHCP Messages types
//====================
#define DHCPDISCOVER 1
#define DHCPOFFER 2
#define DHCPREQUEST 3
#define DHCPDECLINE 4
#define DHCPACK 5
#define DHCPNAK 6
#define DHCPRELEASE 7
#define DHCPINFORM 8
#if DBG
VOID
DumpDHCP (const ETH_HEADER *eth,
const IPHDR *ip,
const UDPHDR *udp,
const DHCP *dhcp,
const int optlen);
#endif

View File

@ -0,0 +1,35 @@
/*
* TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows.
*
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
*
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
* 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 version 2
* as published by the Free Software Foundation.
*
* 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
*/
#ifdef TAP_LITTLE_ENDIAN
#define ntohs(x) RtlUshortByteSwap(x)
#define htons(x) RtlUshortByteSwap(x)
#define ntohl(x) RtlUlongByteSwap(x)
#define htonl(x) RtlUlongByteSwap(x)
#else
#define ntohs(x) ((USHORT)(x))
#define htons(x) ((USHORT)(x))
#define ntohl(x) ((ULONG)(x))
#define htonl(x) ((ULONG)(x))
#endif

View File

@ -0,0 +1,385 @@
/*
* TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows.
*
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
*
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
* 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 version 2
* as published by the Free Software Foundation.
*
* 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
*/
//-----------------
// DEBUGGING OUTPUT
//-----------------
const char *g_LastErrorFilename;
int g_LastErrorLineNumber;
#if DBG
DebugOutput g_Debug;
BOOLEAN
NewlineExists (const char *str, int len)
{
while (len-- > 0)
{
const char c = *str++;
if (c == '\n')
return TRUE;
else if (c == '\0')
break;
}
return FALSE;
}
VOID
MyDebugInit (unsigned int bufsiz)
{
NdisZeroMemory (&g_Debug, sizeof (g_Debug));
g_Debug.text = (char *) MemAlloc (bufsiz, FALSE);
if (g_Debug.text)
g_Debug.capacity = bufsiz;
}
VOID
MyDebugFree ()
{
if (g_Debug.text)
MemFree (g_Debug.text, g_Debug.capacity);
NdisZeroMemory (&g_Debug, sizeof (g_Debug));
}
VOID
MyDebugPrint (const unsigned char* format, ...)
{
if (g_Debug.text && g_Debug.capacity > 0 && CAN_WE_PRINT)
{
BOOLEAN owned;
ACQUIRE_MUTEX_ADAPTIVE (&g_Debug.lock, owned);
if (owned)
{
const int remaining = (int)g_Debug.capacity - (int)g_Debug.out;
if (remaining > 0)
{
va_list args;
NTSTATUS status;
char *end;
#ifdef DBG_PRINT
va_start (args, format);
vDbgPrintEx (DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, format, args);
va_end (args);
#endif
va_start (args, format);
status = RtlStringCchVPrintfExA (g_Debug.text + g_Debug.out,
remaining,
&end,
NULL,
STRSAFE_NO_TRUNCATION | STRSAFE_IGNORE_NULLS,
format,
args);
va_end (args);
va_start (args, format);
vDbgPrintEx(DPFLTR_IHVDRIVER_ID , 1, format, args);
va_end (args);
if (status == STATUS_SUCCESS)
g_Debug.out = (unsigned int) (end - g_Debug.text);
else
g_Debug.error = TRUE;
}
else
g_Debug.error = TRUE;
RELEASE_MUTEX (&g_Debug.lock);
}
else
g_Debug.error = TRUE;
}
}
BOOLEAN
GetDebugLine (char *buf, const int len)
{
static const char *truncated = "[OUTPUT TRUNCATED]\n";
BOOLEAN ret = FALSE;
NdisZeroMemory (buf, len);
if (g_Debug.text && g_Debug.capacity > 0)
{
BOOLEAN owned;
ACQUIRE_MUTEX_ADAPTIVE (&g_Debug.lock, owned);
if (owned)
{
int i = 0;
if (g_Debug.error || NewlineExists (g_Debug.text + g_Debug.in, (int)g_Debug.out - (int)g_Debug.in))
{
while (i < (len - 1) && g_Debug.in < g_Debug.out)
{
const char c = g_Debug.text[g_Debug.in++];
if (c == '\n')
break;
buf[i++] = c;
}
if (i < len)
buf[i] = '\0';
}
if (!i)
{
if (g_Debug.in == g_Debug.out)
{
g_Debug.in = g_Debug.out = 0;
if (g_Debug.error)
{
const unsigned int tlen = strlen (truncated);
if (tlen < g_Debug.capacity)
{
NdisMoveMemory (g_Debug.text, truncated, tlen+1);
g_Debug.out = tlen;
}
g_Debug.error = FALSE;
}
}
}
else
ret = TRUE;
RELEASE_MUTEX (&g_Debug.lock);
}
}
return ret;
}
VOID
MyAssert (const unsigned char *file, int line)
{
DEBUGP (("MYASSERT failed %s/%d\n", file, line));
KeBugCheckEx (0x0F00BABA,
(ULONG_PTR) line,
(ULONG_PTR) 0,
(ULONG_PTR) 0,
(ULONG_PTR) 0);
}
VOID
PrMac (const MACADDR mac)
{
DEBUGP (("%x:%x:%x:%x:%x:%x",
mac[0], mac[1], mac[2],
mac[3], mac[4], mac[5]));
}
VOID
PrIP (IPADDR ip_addr)
{
const unsigned char *ip = (const unsigned char *) &ip_addr;
DEBUGP (("%d.%d.%d.%d",
ip[0], ip[1], ip[2], ip[3]));
}
const char *
PrIPProto (int proto)
{
switch (proto)
{
case IPPROTO_UDP:
return "UDP";
case IPPROTO_TCP:
return "TCP";
case IPPROTO_ICMP:
return "ICMP";
case IPPROTO_IGMP:
return "IGMP";
default:
return "???";
}
}
VOID
DumpARP (const char *prefix, const ARP_PACKET *arp)
{
DEBUGP (("%s ARP src=", prefix));
PrMac (arp->m_MAC_Source);
DEBUGP ((" dest="));
PrMac (arp->m_MAC_Destination);
DEBUGP ((" OP=0x%04x",
(int)ntohs(arp->m_ARP_Operation)));
DEBUGP ((" M=0x%04x(%d)",
(int)ntohs(arp->m_MAC_AddressType),
(int)arp->m_MAC_AddressSize));
DEBUGP ((" P=0x%04x(%d)",
(int)ntohs(arp->m_PROTO_AddressType),
(int)arp->m_PROTO_AddressSize));
DEBUGP ((" MacSrc="));
PrMac (arp->m_ARP_MAC_Source);
DEBUGP ((" MacDest="));
PrMac (arp->m_ARP_MAC_Destination);
DEBUGP ((" IPSrc="));
PrIP (arp->m_ARP_IP_Source);
DEBUGP ((" IPDest="));
PrIP (arp->m_ARP_IP_Destination);
DEBUGP (("\n"));
}
struct ethpayload {
ETH_HEADER eth;
UCHAR payload[DEFAULT_PACKET_LOOKAHEAD];
};
VOID
DumpPacket2 (const char *prefix,
const ETH_HEADER *eth,
const unsigned char *data,
unsigned int len)
{
struct ethpayload *ep = (struct ethpayload *) MemAlloc (sizeof (struct ethpayload), TRUE);
if (ep)
{
if (len > DEFAULT_PACKET_LOOKAHEAD)
len = DEFAULT_PACKET_LOOKAHEAD;
ep->eth = *eth;
NdisMoveMemory (ep->payload, data, len);
DumpPacket (prefix, (unsigned char *) ep, sizeof (ETH_HEADER) + len);
MemFree (ep, sizeof (struct ethpayload));
}
}
VOID
DumpPacket (const char *prefix,
const unsigned char *data,
unsigned int len)
{
const ETH_HEADER *eth = (const ETH_HEADER *) data;
const IPHDR *ip = (const IPHDR *) (data + sizeof (ETH_HEADER));
if (len < sizeof (ETH_HEADER))
{
DEBUGP (("%s TRUNCATED PACKET LEN=%d\n", prefix, len));
return;
}
// ARP Packet?
if (len >= sizeof (ARP_PACKET) && eth->proto == htons (ETH_P_ARP))
{
DumpARP (prefix, (const ARP_PACKET *) data);
return;
}
// IPv4 packet?
if (len >= (sizeof (IPHDR) + sizeof (ETH_HEADER))
&& eth->proto == htons (ETH_P_IP)
&& IPH_GET_VER (ip->version_len) == 4)
{
const int hlen = IPH_GET_LEN (ip->version_len);
const int blen = len - sizeof (ETH_HEADER);
BOOLEAN did = FALSE;
DEBUGP (("%s IPv4 %s[%d]", prefix, PrIPProto (ip->protocol), len));
if (!(ntohs (ip->tot_len) == blen && hlen <= blen))
{
DEBUGP ((" XXX"));
return;
}
// TCP packet?
if (ip->protocol == IPPROTO_TCP
&& blen - hlen >= (sizeof (TCPHDR)))
{
const TCPHDR *tcp = (TCPHDR *) (data + sizeof (ETH_HEADER) + hlen);
DEBUGP ((" "));
PrIP (ip->saddr);
DEBUGP ((":%d", ntohs (tcp->source)));
DEBUGP ((" -> "));
PrIP (ip->daddr);
DEBUGP ((":%d", ntohs (tcp->dest)));
did = TRUE;
}
// UDP packet?
else if ((ntohs (ip->frag_off) & IP_OFFMASK) == 0
&& ip->protocol == IPPROTO_UDP
&& blen - hlen >= (sizeof (UDPHDR)))
{
const UDPHDR *udp = (UDPHDR *) (data + sizeof (ETH_HEADER) + hlen);
// DHCP packet?
if ((udp->dest == htons (BOOTPC_PORT) || udp->dest == htons (BOOTPS_PORT))
&& blen - hlen >= (sizeof (UDPHDR) + sizeof (DHCP)))
{
const DHCP *dhcp = (DHCP *) (data
+ hlen
+ sizeof (ETH_HEADER)
+ sizeof (UDPHDR));
int optlen = len
- sizeof (ETH_HEADER)
- hlen
- sizeof (UDPHDR)
- sizeof (DHCP);
if (optlen < 0)
optlen = 0;
DumpDHCP (eth, ip, udp, dhcp, optlen);
did = TRUE;
}
if (!did)
{
DEBUGP ((" "));
PrIP (ip->saddr);
DEBUGP ((":%d", ntohs (udp->source)));
DEBUGP ((" -> "));
PrIP (ip->daddr);
DEBUGP ((":%d", ntohs (udp->dest)));
did = TRUE;
}
}
if (!did)
{
DEBUGP ((" ipproto=%d ", ip->protocol));
PrIP (ip->saddr);
DEBUGP ((" -> "));
PrIP (ip->daddr);
}
DEBUGP (("\n"));
return;
}
{
DEBUGP (("%s ??? src=", prefix));
PrMac (eth->src);
DEBUGP ((" dest="));
PrMac (eth->dest);
DEBUGP ((" proto=0x%04x len=%d\n",
(int) ntohs(eth->proto),
len));
}
}
#endif

View File

@ -0,0 +1,88 @@
/*
* TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows.
*
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
*
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
* 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 version 2
* as published by the Free Software Foundation.
*
* 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
*/
//-----------------
// DEBUGGING OUTPUT
//-----------------
#define NOTE_ERROR() \
{ \
g_LastErrorFilename = __FILE__; \
g_LastErrorLineNumber = __LINE__; \
}
#if DBG
typedef struct {
unsigned int in;
unsigned int out;
unsigned int capacity;
char *text;
BOOLEAN error;
MUTEX lock;
} DebugOutput;
VOID MyDebugPrint (const unsigned char* format, ...);
VOID MyAssert (const unsigned char *file, int line);
VOID DumpPacket (const char *prefix,
const unsigned char *data,
unsigned int len);
VOID DumpPacket2 (const char *prefix,
const ETH_HEADER *eth,
const unsigned char *data,
unsigned int len);
#define CAN_WE_PRINT (DEBUGP_AT_DISPATCH || KeGetCurrentIrql () < DISPATCH_LEVEL)
#if ALSO_DBGPRINT
#define DEBUGP(fmt) { MyDebugPrint fmt; if (CAN_WE_PRINT) DbgPrint fmt; }
#else
#define DEBUGP(fmt) { MyDebugPrint fmt; }
#endif
#define MYASSERT(exp) \
{ \
if (!(exp)) \
{ \
MyAssert(__FILE__, __LINE__); \
} \
}
#define DUMP_PACKET(prefix, data, len) \
DumpPacket (prefix, data, len)
#define DUMP_PACKET2(prefix, eth, data, len) \
DumpPacket2 (prefix, eth, data, len)
#else
#define DEBUGP(fmt)
#define MYASSERT(exp)
#define DUMP_PACKET(prefix, data, len)
#define DUMP_PACKET2(prefix, eth, data, len)
#endif

View File

@ -0,0 +1,241 @@
/*
* TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows.
*
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
*
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
* 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 version 2
* as published by the Free Software Foundation.
*
* 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
*/
#define INSTANCE_KEY(a) ((PVOID)((a)->m_Extension.m_TapDevice))
#define N_INSTANCE_BUCKETS 256
typedef struct _INSTANCE {
struct _INSTANCE *next;
TapAdapterPointer m_Adapter;
} INSTANCE;
typedef struct {
INSTANCE *list;
MUTEX lock;
} INSTANCE_BUCKET;
typedef struct {
INSTANCE_BUCKET buckets[N_INSTANCE_BUCKETS];
} INSTANCE_HASH;
INSTANCE_HASH *g_InstanceHash = NULL;
// must return a hash >= 0 and < N_INSTANCE_BUCKETS
int
InstanceHashValue (PVOID addr)
{
UCHAR *p = (UCHAR *) &addr;
if (sizeof (addr) == 4)
return p[0] ^ p[1] ^ p[2] ^ p[3];
else if (sizeof (addr) == 8)
return p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4] ^ p[5] ^ p[6] ^ p[7];
else
{
MYASSERT (0);
}
}
BOOLEAN
InitInstanceList (VOID)
{
MYASSERT (g_InstanceHash == NULL);
g_InstanceHash = MemAlloc (sizeof (INSTANCE_HASH), TRUE);
if (g_InstanceHash)
{
int i;
for (i = 0; i < N_INSTANCE_BUCKETS; ++i)
INIT_MUTEX (&g_InstanceHash->buckets[i].lock);
return TRUE;
}
else
return FALSE;
}
int
NInstances (VOID)
{
int i, n = 0;
if (g_InstanceHash)
{
for (i = 0; i < N_INSTANCE_BUCKETS; ++i)
{
BOOLEAN got_lock;
INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[i];
ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
if (got_lock)
{
INSTANCE *current;
for (current = ib->list; current != NULL; current = current->next)
++n;
RELEASE_MUTEX (&ib->lock);
}
else
return -1;
}
}
return n;
}
int
InstanceMaxBucketSize (VOID)
{
int i, n = 0;
if (g_InstanceHash)
{
for (i = 0; i < N_INSTANCE_BUCKETS; ++i)
{
BOOLEAN got_lock;
int bucket_size = 0;
INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[i];
ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
if (got_lock)
{
INSTANCE *current;
for (current = ib->list; current != NULL; current = current->next)
++bucket_size;
if (bucket_size > n)
n = bucket_size;
RELEASE_MUTEX (&ib->lock);
}
else
return -1;
}
}
return n;
}
VOID
FreeInstanceList (VOID)
{
if (g_InstanceHash)
{
MYASSERT (NInstances() == 0);
MemFree (g_InstanceHash, sizeof (INSTANCE_HASH));
g_InstanceHash = NULL;
}
}
BOOLEAN
AddAdapterToInstanceList (TapAdapterPointer p_Adapter)
{
BOOLEAN got_lock;
BOOLEAN ret = FALSE;
const int hash = InstanceHashValue(INSTANCE_KEY(p_Adapter));
INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[hash];
DEBUGP (("[TAP] AddAdapterToInstanceList hash=%d\n", hash));
ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
if (got_lock)
{
INSTANCE *i = MemAlloc (sizeof (INSTANCE), FALSE);
if (i)
{
MYASSERT (p_Adapter);
i->m_Adapter = p_Adapter;
i->next = ib->list;
ib->list = i;
ret = TRUE;
}
RELEASE_MUTEX (&ib->lock);
}
return ret;
}
BOOLEAN
RemoveAdapterFromInstanceList (TapAdapterPointer p_Adapter)
{
BOOLEAN got_lock;
BOOLEAN ret = FALSE;
INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[InstanceHashValue(INSTANCE_KEY(p_Adapter))];
ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
if (got_lock)
{
INSTANCE *current, *prev=NULL;
for (current = ib->list; current != NULL; current = current->next)
{
if (current->m_Adapter == p_Adapter) // found match
{
if (prev)
prev->next = current->next;
else
ib->list = current->next;
MemFree (current->m_Adapter, sizeof (TapAdapter));
MemFree (current, sizeof (INSTANCE));
ret = TRUE;
break;
}
prev = current;
}
RELEASE_MUTEX (&ib->lock);
}
return ret;
}
TapAdapterPointer
LookupAdapterInInstanceList (PDEVICE_OBJECT p_DeviceObject)
{
BOOLEAN got_lock;
TapAdapterPointer ret = NULL;
INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[InstanceHashValue((PVOID)p_DeviceObject)];
ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
if (got_lock)
{
INSTANCE *current, *prev=NULL;
for (current = ib->list; current != NULL; current = current->next)
{
if (p_DeviceObject == INSTANCE_KEY (current->m_Adapter)) // found match
{
// move it to head of list
if (prev)
{
prev->next = current->next;
current->next = ib->list;
ib->list = current;
}
ret = ib->list->m_Adapter;
break;
}
prev = current;
}
RELEASE_MUTEX (&ib->lock);
}
return ret;
}

View File

@ -0,0 +1,75 @@
/*
* TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows.
*
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
*
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
* 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 version 2
* as published by the Free Software Foundation.
*
* 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
*/
typedef struct
{
volatile long count;
} MUTEX;
#define MUTEX_SLEEP_TIME 10000 // microseconds
#define INIT_MUTEX(m) { (m)->count = 0; }
#define ACQUIRE_MUTEX_BLOCKING(m) \
{ \
while (NdisInterlockedIncrement (&((m)->count)) != 1) \
{ \
NdisInterlockedDecrement(&((m)->count)); \
NdisMSleep(MUTEX_SLEEP_TIME); \
} \
}
#define RELEASE_MUTEX(m) \
{ \
NdisInterlockedDecrement(&((m)->count)); \
}
#define ACQUIRE_MUTEX_NONBLOCKING(m, result) \
{ \
if (NdisInterlockedIncrement (&((m)->count)) != 1) \
{ \
NdisInterlockedDecrement(&((m)->count)); \
result = FALSE; \
} \
else \
{ \
result = TRUE; \
} \
}
#define ACQUIRE_MUTEX_ADAPTIVE(m, result) \
{ \
result = TRUE; \
while (NdisInterlockedIncrement (&((m)->count)) != 1) \
{ \
NdisInterlockedDecrement(&((m)->count)); \
if (KeGetCurrentIrql () < DISPATCH_LEVEL) \
NdisMSleep(MUTEX_SLEEP_TIME); \
else \
{ \
result = FALSE; \
break; \
} \
} \
}

View File

@ -0,0 +1,154 @@
/*
* TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows.
*
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
*
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
* 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 version 2
* as published by the Free Software Foundation.
*
* 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 "macinfo.h"
int
HexStringToDecimalInt (const int p_Character)
{
int l_Value = 0;
if (p_Character >= 'A' && p_Character <= 'F')
l_Value = (p_Character - 'A') + 10;
else if (p_Character >= 'a' && p_Character <= 'f')
l_Value = (p_Character - 'a') + 10;
else if (p_Character >= '0' && p_Character <= '9')
l_Value = p_Character - '0';
return l_Value;
}
BOOLEAN
ParseMAC (MACADDR dest, const char *src)
{
int c;
int mac_index = 0;
BOOLEAN high_digit = FALSE;
int delim_action = 1;
MYASSERT (src);
MYASSERT (dest);
CLEAR_MAC (dest);
while (c = *src++)
{
if (IsMacDelimiter (c))
{
mac_index += delim_action;
high_digit = FALSE;
delim_action = 1;
}
else if (IsHexDigit (c))
{
const int digit = HexStringToDecimalInt (c);
if (mac_index < sizeof (MACADDR))
{
if (!high_digit)
{
dest[mac_index] = (char)(digit);
high_digit = TRUE;
delim_action = 1;
}
else
{
dest[mac_index] = (char)(dest[mac_index] * 16 + digit);
++mac_index;
high_digit = FALSE;
delim_action = 0;
}
}
else
return FALSE;
}
else
return FALSE;
}
return (mac_index + delim_action) >= sizeof (MACADDR);
}
/*
* Generate a MAC using the GUID in the adapter name.
*
* The mac is constructed as 00:FF:xx:xx:xx:xx where
* the Xs are taken from the first 32 bits of the GUID in the
* adapter name. This is similar to the Linux 2.4 tap MAC
* generator, except linux uses 32 random bits for the Xs.
*
* In general, this solution is reasonable for most
* applications except for very large bridged TAP networks,
* where the probability of address collisions becomes more
* than infintesimal.
*
* Using the well-known "birthday paradox", on a 1000 node
* network the probability of collision would be
* 0.000116292153. On a 10,000 node network, the probability
* of collision would be 0.01157288998621678766.
*/
VOID GenerateRandomMac (MACADDR mac, const unsigned char *adapter_name)
{
unsigned const char *cp = adapter_name;
unsigned char c;
unsigned int i = 2;
unsigned int byte = 0;
int brace = 0;
int state = 0;
CLEAR_MAC (mac);
mac[0] = 0x00;
mac[1] = 0xFF;
while (c = *cp++)
{
if (i >= sizeof (MACADDR))
break;
if (c == '{')
brace = 1;
if (IsHexDigit (c) && brace)
{
const unsigned int digit = HexStringToDecimalInt (c);
if (state)
{
byte <<= 4;
byte |= digit;
mac[i++] = (unsigned char) byte;
state = 0;
}
else
{
byte = digit;
state = 1;
}
}
}
}
VOID GenerateRelatedMAC (MACADDR dest, const MACADDR src, const int delta)
{
COPY_MAC (dest, src);
dest[2] += (UCHAR) delta;
}

View File

@ -0,0 +1,38 @@
/*
* TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows.
*
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
*
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
* 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 version 2
* as published by the Free Software Foundation.
*
* 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
*/
#ifndef MacInfoDefined
#define MacInfoDefined
//===================================================================================
// Macros
//===================================================================================
#define IsMacDelimiter(a) (a == ':' || a == '-' || a == '.')
#define IsHexDigit(c) ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))
#define COPY_MAC(dest, src) NdisMoveMemory ((dest), (src), sizeof (MACADDR))
#define CLEAR_MAC(dest) NdisZeroMemory ((dest), sizeof (MACADDR))
#define MAC_EQUAL(a,b) (memcmp ((a), (b), sizeof (MACADDR)) == 0)
#endif

186
vsprojects/TapDriver/mem.c Normal file
View File

@ -0,0 +1,186 @@
/*
* TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows.
*
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
*
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
* 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 version 2
* as published by the Free Software Foundation.
*
* 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
*/
//------------------
// Memory Management
//------------------
PVOID
MemAlloc (ULONG p_Size, BOOLEAN zero)
{
PVOID l_Return = NULL;
if (p_Size)
{
__try
{
if (NdisAllocateMemoryWithTag (&l_Return, p_Size, 'APAT')
== NDIS_STATUS_SUCCESS)
{
if (zero)
NdisZeroMemory (l_Return, p_Size);
}
else
l_Return = NULL;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
l_Return = NULL;
}
}
return l_Return;
}
VOID
MemFree (PVOID p_Addr, ULONG p_Size)
{
if (p_Addr && p_Size)
{
__try
{
#if DBG
NdisZeroMemory (p_Addr, p_Size);
#endif
NdisFreeMemory (p_Addr, p_Size, 0);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
}
}
}
/*
* Circular queue management routines.
*/
#define QUEUE_BYTE_ALLOCATION(size) \
(sizeof (Queue) + (size * sizeof (PVOID)))
#define QUEUE_ADD_INDEX(var, inc) \
{ \
var += inc; \
if (var >= q->capacity) \
var -= q->capacity; \
MYASSERT (var < q->capacity); \
}
#define QUEUE_SANITY_CHECK() \
MYASSERT (q != NULL && q->base < q->capacity && q->size <= q->capacity)
#define QueueCount(q) (q->size)
#define UPDATE_MAX_SIZE() \
{ \
if (q->size > q->max_size) \
q->max_size = q->size; \
}
Queue *
QueueInit (ULONG capacity)
{
Queue *q;
MYASSERT (capacity > 0);
q = (Queue *) MemAlloc (QUEUE_BYTE_ALLOCATION (capacity), TRUE);
if (!q)
return NULL;
q->base = q->size = 0;
q->capacity = capacity;
q->max_size = 0;
return q;
}
VOID
QueueFree (Queue *q)
{
if (q)
{
QUEUE_SANITY_CHECK ();
MemFree (q, QUEUE_BYTE_ALLOCATION (q->capacity));
}
}
PVOID
QueuePush (Queue *q, PVOID item)
{
ULONG dest;
QUEUE_SANITY_CHECK ();
if (q->size == q->capacity)
return NULL;
dest = q->base;
QUEUE_ADD_INDEX (dest, q->size);
q->data[dest] = item;
++q->size;
UPDATE_MAX_SIZE();
return item;
}
PVOID
QueuePop (Queue *q)
{
ULONG oldbase;
QUEUE_SANITY_CHECK ();
if (!q->size)
return NULL;
oldbase = q->base;
QUEUE_ADD_INDEX (q->base, 1);
--q->size;
UPDATE_MAX_SIZE();
return q->data[oldbase];
}
PVOID
QueueExtract (Queue *q, PVOID item)
{
ULONG src, dest, count, n;
QUEUE_SANITY_CHECK ();
n = 0;
src = dest = q->base;
count = q->size;
while (count--)
{
if (item == q->data[src])
{
++n;
--q->size;
}
else
{
q->data[dest] = q->data[src];
QUEUE_ADD_INDEX (dest, 1);
}
QUEUE_ADD_INDEX (src, 1);
}
if (n)
return item;
else
return NULL;
}
#undef QUEUE_BYTE_ALLOCATION
#undef QUEUE_ADD_INDEX
#undef QUEUE_SANITY_CHECK
#undef UPDATE_MAX_SIZE

View File

@ -0,0 +1,187 @@
; ****************************************************************************
; * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. *
; * This program is free software; you can redistribute it and/or modify *
; * it under the terms of the GNU General Public License version 2 *
; * as published by the Free Software Foundation. *
; ****************************************************************************
; SYNTAX CHECKER
; cd \WINDDK\3790\tools\chkinf
; chkinf c:\src\openvpn\tap-win32\i386\oemwin2k.inf
; OUTPUT -> file:///c:/WINDDK/3790/tools/chkinf/htm/c%23+src+openvpn+tap-win32+i386+__OemWin2k.htm
; INSTALL/REMOVE DRIVER
; tapinstall install OemWin2k.inf TAP0901
; tapinstall update OemWin2k.inf TAP0901
; tapinstall remove TAP0901
;*********************************************************
; Note to Developers:
;
; If you are bundling the TAP-Windows driver with your app,
; you should try to rename it in such a way that it will
; not collide with other instances of TAP-Windows defined
; by other apps. Multiple versions of the TAP-Windows
; driver, each installed by different apps, can coexist
; on the same machine if you follow these guidelines.
; NOTE: these instructions assume you are editing the
; generated OemWin2k.inf file, not the source
; OemWin2k.inf.in file which is preprocessed by winconfig
; and uses macro definitions from settings.in.
;
; (1) Rename all tapXXXX instances in this file to
; something different (use at least 5 characters
; for this name!)
; (2) Change the "!define TAP" definition in openvpn.nsi
; to match what you changed tapXXXX to.
; (3) Change TARGETNAME in SOURCES to match what you
; changed tapXXXX to.
; (4) Change TAP_COMPONENT_ID in common.h to match what
; you changed tapXXXX to.
; (5) Change SZDEPENDENCIES in service.h to match what
; you changed tapXXXX to.
; (6) Change DeviceDescription and Provider strings.
; (7) Change PRODUCT_TAP_WIN_DEVICE_DESCRIPTION in constants.h to what you
; set DeviceDescription to.
;
;*********************************************************
[Version]
Signature = "$Windows NT$"
CatalogFile = @PRODUCT_TAP_WIN_COMPONENT_ID@.cat
ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318}
Provider = %Provider%
Class = Net
; This version number should match the version
; number given in SOURCES.
DriverVer=@PRODUCT_TAP_WIN_RELDATE@,@PRODUCT_TAP_WIN_MAJOR@.00.00.@PRODUCT_TAP_WIN_MINOR@
[Strings]
DeviceDescription = "@PRODUCT_TAP_WIN_DEVICE_DESCRIPTION@"
Provider = "@PRODUCT_TAP_WIN_PROVIDER@"
;----------------------------------------------------------------
; Manufacturer + Product Section (Done)
;----------------------------------------------------------------
[Manufacturer]
%Provider% = @PRODUCT_TAP_WIN_COMPONENT_ID@@INF_PROVIDER_SUFFIX@
[@PRODUCT_TAP_WIN_COMPONENT_ID@@INF_SECTION_SUFFIX@]
%DeviceDescription% = @PRODUCT_TAP_WIN_COMPONENT_ID@.ndi, @PRODUCT_TAP_WIN_COMPONENT_ID@
;---------------------------------------------------------------
; Driver Section (Done)
;---------------------------------------------------------------
;----------------- Characteristics ------------
; NCF_PHYSICAL = 0x04
; NCF_VIRTUAL = 0x01
; NCF_SOFTWARE_ENUMERATED = 0x02
; NCF_HIDDEN = 0x08
; NCF_NO_SERVICE = 0x10
; NCF_HAS_UI = 0x80
;----------------- Characteristics ------------
[@PRODUCT_TAP_WIN_COMPONENT_ID@.ndi]
CopyFiles = @PRODUCT_TAP_WIN_COMPONENT_ID@.driver, @PRODUCT_TAP_WIN_COMPONENT_ID@.files
AddReg = @PRODUCT_TAP_WIN_COMPONENT_ID@.reg
AddReg = @PRODUCT_TAP_WIN_COMPONENT_ID@.params.reg
Characteristics = @PRODUCT_TAP_WIN_CHARACTERISTICS@
[@PRODUCT_TAP_WIN_COMPONENT_ID@.ndi.Services]
AddService = @PRODUCT_TAP_WIN_COMPONENT_ID@, 2, @PRODUCT_TAP_WIN_COMPONENT_ID@.service
[@PRODUCT_TAP_WIN_COMPONENT_ID@.reg]
HKR, Ndi, Service, 0, "@PRODUCT_TAP_WIN_COMPONENT_ID@"
HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
HKR, , Manufacturer, 0, "%Provider%"
HKR, , ProductName, 0, "%DeviceDescription%"
[@PRODUCT_TAP_WIN_COMPONENT_ID@.params.reg]
HKR, Ndi\params\MTU, ParamDesc, 0, "MTU"
HKR, Ndi\params\MTU, Type, 0, "int"
HKR, Ndi\params\MTU, Default, 0, "1500"
HKR, Ndi\params\MTU, Optional, 0, "0"
HKR, Ndi\params\MTU, Min, 0, "100"
HKR, Ndi\params\MTU, Max, 0, "1500"
HKR, Ndi\params\MTU, Step, 0, "1"
HKR, Ndi\params\MediaStatus, ParamDesc, 0, "Media Status"
HKR, Ndi\params\MediaStatus, Type, 0, "enum"
HKR, Ndi\params\MediaStatus, Default, 0, "0"
HKR, Ndi\params\MediaStatus, Optional, 0, "0"
HKR, Ndi\params\MediaStatus\enum, "0", 0, "Application Controlled"
HKR, Ndi\params\MediaStatus\enum, "1", 0, "Always Connected"
HKR, Ndi\params\MAC, ParamDesc, 0, "MAC Address"
HKR, Ndi\params\MAC, Type, 0, "edit"
HKR, Ndi\params\MAC, Optional, 0, "1"
HKR, Ndi\params\AllowNonAdmin, ParamDesc, 0, "Non-Admin Access"
HKR, Ndi\params\AllowNonAdmin, Type, 0, "enum"
HKR, Ndi\params\AllowNonAdmin, Default, 0, "1"
HKR, Ndi\params\AllowNonAdmin, Optional, 0, "0"
HKR, Ndi\params\AllowNonAdmin\enum, "0", 0, "Not Allowed"
HKR, Ndi\params\AllowNonAdmin\enum, "1", 0, "Allowed"
;----------------------------------------------------------------
; Service Section
;----------------------------------------------------------------
;---------- Service Type -------------
; SERVICE_KERNEL_DRIVER = 0x01
; SERVICE_WIN32_OWN_PROCESS = 0x10
;---------- Service Type -------------
;---------- Start Mode ---------------
; SERVICE_BOOT_START = 0x0
; SERVICE_SYSTEM_START = 0x1
; SERVICE_AUTO_START = 0x2
; SERVICE_DEMAND_START = 0x3
; SERVICE_DISABLED = 0x4
;---------- Start Mode ---------------
[@PRODUCT_TAP_WIN_COMPONENT_ID@.service]
DisplayName = %DeviceDescription%
ServiceType = 1
StartType = 3
ErrorControl = 1
LoadOrderGroup = NDIS
ServiceBinary = %12%\@PRODUCT_TAP_WIN_COMPONENT_ID@.sys
;-----------------------------------------------------------------
; File Installation
;-----------------------------------------------------------------
;----------------- Copy Flags ------------
; COPYFLG_NOSKIP = 0x02
; COPYFLG_NOVERSIONCHECK = 0x04
;----------------- Copy Flags ------------
; SourceDisksNames
; diskid = description[, [tagfile] [, <unused>, subdir]]
; 1 = "Intel Driver Disk 1",e100bex.sys,,
[SourceDisksNames]
1 = %DeviceDescription%, @PRODUCT_TAP_WIN_COMPONENT_ID@.sys
; SourceDisksFiles
; filename_on_source = diskID[, [subdir][, size]]
; e100bex.sys = 1,, ; on distribution disk 1
[SourceDisksFiles]
@PRODUCT_TAP_WIN_COMPONENT_ID@.sys = 1
[DestinationDirs]
@PRODUCT_TAP_WIN_COMPONENT_ID@.files = 11
@PRODUCT_TAP_WIN_COMPONENT_ID@.driver = 12
[@PRODUCT_TAP_WIN_COMPONENT_ID@.files]
; TapPanel.cpl,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK
; cipsrvr.exe,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK
[@PRODUCT_TAP_WIN_COMPONENT_ID@.driver]
@PRODUCT_TAP_WIN_COMPONENT_ID@.sys,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK
;---------------------------------------------------------------
; End
;---------------------------------------------------------------

View File

@ -0,0 +1,224 @@
/*
* TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows.
*
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
*
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
* 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 version 2
* as published by the Free Software Foundation.
*
* 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
*/
//============================================================
// MAC address, Ethernet header, and ARP
//============================================================
#pragma pack(1)
#define IP_HEADER_SIZE 20
#define IPV6_HEADER_SIZE 40
typedef unsigned char MACADDR [6];
typedef unsigned long IPADDR;
typedef unsigned char IPV6ADDR [16];
//-----------------
// Ethernet address
//-----------------
typedef struct {
MACADDR addr;
} ETH_ADDR;
typedef struct {
ETH_ADDR list[NIC_MAX_MCAST_LIST];
} MC_LIST;
//----------------
// Ethernet header
//----------------
typedef struct
{
MACADDR dest; /* destination eth addr */
MACADDR src; /* source ether addr */
# define ETH_P_IP 0x0800 /* IPv4 protocol */
# define ETH_P_IPV6 0x86DD /* IPv6 protocol */
# define ETH_P_ARP 0x0806 /* ARP protocol */
USHORT proto; /* packet type ID field */
} ETH_HEADER, *PETH_HEADER;
//----------------
// ARP packet
//----------------
typedef struct
{
MACADDR m_MAC_Destination; // Reverse these two
MACADDR m_MAC_Source; // to answer ARP requests
USHORT m_Proto; // 0x0806
# define MAC_ADDR_TYPE 0x0001
USHORT m_MAC_AddressType; // 0x0001
USHORT m_PROTO_AddressType; // 0x0800
UCHAR m_MAC_AddressSize; // 0x06
UCHAR m_PROTO_AddressSize; // 0x04
# define ARP_REQUEST 0x0001
# define ARP_REPLY 0x0002
USHORT m_ARP_Operation; // 0x0001 for ARP request, 0x0002 for ARP reply
MACADDR m_ARP_MAC_Source;
IPADDR m_ARP_IP_Source;
MACADDR m_ARP_MAC_Destination;
IPADDR m_ARP_IP_Destination;
}
ARP_PACKET, *PARP_PACKET;
//----------
// IP Header
//----------
typedef struct {
# define IPH_GET_VER(v) (((v) >> 4) & 0x0F)
# define IPH_GET_LEN(v) (((v) & 0x0F) << 2)
UCHAR version_len;
UCHAR tos;
USHORT tot_len;
USHORT id;
# define IP_OFFMASK 0x1fff
USHORT frag_off;
UCHAR ttl;
# define IPPROTO_UDP 17 /* UDP protocol */
# define IPPROTO_TCP 6 /* TCP protocol */
# define IPPROTO_ICMP 1 /* ICMP protocol */
# define IPPROTO_IGMP 2 /* IGMP protocol */
UCHAR protocol;
USHORT check;
ULONG saddr;
ULONG daddr;
/* The options start here. */
} IPHDR;
//-----------
// UDP header
//-----------
typedef struct {
USHORT source;
USHORT dest;
USHORT len;
USHORT check;
} UDPHDR;
//--------------------------
// TCP header, per RFC 793.
//--------------------------
typedef struct {
USHORT source; /* source port */
USHORT dest; /* destination port */
ULONG seq; /* sequence number */
ULONG ack_seq; /* acknowledgement number */
# define TCPH_GET_DOFF(d) (((d) & 0xF0) >> 2)
UCHAR doff_res;
# define TCPH_FIN_MASK (1<<0)
# define TCPH_SYN_MASK (1<<1)
# define TCPH_RST_MASK (1<<2)
# define TCPH_PSH_MASK (1<<3)
# define TCPH_ACK_MASK (1<<4)
# define TCPH_URG_MASK (1<<5)
# define TCPH_ECE_MASK (1<<6)
# define TCPH_CWR_MASK (1<<7)
UCHAR flags;
USHORT window;
USHORT check;
USHORT urg_ptr;
} TCPHDR;
#define TCPOPT_EOL 0
#define TCPOPT_NOP 1
#define TCPOPT_MAXSEG 2
#define TCPOLEN_MAXSEG 4
//------------
// IPv6 Header
//------------
typedef struct {
UCHAR version_prio;
UCHAR flow_lbl[3];
USHORT payload_len;
# define IPPROTO_ICMPV6 0x3a /* ICMP protocol v6 */
UCHAR nexthdr;
UCHAR hop_limit;
IPV6ADDR saddr;
IPV6ADDR daddr;
} IPV6HDR;
//--------------------------------------------
// IPCMPv6 NS/NA Packets (RFC4443 and RFC4861)
//--------------------------------------------
// Neighbor Solictiation - RFC 4861, 4.3
// (this is just the ICMPv6 part of the packet)
typedef struct {
UCHAR type;
# define ICMPV6_TYPE_NS 135 // neighbour solicitation
UCHAR code;
# define ICMPV6_CODE_0 0 // no specific sub-code for NS/NA
USHORT checksum;
ULONG reserved;
IPV6ADDR target_addr;
} ICMPV6_NS;
// Neighbor Advertisement - RFC 4861, 4.4 + 4.6/4.6.1
// (this is just the ICMPv6 payload)
typedef struct {
UCHAR type;
# define ICMPV6_TYPE_NA 136 // neighbour advertisement
UCHAR code;
# define ICMPV6_CODE_0 0 // no specific sub-code for NS/NA
USHORT checksum;
UCHAR rso_bits; // Router(0), Solicited(2), Ovrrd(4)
UCHAR reserved[3];
IPV6ADDR target_addr;
// always include "Target Link-layer Address" option (RFC 4861 4.6.1)
UCHAR opt_type;
#define ICMPV6_OPTION_TLLA 2
UCHAR opt_length;
#define ICMPV6_LENGTH_TLLA 1 // multiplied by 8 -> 1 = 8 bytes
MACADDR target_macaddr;
} ICMPV6_NA;
// this is the complete packet with Ethernet and IPv6 headers
typedef struct {
ETH_HEADER eth;
IPV6HDR ipv6;
ICMPV6_NA icmpv6;
} ICMPV6_NA_PKT;
#pragma pack()

View File

@ -0,0 +1,260 @@
/*
* TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows.
*
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
*
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
* 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 version 2
* as published by the Free Software Foundation.
*
* 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
*/
#ifndef TAP_PROTOTYPES_DEFINED
#define TAP_PROTOTYPES_DEFINED
NTSTATUS DriverEntry
(
IN PDRIVER_OBJECT p_DriverObject,
IN PUNICODE_STRING p_RegistryPath
);
VOID TapDriverUnload
(
IN PDRIVER_OBJECT p_DriverObject
);
NDIS_STATUS AdapterCreate
(
OUT PNDIS_STATUS p_ErrorStatus,
OUT PUINT p_MediaIndex,
IN PNDIS_MEDIUM p_Media,
IN UINT p_MediaCount,
IN NDIS_HANDLE p_AdapterHandle,
IN NDIS_HANDLE p_ConfigurationHandle
);
VOID AdapterHalt
(
IN NDIS_HANDLE p_AdapterContext
);
VOID AdapterFreeResources
(
TapAdapterPointer p_Adapter
);
NDIS_STATUS AdapterReset
(
OUT PBOOLEAN p_AddressingReset,
IN NDIS_HANDLE p_AdapterContext
);
NDIS_STATUS AdapterQuery
(
IN NDIS_HANDLE p_AdapterContext,
IN NDIS_OID p_OID,
IN PVOID p_Buffer,
IN ULONG p_BufferLength,
OUT PULONG p_BytesWritten,
OUT PULONG p_BytesNeeded
);
NDIS_STATUS AdapterModify
(
IN NDIS_HANDLE p_AdapterContext,
IN NDIS_OID p_OID,
IN PVOID p_Buffer,
IN ULONG p_BufferLength,
OUT PULONG p_BytesRead,
OUT PULONG p_BytesNeeded
);
NDIS_STATUS AdapterTransmit
(
IN NDIS_HANDLE p_AdapterContext,
IN PNDIS_PACKET p_Packet,
IN UINT p_Flags
);
NDIS_STATUS AdapterReceive
(
OUT PNDIS_PACKET p_Packet,
OUT PUINT p_Transferred,
IN NDIS_HANDLE p_AdapterContext,
IN NDIS_HANDLE p_ReceiveContext,
IN UINT p_Offset,
IN UINT p_ToTransfer
);
NTSTATUS TapDeviceHook
(
IN PDEVICE_OBJECT p_DeviceObject,
IN PIRP p_IRP
);
NDIS_STATUS CreateTapDevice
(
TapExtensionPointer p_Extension,
const char *p_Name
);
VOID DestroyTapDevice
(
TapExtensionPointer p_Extension
);
VOID TapDeviceFreeResources
(
TapExtensionPointer p_Extension
);
NTSTATUS CompleteIRP
(
IN PIRP p_IRP,
IN TapPacketPointer p_PacketBuffer,
IN CCHAR PriorityBoost
);
VOID CancelIRPCallback
(
IN PDEVICE_OBJECT p_DeviceObject,
IN PIRP p_IRP
);
VOID CancelIRP
(
TapExtensionPointer p_Extension,
IN PIRP p_IRP,
BOOLEAN callback
);
VOID FlushQueues
(
TapExtensionPointer p_Extension
);
VOID ResetTapAdapterState
(
TapAdapterPointer p_Adapter
);
BOOLEAN ProcessARP
(
TapAdapterPointer p_Adapter,
const PARP_PACKET src,
const IPADDR adapter_ip,
const IPADDR ip_network,
const IPADDR ip_netmask,
const MACADDR mac
);
VOID SetMediaStatus
(
TapAdapterPointer p_Adapter,
BOOLEAN state
);
VOID InjectPacketDeferred
(
TapAdapterPointer p_Adapter,
UCHAR *packet,
const unsigned int len
);
VOID InjectPacketNow
(
TapAdapterPointer p_Adapter,
UCHAR *packet,
const unsigned int len
);
// for KDEFERRED_ROUTINE and Static Driver Verifier
//#include <wdm.h>
//KDEFERRED_ROUTINE InjectPacketDpc;
VOID InjectPacketDpc
(
KDPC *Dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2
);
VOID CheckIfDhcpAndTunMode
(
TapAdapterPointer p_Adapter
);
VOID HookDispatchFunctions();
#if ENABLE_NONADMIN
#if defined(DDKVER_MAJOR) && DDKVER_MAJOR < 5600
/*
* Better solution for use on Vista DDK, but possibly not compatible with
* earlier DDKs:
*
* Eliminate the definition of SECURITY_DESCRIPTOR (and even ZwSetSecurityObject),
* and at the top of tapdrv.c change:
*
* #include <ndis.h>
* #include <ntstrsafe.h>
* #include <ntddk.h>
*
* To
*
* #include <ntifs.h>
* #include <ndis.h>
* #include <ntstrsafe.h>
*/
typedef struct _SECURITY_DESCRIPTOR {
unsigned char opaque[64];
} SECURITY_DESCRIPTOR;
NTSYSAPI
NTSTATUS
NTAPI
ZwSetSecurityObject (
IN HANDLE Handle,
IN SECURITY_INFORMATION SecurityInformation,
IN PSECURITY_DESCRIPTOR SecurityDescriptor);
#endif
VOID AllowNonAdmin (TapExtensionPointer p_Extension);
#endif
struct WIN2K_NDIS_MINIPORT_BLOCK
{
unsigned char opaque[16];
UNICODE_STRING MiniportName; // how mini-port refers to us
};
#if PACKET_TRUNCATION_CHECK
VOID IPv4PacketSizeVerify
(
const UCHAR *data,
ULONG length,
BOOLEAN tun,
const char *prefix,
LONG *counter
);
#endif
#endif

View File

@ -0,0 +1,74 @@
/*
* TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows.
*
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
*
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
* 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 version 2
* as published by the Free Software Foundation.
*
* 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
*/
#ifndef __TAP_WIN_H
#define __TAP_WIN_H
/*
* =============
* TAP IOCTLs
* =============
*/
#define TAP_WIN_CONTROL_CODE(request,method) \
CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
/* Present in 8.1 */
#define TAP_WIN_IOCTL_GET_MAC TAP_WIN_CONTROL_CODE (1, METHOD_BUFFERED)
#define TAP_WIN_IOCTL_GET_VERSION TAP_WIN_CONTROL_CODE (2, METHOD_BUFFERED)
#define TAP_WIN_IOCTL_GET_MTU TAP_WIN_CONTROL_CODE (3, METHOD_BUFFERED)
#define TAP_WIN_IOCTL_GET_INFO TAP_WIN_CONTROL_CODE (4, METHOD_BUFFERED)
#define TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT TAP_WIN_CONTROL_CODE (5, METHOD_BUFFERED)
#define TAP_WIN_IOCTL_SET_MEDIA_STATUS TAP_WIN_CONTROL_CODE (6, METHOD_BUFFERED)
#define TAP_WIN_IOCTL_CONFIG_DHCP_MASQ TAP_WIN_CONTROL_CODE (7, METHOD_BUFFERED)
#define TAP_WIN_IOCTL_GET_LOG_LINE TAP_WIN_CONTROL_CODE (8, METHOD_BUFFERED)
#define TAP_WIN_IOCTL_CONFIG_DHCP_SET_OPT TAP_WIN_CONTROL_CODE (9, METHOD_BUFFERED)
/* Added in 8.2 */
/* obsoletes TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT */
#define TAP_WIN_IOCTL_CONFIG_TUN TAP_WIN_CONTROL_CODE (10, 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 TAP_WIN_SUFFIX ".tap"
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,178 @@
/*
* TAP-Windows -- A kernel driver to provide virtual tap
* device functionality on Windows.
*
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
*
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
* 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 version 2
* as published by the Free Software Foundation.
*
* 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
*/
#ifndef TAP_TYPES_DEFINED
#define TAP_TYPES_DEFINED
typedef struct _Queue
{
ULONG base;
ULONG size;
ULONG capacity;
ULONG max_size;
PVOID data[];
} Queue;
typedef struct _TapAdapter;
typedef struct _TapPacket;
typedef union _TapAdapterQuery
{
NDIS_HARDWARE_STATUS m_HardwareStatus;
NDIS_MEDIUM m_Medium;
NDIS_PHYSICAL_MEDIUM m_PhysicalMedium;
UCHAR m_MacAddress [6];
UCHAR m_Buffer [256];
ULONG m_Long;
USHORT m_Short;
UCHAR m_Byte;
}
TapAdapterQuery, *TapAdapterQueryPointer;
typedef struct _TapExtension
{
// TAP device object and packet queues
Queue *m_PacketQueue, *m_IrpQueue;
PDEVICE_OBJECT m_TapDevice;
NDIS_HANDLE m_TapDeviceHandle;
ULONG m_TapOpens;
// Used to lock packet queues
NDIS_SPIN_LOCK m_QueueLock;
BOOLEAN m_AllocatedSpinlocks;
// Used to bracket open/close
// state changes.
MUTEX m_OpenCloseMutex;
// True if device has been permanently halted
BOOLEAN m_Halt;
// TAP device name
unsigned char *m_TapName;
UNICODE_STRING m_UnicodeLinkName;
BOOLEAN m_CreatedUnicodeLinkName;
// Used for device status ioctl only
const char *m_LastErrorFilename;
int m_LastErrorLineNumber;
LONG m_NumTapOpens;
// Flags
BOOLEAN m_TapIsRunning;
BOOLEAN m_CalledTapDeviceFreeResources;
// DPC queue for deferred packet injection
BOOLEAN m_InjectDpcInitialized;
KDPC m_InjectDpc;
NDIS_SPIN_LOCK m_InjectLock;
Queue *m_InjectQueue;
}
TapExtension, *TapExtensionPointer;
typedef struct _TapPacket
{
# define TAP_PACKET_SIZE(data_size) (sizeof (TapPacket) + (data_size))
# define TP_TUN 0x80000000
# define TP_SIZE_MASK (~TP_TUN)
ULONG m_SizeFlags;
UCHAR m_Data []; // m_Data must be the last struct member
}
TapPacket, *TapPacketPointer;
typedef struct _InjectPacket
{
# define INJECT_PACKET_SIZE(data_size) (sizeof (InjectPacket) + (data_size))
# define INJECT_PACKET_FREE(ib) NdisFreeMemory ((ib), INJECT_PACKET_SIZE ((ib)->m_Size), 0)
ULONG m_Size;
UCHAR m_Data []; // m_Data must be the last struct member
}
InjectPacket, *InjectPacketPointer;
typedef struct _TapAdapter
{
# define NAME(a) ((a)->m_NameAnsi.Buffer)
ANSI_STRING m_NameAnsi;
MACADDR m_MAC;
BOOLEAN m_InterfaceIsRunning;
NDIS_HANDLE m_MiniportAdapterHandle;
LONG m_Rx, m_Tx, m_RxErr, m_TxErr;
#if PACKET_TRUNCATION_CHECK
LONG m_RxTrunc, m_TxTrunc;
#endif
NDIS_MEDIUM m_Medium;
ULONG m_Lookahead;
ULONG m_MTU;
// TRUE if adapter should always be
// "connected" even when device node
// is not open by a userspace process.
BOOLEAN m_MediaStateAlwaysConnected;
// TRUE if device is "connected"
BOOLEAN m_MediaState;
// Adapter power state
char m_DeviceState;
// Info for point-to-point mode
BOOLEAN m_tun;
IPADDR m_localIP;
IPADDR m_remoteNetwork;
IPADDR m_remoteNetmask;
ETH_HEADER m_TapToUser;
ETH_HEADER m_UserToTap;
ETH_HEADER m_UserToTap_IPv6; // same as UserToTap but proto=ipv6
MACADDR m_MAC_Broadcast;
// Used for DHCP server masquerade
BOOLEAN m_dhcp_enabled;
IPADDR m_dhcp_addr;
ULONG m_dhcp_netmask;
IPADDR m_dhcp_server_ip;
BOOLEAN m_dhcp_server_arp;
MACADDR m_dhcp_server_mac;
ULONG m_dhcp_lease_time;
UCHAR m_dhcp_user_supplied_options_buffer[DHCP_USER_SUPPLIED_OPTIONS_BUFFER_SIZE];
ULONG m_dhcp_user_supplied_options_buffer_len;
BOOLEAN m_dhcp_received_discover;
ULONG m_dhcp_bad_requests;
// Help to tear down the adapter by keeping
// some state information on allocated
// resources.
BOOLEAN m_CalledAdapterFreeResources;
BOOLEAN m_RegisteredAdapterShutdownHandler;
// Multicast list info
NDIS_SPIN_LOCK m_MCLock;
BOOLEAN m_MCLockAllocated;
ULONG m_MCListSize;
MC_LIST m_MCList;
// Information on the TAP device
TapExtension m_Extension;
} TapAdapter, *TapAdapterPointer;
#endif