diff options
Diffstat (limited to 'osdep')
-rw-r--r-- | osdep/ManagedRoute.cpp | 77 |
1 files changed, 45 insertions, 32 deletions
diff --git a/osdep/ManagedRoute.cpp b/osdep/ManagedRoute.cpp index 62597a00..bffaf0b1 100644 --- a/osdep/ManagedRoute.cpp +++ b/osdep/ManagedRoute.cpp @@ -273,20 +273,25 @@ static void _routeCmd(const char *op,const InetAddress &target,const InetAddress bool ManagedRoute::sync() { - if (_target.isDefaultRoute()) { - /* In ZeroTier we use a forked-route trick to override the default - * with a more specific one while leaving the original system route - * intact. We also create a shadow more specific route to the - * original gateway that is device-bound so that ZeroTier's device - * bound ports go via the physical Internet link. This has to be - * done *slightly* differently on different platforms. */ - + if ((_target.isDefaultRoute())||((_target.ss_family == AF_INET)&&(_target.netmaskBits() < 32))) { + /* In ZeroTier we create two more specific routes for every one route. We + * do this for default routes and IPv4 routes other than /32s. If there + * is a pre-existing system route that this route will override, we create + * two more specific interface-bound shadow routes for it. + * + * This means that ZeroTier can *itself* continue communicating over + * whatever physical routes might be present while simultaneously + * overriding them for general system traffic. This is mostly for + * "full tunnel" VPN modes of operation, but might be useful for + * virtualizing physical networks in a hybrid design as well. */ + + // Generate two more specific routes than target with one extra bit InetAddress leftt,rightt; _forkTarget(_target,leftt,rightt); #ifdef __BSD__ // ------------------------------------------------------------ - // Get system default route information + // Find lowest metric system route that this route should override (if any) InetAddress newSystemVia; char newSystemDevice[128]; newSystemDevice[0] = (char)0; @@ -296,12 +301,12 @@ bool ManagedRoute::sync() if (r->via) { if ((!newSystemVia)||(r->metric < systemMetric)) { newSystemVia = r->via; - Utils::scopy(_systemDevice,sizeof(_systemDevice),r->device); + Utils::scopy(newSystemDevice,sizeof(newSystemDevice),r->device); systemMetric = r->metric; } } } - if (!newSystemDevice[0]) { + if ((newSystemVia)&&(!newSystemDevice[0])) { rtes = _getRTEs(newSystemVia,true); for(std::vector<_RTE>::iterator r(rtes.begin());r!=rtes.end();++r) { if (r->device[0]) { @@ -310,10 +315,10 @@ bool ManagedRoute::sync() } } } - if ((!newSystemVia)||(!newSystemDevice[0])) - return false; - // If system default route has changed or hasn't been shadowed yet, update shadow + // Shadow system route if it exists, also delete any obsolete shadows + // and replace them with the new state. sync() is called periodically to + // allow us to do that if underlying connectivity changes. if ((_systemVia != newSystemVia)||(!strcmp(_systemDevice,newSystemDevice))) { if ((_systemVia)&&(_systemDevice[0])) { _routeCmd("delete",leftt,_systemVia,_systemDevice,(const char *)0); @@ -323,13 +328,15 @@ bool ManagedRoute::sync() _systemVia = newSystemVia; Utils::scopy(_systemDevice,sizeof(_systemDevice),newSystemDevice); - _routeCmd("add",leftt,_systemVia,_systemDevice,(const char *)0); - _routeCmd("change",leftt,_systemVia,_systemDevice,(const char *)0); - _routeCmd("add",rightt,_systemVia,_systemDevice,(const char *)0); - _routeCmd("change",rightt,_systemVia,_systemDevice,(const char *)0); + if ((_systemVia)&&(_systemDevice[0])) { + _routeCmd("add",leftt,_systemVia,_systemDevice,(const char *)0); + _routeCmd("change",leftt,_systemVia,_systemDevice,(const char *)0); + _routeCmd("add",rightt,_systemVia,_systemDevice,(const char *)0); + _routeCmd("change",rightt,_systemVia,_systemDevice,(const char *)0); + } } - // Apply overriding routes + // Apply overriding non-device-scoped routes if (!_applied) { if (_via) { _routeCmd("add",leftt,_via,(const char *)0,(const char *)0); @@ -357,11 +364,22 @@ bool ManagedRoute::sync() #endif // __WINDOWS__ -------------------------------------------------------- } else { - - // TODO + /* For non-default routes, IPv4 /32, and IPv6 non-default routes, we just + * add the route itself. */ #ifdef __BSD__ // ------------------------------------------------------------ + if (!_applied) { + if (_via) { + _routeCmd("add",_target,_via,(const char *)0,(const char *)0); + _routeCmd("change",_target,_via,(const char *)0,(const char *)0); + } else if (_device[0]) { + _routeCmd("add",_target,_via,(const char *)0,_device); + _routeCmd("change",_target,_via,(const char *)0,_device); + } + _applied = true; + } + #endif // __BSD__ ------------------------------------------------------------ #ifdef __LINUX__ // ---------------------------------------------------------- @@ -418,10 +436,14 @@ void ManagedRoute::remove() } else { - // TODO - #ifdef __BSD__ // ------------------------------------------------------------ + if (_via) { + _routeCmd("delete",_target,_via,(const char *)0,(const char *)0); + } else if (_device[0]) { + _routeCmd("delete",_target,_via,(const char *)0,_device); + } + #endif // __BSD__ ------------------------------------------------------------ #ifdef __LINUX__ // ---------------------------------------------------------- @@ -444,12 +466,3 @@ void ManagedRoute::remove() } } // namespace ZeroTier - -/* -int main(int argc,char **argv) -{ - ZeroTier::ManagedRoute t; - t.set(ZeroTier::InetAddress("0.0.0.0/0"),ZeroTier::InetAddress("10.6.6.112"),"zt2"); - sleep(10000); -} -*/ |