diff --git a/osdep/ManagedRoute.cpp b/osdep/ManagedRoute.cpp index 3094c32d1..cf727fd95 100644 --- a/osdep/ManagedRoute.cpp +++ b/osdep/ManagedRoute.cpp @@ -388,6 +388,29 @@ static bool _winHasRoute(const NET_LUID &interfaceLuid, const NET_IFINDEX &inter } // anonymous namespace +ManagedRoute::ManagedRoute(const InetAddress &target,const InetAddress &via,const InetAddress &src,const char *device) +{ + _target = target; + _via = via; + _src = src; + if (via.ss_family == AF_INET) + _via.setPort(32); + else if (via.ss_family == AF_INET6) + _via.setPort(128); + if (src.ss_family == AF_INET) { + _src.setPort(32); + } else if (src.ss_family == AF_INET6) { + _src.setPort(128); + } + Utils::scopy(_device,sizeof(_device),device); + _systemDevice[0] = (char)0; +} + +ManagedRoute::~ManagedRoute() +{ + this->remove(); +} + /* Linux NOTE: for default route override, some Linux distributions will * require a change to the rp_filter parameter. A value of '1' will prevent * default route override from working properly. diff --git a/osdep/ManagedRoute.hpp b/osdep/ManagedRoute.hpp index 9cdf3f264..004aea48f 100644 --- a/osdep/ManagedRoute.hpp +++ b/osdep/ManagedRoute.hpp @@ -36,28 +36,8 @@ class ManagedRoute friend class SharedPtr; public: - ManagedRoute(const InetAddress &target,const InetAddress &via,const InetAddress &src,const char *device) - { - _target = target; - _via = via; - _src = src; - if (via.ss_family == AF_INET) - _via.setPort(32); - else if (via.ss_family == AF_INET6) - _via.setPort(128); - if (src.ss_family == AF_INET) { - _src.setPort(32); - } else if (src.ss_family == AF_INET6) { - _src.setPort(128); - } - Utils::scopy(_device,sizeof(_device),device); - _systemDevice[0] = (char)0; - } - - ~ManagedRoute() - { - this->remove(); - } + ManagedRoute(const InetAddress &target,const InetAddress &via,const InetAddress &src,const char *device); + ~ManagedRoute(); /** * Set or update currently set route diff --git a/service/OneService.cpp b/service/OneService.cpp index c37f09001..5b3ec7f29 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -529,7 +529,7 @@ public: std::shared_ptr tap; ZT_VirtualNetworkConfig config; // memcpy() of raw config from core std::vector managedIps; - std::list< SharedPtr > managedRoutes; + std::map< InetAddress, SharedPtr > managedRoutes; NetworkSettings settings; }; std::map _nets; @@ -1932,15 +1932,72 @@ public: } if (syncRoutes) { - char tapdev[64]; + // Get tap device name (use LUID in hex on Windows) and IP addresses. + char tapdevbuf[64]; + std::string tapdev; #if defined(__WINDOWS__) && !defined(ZT_SDK) - OSUtils::ztsnprintf(tapdev,sizeof(tapdev),"%.16llx",(unsigned long long)((WindowsEthernetTap *)(n.tap.get()))->luid().Value); + OSUtils::ztsnprintf(tapdevbuf,sizeof(tapdevbuf),"%.16llx",(unsigned long long)((WindowsEthernetTap *)(n.tap.get()))->luid().Value); + tapdev = tapdevbuf; #else - Utils::scopy(tapdev,sizeof(tapdev),n.tap->deviceName().c_str()); + tapdev = n.tap->deviceName(); #endif - std::vector myIps(n.tap->ips()); + // Add routes not already added. + std::set haveRouteTargets; + for(unsigned int i=0;i(&(n.config.routes[i].target)); + const InetAddress *const via = reinterpret_cast(&(n.config.routes[i].via)); + + const InetAddress *src = NULL; + for (unsigned int j=0; j(&(n.config.assignedAddresses[j])); + if (target->isV4() && tmp->isV4()) { + src = reinterpret_cast(&(n.config.assignedAddresses[j])); + break; + } else if (target->isV6() && tmp->isV6()) { + src = reinterpret_cast(&(n.config.assignedAddresses[j])); + break; + } + } + if (!src) + src = &NULL_INET_ADDR; + + if ( (!checkIfManagedIsAllowed(n,*target)) || ((via->ss_family == target->ss_family)&&(matchIpOnly(myIps,*via))) ) + continue; + + // Ignore routes implied by local managed IPs since adding the IP adds the route +#ifndef __APPLE__ + bool haveRoute = false; + for(std::vector::iterator ip(n.managedIps.begin());ip!=n.managedIps.end();++ip) { + if ((target->netmaskBits() == ip->netmaskBits())&&(target->containsAddress(*ip))) { + haveRoute = true; + break; + } + } + if (haveRoute) + continue; +#endif + + haveRouteTargets.insert(*target); + +#ifndef ZT_SDK + SharedPtr &mr = n.managedRoutes[*target]; + if (!mr) + mr.set(new ManagedRoute(*target, *via, *src, tapdev.c_str())); + mr->sync(); +#endif + } + + // Destroy managed routes no longer in n.managedRoutes. + for(std::map< InetAddress, SharedPtr >::iterator r(n.managedRoutes.begin());r!=n.managedRoutes.end();) { + if (haveRouteTargets.find(r->first) == haveRouteTargets.end()) + n.managedRoutes.erase(r++); + else ++r; + } + + // This is the old logic for applying managed routes, and is kept around for now for documentation purposes. +#if 0 // Nuke applied routes that are no longer in n.config.routes[] and/or are not allowed for(std::list< SharedPtr >::iterator mr(n.managedRoutes.begin());mr!=n.managedRoutes.end();) { bool haveRoute = false; @@ -2014,6 +2071,7 @@ public: n.managedRoutes.pop_back(); #endif } +#endif // end old managed route apply logic } if (syncDns) {