summaryrefslogtreecommitdiff
path: root/node/EthernetTap.cpp
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@zerotier.com>2014-01-21 13:07:22 -0800
committerAdam Ierymenko <adam.ierymenko@zerotier.com>2014-01-21 13:07:22 -0800
commit370dd6c4da6acff85947cef365e4df48c00d0863 (patch)
tree96dd0db7a3fcecb6354276ed23c6274c5b7804d7 /node/EthernetTap.cpp
parent06ca24e8e2b663842fee7daabac4a2652da5a834 (diff)
downloadinfinitytier-370dd6c4da6acff85947cef365e4df48c00d0863.tar.gz
infinitytier-370dd6c4da6acff85947cef365e4df48c00d0863.zip
Several things:
(1) Add a bunch of tedious type casts to eliminate unnecessary compiler warnings on Windows X64 builds. (2) Some EthernetTap work to integrate Windows custom IOCTL for multicast group lookup (not done quite yet). (3) Dump some more info in selftest to make sure our Windows path lookup functions are returning sane results.
Diffstat (limited to 'node/EthernetTap.cpp')
-rw-r--r--node/EthernetTap.cpp114
1 files changed, 55 insertions, 59 deletions
diff --git a/node/EthernetTap.cpp b/node/EthernetTap.cpp
index 458f1eed..231fde06 100644
--- a/node/EthernetTap.cpp
+++ b/node/EthernetTap.cpp
@@ -268,8 +268,6 @@ EthernetTap::EthernetTap(
_r(renv),
_handler(handler),
_arg(arg),
- _dhcp(false),
- _dhcp6(false),
_fd(0)
{
char devpath[64],ethaddr[64],mtustr[16],tmp[4096];
@@ -389,7 +387,7 @@ void EthernetTap::whack()
if (cpid == 0) {
execl(ipconfig,ipconfig,"set",_dev,"AUTOMATIC-V6",(const char *)0);
_exit(-1);
- } else {
+ } else if (cpid > 0) {
int exitcode = -1;
waitpid(cpid,&exitcode,0);
}
@@ -399,17 +397,6 @@ void EthernetTap::whack()
void EthernetTap::whack() {}
#endif // __APPLE__ / !__APPLE__
-bool EthernetTap::setDhcpEnabled(bool dhcp)
-{
- // TODO
- return _dhcp;
-}
-
-bool EthernetTap::setDhcp6Enabled(bool dhcp)
-{
- return _dhcp6;
-}
-
void EthernetTap::setDisplayName(const char *dn)
{
}
@@ -810,7 +797,6 @@ static inline void _intl_freeifmaddrs(struct ifmaddrs *ifmp)
free(ifmp);
}
-
// --------------------------------------------------------------------------
bool EthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups)
@@ -981,8 +967,6 @@ EthernetTap::EthernetTap(
_r(renv),
_handler(handler),
_arg(arg),
- _dhcp(false),
- _dhcp6(false),
_tap(INVALID_HANDLE_VALUE),
_injectSemaphore(INVALID_HANDLE_VALUE),
_run(true)
@@ -995,10 +979,14 @@ EthernetTap::EthernetTap(
throw std::runtime_error("MTU too large for Windows tap");
#ifdef _WIN64
- const char *devcon = "\\devcon64.exe";
+ BOOL is64Bit = TRUE;
+ const char *devcon = "\\devcon_x64.exe";
+ const char *tapDriver = "\\tap-windows\\x64\\ztTap100.inf";
#else
- BOOL f64 = FALSE;
- const char *devcon = ((IsWow64Process(GetCurrentProcess(),&f64) == TRUE) ? "\\devcon64.exe" : "\\devcon32.exe");
+ BOOL is64Bit = FALSE;
+ IsWow64Process(GetCurrentProcess(),&is64Bit);
+ const char *devcon = ((is64Bit == TRUE) ? "\\devcon_x64.exe" : "\\devcon_x86.exe");
+ const char *tapDriver = ((is64Bit == TRUE) ? "\\tap-windows\\x64\\ztTap100.inf" : "\\tap-windows\\x86\\ztTap100.inf");
#endif
Mutex::Lock _l(_systemTapInitLock); // only init one tap at a time, process-wide
@@ -1066,7 +1054,7 @@ EthernetTap::EthernetTap(
PROCESS_INFORMATION processInfo;
memset(&startupInfo,0,sizeof(STARTUPINFOA));
memset(&processInfo,0,sizeof(PROCESS_INFORMATION));
- if (!CreateProcessA(NULL,(LPSTR)(std::string("\"") + _r->homePath + devcon + "\" install \"" + _r->homePath + "\\ztTap100.inf\" ztTap100").c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) {
+ if (!CreateProcessA(NULL,(LPSTR)(std::string("\"") + _r->homePath + devcon + "\" install \"" + _r->homePath + tapDriver + "\" ztTap100").c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) {
RegCloseKey(nwAdapters);
throw std::runtime_error(std::string("unable to find or execute devcon at ")+devcon);
}
@@ -1145,9 +1133,6 @@ EthernetTap::EthernetTap(
throw std::runtime_error("unable to convert instance ID GUID to native GUID (invalid NetCfgInstanceId in registry?)");
}
- setDhcpEnabled(false);
- setDhcp6Enabled(false);
-
// Disable and enable interface to ensure registry settings take effect
{
STARTUPINFOA startupInfo;
@@ -1211,24 +1196,25 @@ EthernetTap::~EthernetTap()
CloseHandle(_tapOvlWrite.hEvent);
CloseHandle(_injectSemaphore);
- // Disable network device on shutdown
#ifdef _WIN64
- const char *devcon = "\\devcon64.exe";
+ BOOL is64Bit = TRUE;
+ const char *devcon = "\\devcon_x64.exe";
#else
- BOOL f64 = FALSE;
- const char *devcon = ((IsWow64Process(GetCurrentProcess(),&f64) == TRUE) ? "\\devcon64.exe" : "\\devcon32.exe");
+ BOOL is64Bit = FALSE;
+ IsWow64Process(GetCurrentProcess(),&is64Bit);
+ const char *devcon = ((is64Bit == TRUE) ? "\\devcon_x64.exe" : "\\devcon_x86.exe");
#endif
- {
- STARTUPINFOA startupInfo;
- startupInfo.cb = sizeof(startupInfo);
- PROCESS_INFORMATION processInfo;
- memset(&startupInfo,0,sizeof(STARTUPINFOA));
- memset(&processInfo,0,sizeof(PROCESS_INFORMATION));
- if (CreateProcessA(NULL,(LPSTR)(std::string("\"") + _r->homePath + devcon + "\" disable @" + _myDeviceInstanceIdPath).c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) {
- WaitForSingleObject(processInfo.hProcess,INFINITE);
- CloseHandle(processInfo.hProcess);
- CloseHandle(processInfo.hThread);
- }
+
+ // Disable network device on shutdown
+ STARTUPINFOA startupInfo;
+ startupInfo.cb = sizeof(startupInfo);
+ PROCESS_INFORMATION processInfo;
+ memset(&startupInfo,0,sizeof(STARTUPINFOA));
+ memset(&processInfo,0,sizeof(PROCESS_INFORMATION));
+ if (CreateProcessA(NULL,(LPSTR)(std::string("\"") + _r->homePath + devcon + "\" disable @" + _myDeviceInstanceIdPath).c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) {
+ WaitForSingleObject(processInfo.hProcess,INFINITE);
+ CloseHandle(processInfo.hProcess);
+ CloseHandle(processInfo.hThread);
}
}
@@ -1236,25 +1222,6 @@ void EthernetTap::whack()
{
}
-bool EthernetTap::setDhcpEnabled(bool dhcp)
-{
- HKEY tcpIpInterfaces;
- if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces",0,KEY_READ|KEY_WRITE,&tcpIpInterfaces) == ERROR_SUCCESS) {
- _dhcp = dhcp;
- DWORD enable = (dhcp ? 1 : 0);
- RegSetKeyValueA(tcpIpInterfaces,_myDeviceInstanceId.c_str(),"EnableDHCP",REG_DWORD,&enable,sizeof(enable));
- RegCloseKey(tcpIpInterfaces);
- } else _dhcp = false;
-
- return _dhcp;
-}
-
-bool EthernetTap::setDhcp6Enabled(bool dhcp)
-{
- // TODO
- return _dhcp6;
-}
-
void EthernetTap::setDisplayName(const char *dn)
{
HKEY ifp;
@@ -1394,14 +1361,43 @@ bool EthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups)
{
std::set<MulticastGroup> newGroups;
+ // Ensure that groups are added for each IP... this handles the MAC:ADI
+ // groups that are created from IPv4 addresses. Some of these may end
+ // up being duplicates of what the IOCTL returns but that's okay since
+ // the set will filter these.
std::set<InetAddress> ipaddrs(allIps());
for(std::set<InetAddress>::const_iterator i(ipaddrs.begin());i!=ipaddrs.end();++i)
newGroups.insert(MulticastGroup::deriveMulticastGroupForAddressResolution(*i));
- bool changed = false;
+ // The ZT1 tap driver supports an IOCTL to get multicast memberships at the L2
+ // level... something Windows does not seem to expose ordinarily. This lets
+ // pretty much anything work... IPv4, IPv6, IPX, oldskool Netbios, who knows...
+ unsigned char mcastbuf[TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS_OUTPUT_BUF_SIZE];
+ DWORD bytesReturned = 0;
+ if (DeviceIoControl(_tap,TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS,(LPVOID)0,0,(LPVOID)mcastbuf,sizeof(mcastbuf),&bytesReturned,NULL)) {
+ printf("TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS: got %d bytes\n",(int)bytesReturned);
+ MAC mac;
+ DWORD i = 0;
+ while ((i + 6) <= bytesReturned) {
+ mac.data[0] = mcastbuf[i++];
+ mac.data[1] = mcastbuf[i++];
+ mac.data[2] = mcastbuf[i++];
+ mac.data[3] = mcastbuf[i++];
+ mac.data[4] = mcastbuf[i++];
+ mac.data[5] = mcastbuf[i++];
+ if (mac.isMulticast()) { // exclude the nulls that may be returned or any other junk Windows puts in there
+ newGroups.insert(MulticastGroup(mac,0));
+ printf("TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS: %s\n",mac.toString().c_str());
+ }
+ }
+ } else {
+ printf("TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS: failed\n");
+ }
newGroups.insert(_blindWildcardMulticastGroup); // always join this
+ bool changed = false;
+
for(std::set<MulticastGroup>::iterator mg(newGroups.begin());mg!=newGroups.end();++mg) {
if (!groups.count(*mg)) {
groups.insert(*mg);