summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
Diffstat (limited to 'node')
-rw-r--r--node/EthernetTap.cpp208
-rw-r--r--node/EthernetTap.hpp19
2 files changed, 32 insertions, 195 deletions
diff --git a/node/EthernetTap.cpp b/node/EthernetTap.cpp
index d9a66b3e..9e07d160 100644
--- a/node/EthernetTap.cpp
+++ b/node/EthernetTap.cpp
@@ -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__ ////////////////////////////////////////////////////////
diff --git a/node/EthernetTap.hpp b/node/EthernetTap.hpp
index a409b412..69e5eafa 100644
--- a/node/EthernetTap.hpp
+++ b/node/EthernetTap.hpp
@@ -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
};