summaryrefslogtreecommitdiff
path: root/osdep
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2016-06-17 13:14:48 -0700
committerAdam Ierymenko <adam.ierymenko@gmail.com>2016-06-17 13:14:48 -0700
commit3ee15e65aa14a8aa661c522c5fb183a0fdfed8b3 (patch)
tree8ef98e2ef9163a738483cd65095ebfd4e0d2c89b /osdep
parent1bf1c38b30a12472d9cb2f36718ba69c9d43abe0 (diff)
downloadinfinitytier-3ee15e65aa14a8aa661c522c5fb183a0fdfed8b3.tar.gz
infinitytier-3ee15e65aa14a8aa661c522c5fb183a0fdfed8b3.zip
Tying up default route and route mgmt loose ends. It now periodically updates shadow routes so hopefully your link will stay up as you move around.
Diffstat (limited to 'osdep')
-rw-r--r--osdep/ManagedRoute.cpp77
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);
-}
-*/