mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-02-07 11:50:13 +00:00
Couple of Windows fixes, get rid of ips()/allIps() distinction in EthernetTap. (Will need to be fixed on Unix now... later.)
This commit is contained in:
parent
9232ba1da0
commit
2f37ea842f
@ -1089,6 +1089,15 @@ EthernetTap::EthernetTap(
|
|||||||
if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS)
|
if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS)
|
||||||
_myDeviceInstanceIdPath.assign(data,dataLen);
|
_myDeviceInstanceIdPath.assign(data,dataLen);
|
||||||
mySubkeyName = subkeyName;
|
mySubkeyName = subkeyName;
|
||||||
|
|
||||||
|
// Disable DHCP by default on newly created devices
|
||||||
|
HKEY tcpIpInterfaces;
|
||||||
|
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces",0,KEY_READ|KEY_WRITE,&tcpIpInterfaces) == ERROR_SUCCESS) {
|
||||||
|
DWORD enable = 0;
|
||||||
|
RegSetKeyValueA(tcpIpInterfaces,_myDeviceInstanceId.c_str(),"EnableDHCP",REG_DWORD,&enable,sizeof(enable));
|
||||||
|
RegCloseKey(tcpIpInterfaces);
|
||||||
|
}
|
||||||
|
|
||||||
subkeyIndex = -1; // break outer loop
|
subkeyIndex = -1; // break outer loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1133,14 +1142,6 @@ EthernetTap::EthernetTap(
|
|||||||
throw std::runtime_error("unable to convert instance ID GUID to native GUID (invalid NetCfgInstanceId in registry?)");
|
throw std::runtime_error("unable to convert instance ID GUID to native GUID (invalid NetCfgInstanceId in registry?)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable DHCP -- this might get changed if/when DHCP is supported
|
|
||||||
HKEY tcpIpInterfaces;
|
|
||||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces",0,KEY_READ|KEY_WRITE,&tcpIpInterfaces) == ERROR_SUCCESS) {
|
|
||||||
DWORD enable = 0;
|
|
||||||
RegSetKeyValueA(tcpIpInterfaces,_myDeviceInstanceId.c_str(),"EnableDHCP",REG_DWORD,&enable,sizeof(enable));
|
|
||||||
RegCloseKey(tcpIpInterfaces);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable and enable interface to ensure registry settings take effect
|
// Disable and enable interface to ensure registry settings take effect
|
||||||
{
|
{
|
||||||
STARTUPINFOA startupInfo;
|
STARTUPINFOA startupInfo;
|
||||||
@ -1241,15 +1242,14 @@ void EthernetTap::setDisplayName(const char *dn)
|
|||||||
|
|
||||||
bool EthernetTap::addIP(const InetAddress &ip)
|
bool EthernetTap::addIP(const InetAddress &ip)
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_ips_m);
|
if (!ip.netmaskBits()) // sanity check... netmask of 0.0.0.0 is WUT?
|
||||||
|
|
||||||
if (_ips.count(ip))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (!ip.port())
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
std::set<InetAddress> haveIps(ips());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Add IP to interface at the netlink level if not already assigned.
|
||||||
|
if (!haveIps.count(ip)) {
|
||||||
std::pair<NET_LUID,NET_IFINDEX> ifidx = _findAdapterByGuid(_deviceGuid);
|
std::pair<NET_LUID,NET_IFINDEX> ifidx = _findAdapterByGuid(_deviceGuid);
|
||||||
MIB_UNICASTIPADDRESS_ROW ipr;
|
MIB_UNICASTIPADDRESS_ROW ipr;
|
||||||
|
|
||||||
@ -1259,6 +1259,7 @@ bool EthernetTap::addIP(const InetAddress &ip)
|
|||||||
ipr.Address.Ipv4.sin_addr.S_un.S_addr = *((const uint32_t *)ip.rawIpData());
|
ipr.Address.Ipv4.sin_addr.S_un.S_addr = *((const uint32_t *)ip.rawIpData());
|
||||||
ipr.OnLinkPrefixLength = ip.port();
|
ipr.OnLinkPrefixLength = ip.port();
|
||||||
} else if (ip.isV6()) {
|
} else if (ip.isV6()) {
|
||||||
|
// TODO
|
||||||
} else return false;
|
} else return false;
|
||||||
|
|
||||||
ipr.PrefixOrigin = IpPrefixOriginManual;
|
ipr.PrefixOrigin = IpPrefixOriginManual;
|
||||||
@ -1270,11 +1271,41 @@ bool EthernetTap::addIP(const InetAddress &ip)
|
|||||||
ipr.InterfaceIndex = ifidx.second;
|
ipr.InterfaceIndex = ifidx.second;
|
||||||
|
|
||||||
if (CreateUnicastIpAddressEntry(&ipr) == NO_ERROR) {
|
if (CreateUnicastIpAddressEntry(&ipr) == NO_ERROR) {
|
||||||
_ips.insert(ip);
|
haveIps.insert(ip);
|
||||||
return true;
|
} else {
|
||||||
|
LOG("unable to add IP address %s to interface %s: %d",ip.toString().c_str(),deviceName().c_str(),(int)GetLastError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch ( ... ) {}
|
|
||||||
|
|
||||||
|
// Update registry to contain all non-link-local IPs for this interface
|
||||||
|
std::string regMultiIps,regMultiNetmasks;
|
||||||
|
for(std::set<InetAddress>::const_iterator i(haveIps.begin());i!=haveIps.end();++i) {
|
||||||
|
if (!i->isLinkLocal()) {
|
||||||
|
regMultiIps.append(i->toIpString());
|
||||||
|
regMultiIps.push_back((char)0);
|
||||||
|
regMultiNetmasks.append(i->netmask().toIpString());
|
||||||
|
regMultiNetmasks.push_back((char)0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HKEY tcpIpInterfaces;
|
||||||
|
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces",0,KEY_READ|KEY_WRITE,&tcpIpInterfaces) == ERROR_SUCCESS) {
|
||||||
|
if (regMultiIps.length()) {
|
||||||
|
regMultiIps.push_back((char)0);
|
||||||
|
regMultiNetmasks.push_back((char)0);
|
||||||
|
RegSetKeyValueA(tcpIpInterfaces,_myDeviceInstanceId.c_str(),"IPAddress",REG_MULTI_SZ,regMultiIps.data(),(DWORD)regMultiIps.length());
|
||||||
|
RegSetKeyValueA(tcpIpInterfaces,_myDeviceInstanceId.c_str(),"SubnetMask",REG_MULTI_SZ,regMultiNetmasks.data(),(DWORD)regMultiNetmasks.length());
|
||||||
|
} else {
|
||||||
|
RegDeleteKeyValueA(tcpIpInterfaces,_myDeviceInstanceId.c_str(),"IPAddress");
|
||||||
|
RegDeleteKeyValueA(tcpIpInterfaces,_myDeviceInstanceId.c_str(),"SubnetMask");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RegCloseKey(tcpIpInterfaces);
|
||||||
|
} catch (std::exception &exc) {
|
||||||
|
LOG("unexpected exception adding IP address to %s: %s",ip.toString().c_str(),deviceName().c_str(),exc.what());
|
||||||
|
} catch ( ... ) {
|
||||||
|
LOG("unexpected exception adding IP address %s to %s: unknown exception",ip.toString().c_str(),deviceName().c_str());
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1283,7 +1314,6 @@ bool EthernetTap::removeIP(const InetAddress &ip)
|
|||||||
try {
|
try {
|
||||||
MIB_UNICASTIPADDRESS_TABLE *ipt = (MIB_UNICASTIPADDRESS_TABLE *)0;
|
MIB_UNICASTIPADDRESS_TABLE *ipt = (MIB_UNICASTIPADDRESS_TABLE *)0;
|
||||||
std::pair<NET_LUID,NET_IFINDEX> ifidx = _findAdapterByGuid(_deviceGuid);
|
std::pair<NET_LUID,NET_IFINDEX> ifidx = _findAdapterByGuid(_deviceGuid);
|
||||||
|
|
||||||
if (GetUnicastIpAddressTable(AF_UNSPEC,&ipt) == NO_ERROR) {
|
if (GetUnicastIpAddressTable(AF_UNSPEC,&ipt) == NO_ERROR) {
|
||||||
for(DWORD i=0;i<ipt->NumEntries;++i) {
|
for(DWORD i=0;i<ipt->NumEntries;++i) {
|
||||||
if ((ipt->Table[i].InterfaceLuid.Value == ifidx.first.Value)&&(ipt->Table[i].InterfaceIndex == ifidx.second)) {
|
if ((ipt->Table[i].InterfaceLuid.Value == ifidx.first.Value)&&(ipt->Table[i].InterfaceIndex == ifidx.second)) {
|
||||||
@ -1294,26 +1324,26 @@ bool EthernetTap::removeIP(const InetAddress &ip)
|
|||||||
break;
|
break;
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
addr.set(ipt->Table[i].Address.Ipv6.sin6_addr.u.Byte,16,ipt->Table[i].OnLinkPrefixLength);
|
addr.set(ipt->Table[i].Address.Ipv6.sin6_addr.u.Byte,16,ipt->Table[i].OnLinkPrefixLength);
|
||||||
|
if (addr.isLinkLocal())
|
||||||
|
continue; // can't remove link-local IPv6 addresses
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (addr == ip) {
|
if (addr == ip) {
|
||||||
DeleteUnicastIpAddressEntry(&(ipt->Table[i]));
|
DeleteUnicastIpAddressEntry(&(ipt->Table[i]));
|
||||||
FreeMibTable(ipt);
|
FreeMibTable(ipt);
|
||||||
Mutex::Lock _l(_ips_m);
|
|
||||||
_ips.erase(ip);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FreeMibTable(&ipt);
|
FreeMibTable((PVOID)ipt);
|
||||||
}
|
}
|
||||||
} catch ( ... ) {}
|
} catch ( ... ) {}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<InetAddress> EthernetTap::allIps() const
|
std::set<InetAddress> EthernetTap::ips() const
|
||||||
{
|
{
|
||||||
static const InetAddress ifLoopback("fe80::1",64);
|
static const InetAddress linkLocalLoopback("fe80::1",64); // what is this and why does Windows assign it?
|
||||||
std::set<InetAddress> addrs;
|
std::set<InetAddress> addrs;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -1324,12 +1354,14 @@ std::set<InetAddress> EthernetTap::allIps() const
|
|||||||
for(DWORD i=0;i<ipt->NumEntries;++i) {
|
for(DWORD i=0;i<ipt->NumEntries;++i) {
|
||||||
if ((ipt->Table[i].InterfaceLuid.Value == ifidx.first.Value)&&(ipt->Table[i].InterfaceIndex == ifidx.second)) {
|
if ((ipt->Table[i].InterfaceLuid.Value == ifidx.first.Value)&&(ipt->Table[i].InterfaceIndex == ifidx.second)) {
|
||||||
switch(ipt->Table[i].Address.si_family) {
|
switch(ipt->Table[i].Address.si_family) {
|
||||||
case AF_INET:
|
case AF_INET: {
|
||||||
addrs.insert(InetAddress(&(ipt->Table[i].Address.Ipv4.sin_addr.S_un.S_addr),4,ipt->Table[i].OnLinkPrefixLength));
|
InetAddress ip(&(ipt->Table[i].Address.Ipv4.sin_addr.S_un.S_addr),4,ipt->Table[i].OnLinkPrefixLength);
|
||||||
break;
|
if (ip != InetAddress::LO4)
|
||||||
|
addrs.insert(ip);
|
||||||
|
} break;
|
||||||
case AF_INET6: {
|
case AF_INET6: {
|
||||||
InetAddress ip(ipt->Table[i].Address.Ipv6.sin6_addr.u.Byte,16,ipt->Table[i].OnLinkPrefixLength);
|
InetAddress ip(ipt->Table[i].Address.Ipv6.sin6_addr.u.Byte,16,ipt->Table[i].OnLinkPrefixLength);
|
||||||
if (ip != ifLoopback) // don't include fe80::1
|
if ((ip != linkLocalLoopback)&&(ip != InetAddress::LO6))
|
||||||
addrs.insert(ip);
|
addrs.insert(ip);
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
@ -1372,8 +1404,8 @@ bool EthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups)
|
|||||||
// Ensure that groups are added for each IP... this handles the MAC:ADI
|
// 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
|
// 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
|
// up being duplicates of what the IOCTL returns but that's okay since
|
||||||
// the set will filter these.
|
// the set<> will filter that.
|
||||||
std::set<InetAddress> ipaddrs(allIps());
|
std::set<InetAddress> ipaddrs(ips());
|
||||||
for(std::set<InetAddress>::const_iterator i(ipaddrs.begin());i!=ipaddrs.end();++i)
|
for(std::set<InetAddress>::const_iterator i(ipaddrs.begin());i!=ipaddrs.end();++i)
|
||||||
newGroups.insert(MulticastGroup::deriveMulticastGroupForAddressResolution(*i));
|
newGroups.insert(MulticastGroup::deriveMulticastGroupForAddressResolution(*i));
|
||||||
|
|
||||||
|
@ -129,24 +129,17 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Remove an IP from this interface
|
* Remove an IP from this interface
|
||||||
*
|
*
|
||||||
|
* Link-local IP addresses may not be able to be removed, depending on platform and type.
|
||||||
|
*
|
||||||
* @param ip IP and netmask (netmask stored in port field)
|
* @param ip IP and netmask (netmask stored in port field)
|
||||||
* @return True if IP removed successfully
|
* @return True if IP removed successfully
|
||||||
*/
|
*/
|
||||||
bool removeIP(const InetAddress &ip);
|
bool removeIP(const InetAddress &ip);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Set of IP addresses / netmasks
|
* @return All IP addresses (V4 and V6) assigned to this interface (including link-local)
|
||||||
*/
|
*/
|
||||||
inline std::set<InetAddress> ips() const
|
std::set<InetAddress> ips() const;
|
||||||
{
|
|
||||||
Mutex::Lock _l(_ips_m);
|
|
||||||
return _ips;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Set of IP addresses / netmasks included any we did not assign, link-local, etc.
|
|
||||||
*/
|
|
||||||
std::set<InetAddress> allIps() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set this tap's IP addresses to exactly this set of IPs
|
* Set this tap's IP addresses to exactly this set of IPs
|
||||||
@ -208,15 +201,14 @@ private:
|
|||||||
|
|
||||||
const RuntimeEnvironment *_r;
|
const RuntimeEnvironment *_r;
|
||||||
|
|
||||||
std::set<InetAddress> _ips;
|
|
||||||
Mutex _ips_m;
|
|
||||||
|
|
||||||
void (*_handler)(void *,const MAC &,const MAC &,unsigned int,const Buffer<4096> &);
|
void (*_handler)(void *,const MAC &,const MAC &,unsigned int,const Buffer<4096> &);
|
||||||
void *_arg;
|
void *_arg;
|
||||||
|
|
||||||
Thread _thread;
|
Thread _thread;
|
||||||
|
|
||||||
#ifdef __UNIX_LIKE__
|
#ifdef __UNIX_LIKE__
|
||||||
|
std::set<InetAddress> _ips;
|
||||||
|
Mutex _ips_m;
|
||||||
char _dev[16];
|
char _dev[16];
|
||||||
int _fd;
|
int _fd;
|
||||||
int _shutdownSignalPipe[2];
|
int _shutdownSignalPipe[2];
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Constants.hpp"
|
#include "Constants.hpp"
|
||||||
|
#include "Utils.hpp"
|
||||||
|
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
#include <WinSock2.h>
|
#include <WinSock2.h>
|
||||||
@ -188,6 +189,28 @@ public:
|
|||||||
_sa.sin6.sin6_port = htons((uint16_t)port);
|
_sa.sin6.sin6_port = htons((uint16_t)port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return True if this is a link-local IP address
|
||||||
|
*/
|
||||||
|
inline bool isLinkLocal() const
|
||||||
|
throw()
|
||||||
|
{
|
||||||
|
if (_sa.saddr.sa_family == AF_INET)
|
||||||
|
return ((Utils::ntoh((uint32_t)_sa.sin.sin_addr.s_addr) & 0xffff0000) == 0xa9fe0000);
|
||||||
|
else if (_sa.saddr.sa_family == AF_INET6) {
|
||||||
|
if (_sa.sin6.sin6_addr.s6_addr[0] != 0xfe) return false;
|
||||||
|
if (_sa.sin6.sin6_addr.s6_addr[1] != 0x80) return false;
|
||||||
|
if (_sa.sin6.sin6_addr.s6_addr[2] != 0x00) return false;
|
||||||
|
if (_sa.sin6.sin6_addr.s6_addr[3] != 0x00) return false;
|
||||||
|
if (_sa.sin6.sin6_addr.s6_addr[4] != 0x00) return false;
|
||||||
|
if (_sa.sin6.sin6_addr.s6_addr[5] != 0x00) return false;
|
||||||
|
if (_sa.sin6.sin6_addr.s6_addr[6] != 0x00) return false;
|
||||||
|
if (_sa.sin6.sin6_addr.s6_addr[7] != 0x00) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ASCII IP/port format representation
|
* @return ASCII IP/port format representation
|
||||||
*/
|
*/
|
||||||
@ -233,6 +256,31 @@ public:
|
|||||||
return port();
|
return port();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a full netmask as an InetAddress
|
||||||
|
*/
|
||||||
|
inline InetAddress netmask() const
|
||||||
|
throw()
|
||||||
|
{
|
||||||
|
InetAddress r(*this);
|
||||||
|
switch(_sa.saddr.sa_family) {
|
||||||
|
case AF_INET:
|
||||||
|
r._sa.sin.sin_addr.s_addr = Utils::hton((uint32_t)(0xffffffff << (32 - netmaskBits())));
|
||||||
|
break;
|
||||||
|
case AF_INET6: {
|
||||||
|
unsigned char *bf = (unsigned char *)r._sa.sin6.sin6_addr.s6_addr;
|
||||||
|
signed int bitsLeft = (signed int)netmaskBits();
|
||||||
|
for(unsigned int i=0;i<16;++i) {
|
||||||
|
if (bitsLeft > 0) {
|
||||||
|
bf[i] = (unsigned char)((bitsLeft >= 8) ? 0xff : (0xff << (8 - bitsLeft)));
|
||||||
|
bitsLeft -= 8;
|
||||||
|
} else bf[i] = (unsigned char)0;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return True if this is an IPv4 address
|
* @return True if this is an IPv4 address
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user