Save enumeration of statically assigned IPs so they will always be reassigned on device "power cycle."

This commit is contained in:
Adam Ierymenko 2015-07-30 14:10:32 -07:00
parent 499b2dccad
commit 922d9657b9
3 changed files with 76 additions and 51 deletions

View file

@ -639,63 +639,28 @@ bool WindowsEthernetTap::enabled() const
bool WindowsEthernetTap::addIp(const InetAddress &ip)
{
if (!_initialized)
return false;
if (!ip.netmaskBits()) // sanity check... netmask of 0.0.0.0 is WUT?
return false;
std::vector<InetAddress> haveIps(ips());
try {
// Add IP to interface at the netlink level if not already assigned.
if (!std::binary_search(haveIps.begin(),haveIps.end(),ip)) {
MIB_UNICASTIPADDRESS_ROW ipr;
InitializeUnicastIpAddressEntry(&ipr);
if (ip.isV4()) {
ipr.Address.Ipv4.sin_family = AF_INET;
ipr.Address.Ipv4.sin_addr.S_un.S_addr = *((const uint32_t *)ip.rawIpData());
ipr.OnLinkPrefixLength = ip.port();
if (ipr.OnLinkPrefixLength >= 32)
return false;
} else if (ip.isV6()) {
ipr.Address.Ipv6.sin6_family = AF_INET6;
memcpy(ipr.Address.Ipv6.sin6_addr.u.Byte,ip.rawIpData(),16);
ipr.OnLinkPrefixLength = ip.port();
if (ipr.OnLinkPrefixLength >= 128)
return false;
} else return false;
ipr.PrefixOrigin = IpPrefixOriginManual;
ipr.SuffixOrigin = IpSuffixOriginManual;
ipr.ValidLifetime = 0xffffffff;
ipr.PreferredLifetime = 0xffffffff;
ipr.InterfaceLuid = _deviceLuid;
ipr.InterfaceIndex = _getDeviceIndex();
if (CreateUnicastIpAddressEntry(&ipr) != NO_ERROR)
return false;
}
std::vector<std::string> regIps(_getRegistryIPv4Value("IPAddress"));
if (std::find(regIps.begin(),regIps.end(),ip.toIpString()) == regIps.end()) {
std::vector<std::string> regSubnetMasks(_getRegistryIPv4Value("SubnetMask"));
regIps.push_back(ip.toIpString());
regSubnetMasks.push_back(ip.netmask().toIpString());
_setRegistryIPv4Value("IPAddress",regIps);
_setRegistryIPv4Value("SubnetMask",regSubnetMasks);
}
} catch ( ... ) {
return false;
}
Mutex::Lock _l(_assignedIps_m);
if (std::find(_assignedIps.begin(),_assignedIps.end(),ip) != _assignedIps.end())
return true;
_assignedIps.push_back(ip);
_syncIps();
return true;
}
bool WindowsEthernetTap::removeIp(const InetAddress &ip)
{
{
Mutex::Lock _l(_assignedIps_m);
std::vector<InetAddress>::iterator aip(std::find(_assignedIps.begin(),_assignedIps.end(),ip));
if (aip != _assignedIps.end())
_assignedIps.erase(aip);
}
if (!_initialized)
return false;
try {
MIB_UNICASTIPADDRESS_TABLE *ipt = (MIB_UNICASTIPADDRESS_TABLE *)0;
if (GetUnicastIpAddressTable(AF_UNSPEC,&ipt) == NO_ERROR) {
@ -972,6 +937,12 @@ void WindowsEthernetTap::threadMain()
}
#endif
// Assign or re-assign any should-be-assigned IPs in case we have restarted
{
Mutex::Lock _l(_assignedIps_m);
_syncIps();
}
memset(&tapOvlRead,0,sizeof(tapOvlRead));
tapOvlRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
memset(&tapOvlWrite,0,sizeof(tapOvlWrite));
@ -1135,4 +1106,55 @@ void WindowsEthernetTap::_setRegistryIPv4Value(const char *regKey,const std::vec
}
}
void WindowsEthernetTap::_syncIps()
{
// assumes _assignedIps_m is locked
if (!_initialized)
return;
std::vector<InetAddress> haveIps(ips());
for(std::vector<InetAddress>::const_iterator aip(_assignedIps.begin());aip!=_assignedIps.end();++aip) {
if (std::find(haveIps.begin(),haveIps.end(),*aip) == haveIps.end()) {
MIB_UNICASTIPADDRESS_ROW ipr;
InitializeUnicastIpAddressEntry(&ipr);
if (aip->isV4()) {
ipr.Address.Ipv4.sin_family = AF_INET;
ipr.Address.Ipv4.sin_addr.S_un.S_addr = *((const uint32_t *)aip->rawIpData());
ipr.OnLinkPrefixLength = aip->netmaskBits();
if (ipr.OnLinkPrefixLength >= 32)
continue;
} else if (aip->isV6()) {
ipr.Address.Ipv6.sin6_family = AF_INET6;
memcpy(ipr.Address.Ipv6.sin6_addr.u.Byte,aip->rawIpData(),16);
ipr.OnLinkPrefixLength = aip->netmaskBits();
if (ipr.OnLinkPrefixLength >= 128)
continue;
} else continue;
ipr.PrefixOrigin = IpPrefixOriginManual;
ipr.SuffixOrigin = IpSuffixOriginManual;
ipr.ValidLifetime = 0xffffffff;
ipr.PreferredLifetime = 0xffffffff;
ipr.InterfaceLuid = _deviceLuid;
ipr.InterfaceIndex = _getDeviceIndex();
CreateUnicastIpAddressEntry(&ipr);
}
std::string ipStr(aip->toString());
std::vector<std::string> regIps(_getRegistryIPv4Value("IPAddress"));
if (std::find(regIps.begin(),regIps.end(),ipStr) == regIps.end()) {
std::vector<std::string> regSubnetMasks(_getRegistryIPv4Value("SubnetMask"));
regIps.push_back(ipStr);
regSubnetMasks.push_back(aip->netmask().toIpString());
_setRegistryIPv4Value("IPAddress",regIps);
_setRegistryIPv4Value("SubnetMask",regSubnetMasks);
}
}
}
} // namespace ZeroTier