summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
Diffstat (limited to 'service')
-rw-r--r--service/OneService.cpp246
1 files changed, 123 insertions, 123 deletions
diff --git a/service/OneService.cpp b/service/OneService.cpp
index 45f4234e..865a849e 100644
--- a/service/OneService.cpp
+++ b/service/OneService.cpp
@@ -527,6 +527,7 @@ public:
NetworkState() : tap((EthernetTap *)0),managedIps(),managedRoutes(),allowManaged(true),allowGlobal(true),allowDefault(true) {}
EthernetTap *tap;
+ ZT_VirtualNetworkConfig config; // memcpy() of raw config from core
std::vector<InetAddress> managedIps;
std::list<ManagedRoute> managedRoutes;
bool allowManaged; // allow managed addresses and routes
@@ -851,7 +852,7 @@ public:
restarted = true;
}
- // Refresh bindings in case device's interfaces have changed
+ // Refresh bindings in case device's interfaces have changed, and also sync routes to update any shadow routes (e.g. shadow default)
if (((now - lastBindRefresh) >= ZT_BINDER_REFRESH_PERIOD)||(restarted)) {
lastBindRefresh = now;
for(int i=0;i<3;++i) {
@@ -859,6 +860,13 @@ public:
_bindings[i].refresh(_phy,_ports[i],*this);
}
}
+ {
+ Mutex::Lock _l(_nets_m);
+ for(std::map<uint64_t,NetworkState>::iterator n(_nets.begin());n!=_nets.end();++n) {
+ if (n->second.tap)
+ syncManagedStuff(n->second,false,true);
+ }
+ }
}
uint64_t dl = _nextBackgroundTaskDeadline;
@@ -985,6 +993,118 @@ public:
// Begin private implementation methods
+ // Checks if a managed IP or route target is allowed
+ bool checkIfManagedIsAllowed(const NetworkState &n,const InetAddress &addr)
+ {
+ if (!n.allowManaged)
+ return false;
+ if (addr.isDefaultRoute())
+ return n.allowDefault;
+ switch(addr.ipScope()) {
+ case InetAddress::IP_SCOPE_NONE:
+ case InetAddress::IP_SCOPE_MULTICAST:
+ case InetAddress::IP_SCOPE_LOOPBACK:
+ case InetAddress::IP_SCOPE_LINK_LOCAL:
+ return false;
+ case InetAddress::IP_SCOPE_GLOBAL:
+ return n.allowGlobal;
+ default:
+ return true;
+ }
+ }
+
+ // Apply or update managed IPs for a configured network (be sure n.tap exists)
+ void syncManagedStuff(NetworkState &n,bool syncIps,bool syncRoutes)
+ {
+ if (syncIps) {
+ std::vector<InetAddress> newManagedIps;
+ newManagedIps.reserve(n.config.assignedAddressCount);
+ for(unsigned int i=0;i<n.config.assignedAddressCount;++i) {
+ const InetAddress *ii = reinterpret_cast<const InetAddress *>(&(n.config.assignedAddresses[i]));
+ if (checkIfManagedIsAllowed(n,*ii))
+ newManagedIps.push_back(*ii);
+ }
+ std::sort(newManagedIps.begin(),newManagedIps.end());
+ newManagedIps.erase(std::unique(newManagedIps.begin(),newManagedIps.end()),newManagedIps.end());
+
+ for(std::vector<InetAddress>::iterator ip(newManagedIps.begin());ip!=newManagedIps.end();++ip) {
+ if (std::find(n.managedIps.begin(),n.managedIps.end(),*ip) == n.managedIps.end()) {
+ if (!n.tap->addIp(*ip))
+ fprintf(stderr,"ERROR: unable to add ip address %s"ZT_EOL_S, ip->toString().c_str());
+ }
+ }
+ for(std::vector<InetAddress>::iterator ip(n.managedIps.begin());ip!=n.managedIps.end();++ip) {
+ if (std::find(newManagedIps.begin(),newManagedIps.end(),*ip) == newManagedIps.end()) {
+ if (!n.tap->removeIp(*ip))
+ fprintf(stderr,"ERROR: unable to remove ip address %s"ZT_EOL_S, ip->toString().c_str());
+ }
+ }
+
+ n.managedIps.swap(newManagedIps);
+ }
+
+ if (syncRoutes) {
+ const std::string tapdev(n.tap->deviceName());
+
+ // Nuke applied routes that are no longer in n.config.routes[] and/or are not allowed
+ for(std::list<ManagedRoute>::iterator mr(n.managedRoutes.begin());mr!=n.managedRoutes.end();) {
+ bool haveRoute = false;
+ if (checkIfManagedIsAllowed(n,mr->target())) {
+ for(unsigned int i=0;i<n.config.routeCount;++i) {
+ const InetAddress *const target = reinterpret_cast<const InetAddress *>(&(n.config.routes[i].target));
+ const InetAddress *const via = reinterpret_cast<const InetAddress *>(&(n.config.routes[i].via));
+ if ( (mr->target() == *target) && ( ((via->ss_family == target->ss_family)&&(mr->via() == *via)) || (tapdev == mr->device()) ) ) {
+ haveRoute = true;
+ break;
+ }
+ }
+ }
+ if (haveRoute) {
+ ++mr;
+ } else {
+ n.managedRoutes.erase(mr++);
+ }
+ }
+
+ // Apply routes in n.config.routes[] that we haven't applied yet, and sync those we have in case shadow routes need to change
+ for(unsigned int i=0;i<n.config.routeCount;++i) {
+ const InetAddress *const target = reinterpret_cast<const InetAddress *>(&(n.config.routes[i].target));
+ const InetAddress *const via = reinterpret_cast<const InetAddress *>(&(n.config.routes[i].via));
+
+ if (!checkIfManagedIsAllowed(n,*target))
+ continue;
+
+ bool haveRoute = false;
+
+ // Ignore routes implied by local managed IPs since adding the IP adds the route
+ for(std::vector<InetAddress>::iterator ip(n.managedIps.begin());ip!=n.managedIps.end();++ip) {
+ if ((target->netmaskBits() == ip->netmaskBits())&&(target->containsAddress(*ip))) {
+ haveRoute = true;
+ break;
+ }
+ }
+ if (haveRoute)
+ continue;
+
+ // If we've already applied this route, just sync it and continue
+ for(std::list<ManagedRoute>::iterator mr(n.managedRoutes.begin());mr!=n.managedRoutes.end();++mr) {
+ if ( (mr->target() == *target) && ( ((via->ss_family == target->ss_family)&&(mr->via() == *via)) || (tapdev == mr->device()) ) ) {
+ haveRoute = true;
+ mr->sync();
+ break;
+ }
+ }
+ if (haveRoute)
+ continue;
+
+ // Add and apply new routes
+ n.managedRoutes.push_back(ManagedRoute());
+ if (!n.managedRoutes.back().set(*target,*via,tapdev.c_str()))
+ n.managedRoutes.pop_back();
+ }
+ }
+ }
+
inline void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len)
{
#ifdef ZT_ENABLE_CLUSTER
@@ -1256,129 +1376,9 @@ public:
// After setting up tap, fall through to CONFIG_UPDATE since we also want to do this...
case ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE:
+ memcpy(&(n.config),nwc,sizeof(ZT_VirtualNetworkConfig));
if (n.tap) { // sanity check
- if (n.allowManaged) {
-
- { // configure managed IP addresses
- std::vector<InetAddress> newManagedIps;
- for(unsigned int i=0;i<nwc->assignedAddressCount;++i) {
- const InetAddress *ii = reinterpret_cast<const InetAddress *>(&(nwc->assignedAddresses[i]));
- switch(ii->ipScope()) {
- case InetAddress::IP_SCOPE_NONE:
- case InetAddress::IP_SCOPE_MULTICAST:
- case InetAddress::IP_SCOPE_LOOPBACK:
- case InetAddress::IP_SCOPE_LINK_LOCAL:
- break; // ignore these -- they shouldn't appear here
- case InetAddress::IP_SCOPE_GLOBAL:
- if (!n.allowGlobal)
- continue; // skip global IP ranges if we haven't given this network permission to assign them
- // else fall through for PSEUDOPRIVATE, SHARED, PRIVATE
- default:
- newManagedIps.push_back(*ii);
- break;
- }
- }
- std::sort(newManagedIps.begin(),newManagedIps.end());
- newManagedIps.erase(std::unique(newManagedIps.begin(),newManagedIps.end()),newManagedIps.end());
-
- for(std::vector<InetAddress>::iterator ip(newManagedIps.begin());ip!=newManagedIps.end();++ip) {
- if (std::find(n.managedIps.begin(),n.managedIps.end(),*ip) == n.managedIps.end()) {
- if (!n.tap->addIp(*ip))
- fprintf(stderr,"ERROR: unable to add ip address %s"ZT_EOL_S, ip->toString().c_str());
- }
- }
- for(std::vector<InetAddress>::iterator ip(n.managedIps.begin());ip!=n.managedIps.end();++ip) {
- if (std::find(newManagedIps.begin(),newManagedIps.end(),*ip) == newManagedIps.end()) {
- if (!n.tap->removeIp(*ip))
- fprintf(stderr,"ERROR: unable to remove ip address %s"ZT_EOL_S, ip->toString().c_str());
- }
- }
-
- n.managedIps.swap(newManagedIps);
- }
-
- { // configure managed routes
- const std::string tapdev(n.tap->deviceName());
-
- for(std::list<ManagedRoute>::iterator mr(n.managedRoutes.begin());mr!=n.managedRoutes.end();) {
- bool haveRoute = false;
- for(unsigned int i=0;i<nwc->routeCount;++i) {
- const InetAddress *const target = reinterpret_cast<const InetAddress *>(&(nwc->routes[i].target));
- const InetAddress *const via = reinterpret_cast<const InetAddress *>(&(nwc->routes[i].via));
- if (mr->target() == *target) {
- if ((via->ss_family == target->ss_family)&&(mr->via() == *via)) {
- haveRoute = true;
- break;
- } else if (tapdev == mr->device()) {
- haveRoute = true;
- break;
- }
- }
- }
- if (haveRoute) {
- ++mr;
- } else {
- n.managedRoutes.erase(mr++); // also removes route via RAII behavior
- }
- }
-
- for(unsigned int i=0;i<nwc->routeCount;++i) {
- const InetAddress *const target = reinterpret_cast<const InetAddress *>(&(nwc->routes[i].target));
- const InetAddress *const via = reinterpret_cast<const InetAddress *>(&(nwc->routes[i].via));
-
- bool haveRoute = false;
-
- // We don't need to bother applying local routes to local managed IPs since these are implied by setting the IP
- for(std::vector<InetAddress>::iterator ip(n.managedIps.begin());ip!=n.managedIps.end();++ip) {
- if ((target->netmaskBits() == ip->netmaskBits())&&(target->containsAddress(*ip))) {
- haveRoute = true;
- break;
- }
- }
-
- if (haveRoute)
- continue;
-
- for(std::list<ManagedRoute>::iterator mr(n.managedRoutes.begin());mr!=n.managedRoutes.end();++mr) {
- if (mr->target() == *target) {
- if ((via->ss_family == target->ss_family)&&(mr->via() == *via)) {
- haveRoute = true;
- break;
- } else if (tapdev == mr->device()) {
- haveRoute = true;
- break;
- }
- }
- }
-
- if (haveRoute)
- continue;
-
- n.managedRoutes.push_back(ManagedRoute());
- if ((target->isDefaultRoute())&&(n.allowDefault)) {
- if (!n.managedRoutes.back().set(*target,*via,tapdev.c_str()))
- n.managedRoutes.pop_back();
- } else {
- switch(target->ipScope()) {
- case InetAddress::IP_SCOPE_NONE:
- case InetAddress::IP_SCOPE_MULTICAST:
- case InetAddress::IP_SCOPE_LOOPBACK:
- case InetAddress::IP_SCOPE_LINK_LOCAL:
- break;
- case InetAddress::IP_SCOPE_GLOBAL:
- if (!n.allowGlobal)
- continue; // skip global IP ranges if we haven't given this network permission to assign them
- // else fall through for PSEUDOPRIVATE, SHARED, PRIVATE
- default:
- if (!n.managedRoutes.back().set(*target,*via,tapdev.c_str()))
- n.managedRoutes.pop_back();
- break;
- }
- }
- }
- }
-
- }
+ syncManagedStuff(n,true,true);
} else {
_nets.erase(nwid);
return -999; // tap init failed