Răsfoiți Sursa

Apply default route a different way - macOS

The original way we applied default route, by forking
0.0.0.0/0 into 0/1 and 128/1 works, but if mac os has any networking
hiccups -if you change SSIDs or sleep/wake- macos erases the system default route.
And then all networking on the computer is broken.

to summarize the new way:
allowDefault=1
```
sudo route delete default 192.168.82.1
sudo route add default 10.2.0.2
sudo route add -ifscope en1 default 192.168.82.1
```

gives us this routing table
```
Destination        Gateway            RT_IFA             Flags        Refs      Use    Mtu          Netif Expire    rtt(ms) rttvar(ms)
default            10.2.0.2           10.2.0.18          UGScg          90        1   2800       feth4823
default            192.168.82.1       192.168.82.217     UGScIg
```

allowDefault=0
```
sudo route delete default
sudo route delete -ifscope en1 default
sudo route add default 192.168.82.1
```

Notice the I flag, for -ifscope, on the physical default route.

route change does not seem to work reliably.
travis laduke 2 ani în urmă
părinte
comite
22ab673480
1 a modificat fișierele cu 77 adăugiri și 63 ștergeri
  1. 77 63
      osdep/ManagedRoute.cpp

+ 77 - 63
osdep/ManagedRoute.cpp

@@ -12,6 +12,7 @@
 /****/
 /****/
 
 
 #include "../node/Constants.hpp"
 #include "../node/Constants.hpp"
+#include "../osdep/OSUtils.hpp"
 
 
 #include <stdint.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdio.h>
@@ -94,6 +95,7 @@ struct _RTE
 	char device[128];
 	char device[128];
 	int metric;
 	int metric;
 	bool ifscope;
 	bool ifscope;
+	bool isDefault;
 };
 };
 
 
 #ifdef __BSD__ // ------------------------------------------------------------
 #ifdef __BSD__ // ------------------------------------------------------------
@@ -127,6 +129,7 @@ static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains)
 
 
 					InetAddress sa_t,sa_v;
 					InetAddress sa_t,sa_v;
 					int deviceIndex = -9999;
 					int deviceIndex = -9999;
+					bool isDefault = false;
 
 
 					if (((rtm->rtm_flags & RTF_LLINFO) == 0)&&((rtm->rtm_flags & RTF_HOST) == 0)&&((rtm->rtm_flags & RTF_UP) != 0)&&((rtm->rtm_flags & RTF_MULTICAST) == 0)) {
 					if (((rtm->rtm_flags & RTF_LLINFO) == 0)&&((rtm->rtm_flags & RTF_HOST) == 0)&&((rtm->rtm_flags & RTF_UP) != 0)&&((rtm->rtm_flags & RTF_MULTICAST) == 0)) {
 						int which = 0;
 						int which = 0;
@@ -160,6 +163,13 @@ static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains)
 											if (!sin6->sin6_scope_id)
 											if (!sin6->sin6_scope_id)
 												sin6->sin6_scope_id = interfaceIndex;
 												sin6->sin6_scope_id = interfaceIndex;
 										}
 										}
+
+#ifdef __APPLE__
+										isDefault = IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && !(rtm->rtm_flags & RTF_IFSCOPE);
+#endif
+									} else {
+										struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
+										isDefault = sin4->sin_addr.s_addr == 0;
 									}
 									}
 									sa_t = *sa;
 									sa_t = *sa;
 									break;
 									break;
@@ -167,8 +177,7 @@ static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains)
 									//printf("RTA_GATEWAY\n");
 									//printf("RTA_GATEWAY\n");
 									switch(sa->sa_family) {
 									switch(sa->sa_family) {
 										case AF_LINK:
 										case AF_LINK:
-											deviceIndex = (int)((const struct sockaddr_dl *)sa)->sdl_index;
-											break;
+											// deviceIndex = (int)((const struct sockaddr_dl *)sa)->sdl_index;
 										case AF_INET:
 										case AF_INET:
 										case AF_INET6:
 										case AF_INET6:
 											sa_v = *sa;
 											sa_v = *sa;
@@ -211,10 +220,15 @@ static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains)
 							saptr += salen;
 							saptr += salen;
 						}
 						}
 
 
+
+						deviceIndex = rtm->rtm_index;
+
+
 						if (((contains)&&(sa_t.containsAddress(target)))||(sa_t == target)) {
 						if (((contains)&&(sa_t.containsAddress(target)))||(sa_t == target)) {
 							rtes.push_back(_RTE());
 							rtes.push_back(_RTE());
 							rtes.back().target = sa_t;
 							rtes.back().target = sa_t;
 							rtes.back().via = sa_v;
 							rtes.back().via = sa_v;
+							rtes.back().isDefault = isDefault;
 							if (deviceIndex >= 0) {
 							if (deviceIndex >= 0) {
 								if_indextoname(deviceIndex,rtes.back().device);
 								if_indextoname(deviceIndex,rtes.back().device);
 							} else {
 							} else {
@@ -457,70 +471,66 @@ bool ManagedRoute::sync()
 			return false;
 			return false;
 	}
 	}
 
 
-	// Find lowest metric system route that this route should override (if any)
-	InetAddress newSystemVia;
-	char newSystemDevice[128];
-	newSystemDevice[0] = (char)0;
-	int systemMetric = 9999999;
 	std::vector<_RTE> rtes(_getRTEs(_target,false));
 	std::vector<_RTE> rtes(_getRTEs(_target,false));
+
+	bool hasRoute = false;
 	for(std::vector<_RTE>::iterator r(rtes.begin());r!=rtes.end();++r) {
 	for(std::vector<_RTE>::iterator r(rtes.begin());r!=rtes.end();++r) {
-		if (r->via) {
-			if ( ((!newSystemVia)||(r->metric < systemMetric)) && (strcmp(r->device,_device) != 0) ) {
-				newSystemVia = r->via;
-				Utils::scopy(newSystemDevice,sizeof(newSystemDevice),r->device);
-				systemMetric = r->metric;
-			}
-		}
+		hasRoute = _target == r->target && _via.ipOnly() == r->via.ipOnly() && (strcmp(r->device,_device) == 0);
+		if (hasRoute) { break; }
 	}
 	}
 
 
-	// Get device corresponding to route if we don't have that already
-	if ((newSystemVia)&&(!newSystemDevice[0])) {
-		rtes = _getRTEs(newSystemVia,true);
-		for(std::vector<_RTE>::iterator r(rtes.begin());r!=rtes.end();++r) {
-			if ( (r->device[0]) && (strcmp(r->device,_device) != 0) && r->target.netmaskBits() != 0) {
-				Utils::scopy(newSystemDevice,sizeof(newSystemDevice),r->device);
-				break;
+
+	if (!hasRoute) {
+		if (_target && _target.netmaskBits() == 0) {
+			InetAddress newSystemVia;
+			char newSystemDevice[128];
+			newSystemDevice[0] = (char)0;
+
+			// Find system default route that this route should override
+			// We need to put it back when default route is turned off
+			for(std::vector<_RTE>::iterator r(rtes.begin());r!=rtes.end();++r) {
+				if (r->via) {
+					if ( !_systemVia && r->isDefault == 1 && (strcmp(r->device,_device) != 0) ) {
+
+						newSystemVia = r->via;
+						Utils::scopy(newSystemDevice,sizeof(newSystemDevice),r->device);
+					}
+				}
 			}
 			}
-		}
-	}
-	if (!newSystemDevice[0])
-		newSystemVia.zero();
-
-	// 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) != 0)) {
-		if (_systemVia) {
-			_routeCmd("delete",leftt,_systemVia,_systemDevice,(const char *)0);
-			if (rightt)
-				_routeCmd("delete",rightt,_systemVia,_systemDevice,(const char *)0);
-		}
 
 
-		_systemVia = newSystemVia;
-		Utils::scopy(_systemDevice,sizeof(_systemDevice),newSystemDevice);
+			if (!newSystemVia) { return false; }
 
 
-		if (_systemVia) {
-			_routeCmd("add",leftt,_systemVia,_systemDevice,(const char *)0);
-			//_routeCmd("change",leftt,_systemVia,_systemDevice,(const char *)0);
-			if (rightt) {
-				_routeCmd("add",rightt,_systemVia,_systemDevice,(const char *)0);
-				//_routeCmd("change",rightt,_systemVia,_systemDevice,(const char *)0);
+			// Get device corresponding to route if we don't have that already
+			if ((newSystemVia)&&(!newSystemDevice[0])) {
+				rtes = _getRTEs(newSystemVia,true);
+				for(std::vector<_RTE>::iterator r(rtes.begin());r!=rtes.end();++r) {
+					if ( (r->device[0]) && (strcmp(r->device,_device) != 0) && r->target.netmaskBits() != 0) {
+						Utils::scopy(newSystemDevice,sizeof(newSystemDevice),r->device);
+						break;
+					}
+				}
 			}
 			}
+			if (!newSystemDevice[0]) { return false; }
+
+
+			// update the system via in case it changed out from under us
+			// while we were in default route mode
+
+			_systemVia = newSystemVia;
+			Utils::scopy(_systemDevice,sizeof(_systemDevice),newSystemDevice);
+
+			// Do the actual default route commands
+			_routeCmd("delete",_target,_systemVia,(const char *)0,(const char *)0);
+			_routeCmd("add",_target,_via,(const char *)0,(const char *)0);
+			_routeCmd("add",_target,_systemVia,_systemDevice,(const char *)0);
+			_applied[_target] = true;
+		} else {
+			// Do the actual route commands
+			_applied[_target] = true;
+			_routeCmd("add",leftt,_via,(const char *)0,(_via) ? (const char *)0 : _device);
 		}
 		}
 	}
 	}
 
 
-	if (leftt && !_applied.count(leftt)) {
-		_applied[leftt] = !_via;
-		//_routeCmd("delete",leftt,_via,(const char *)0,(_via) ? (const char *)0 : _device);
-		_routeCmd("add",leftt,_via,(const char *)0,(_via) ? (const char *)0 : _device);
-		//_routeCmd("change",leftt,_via,(const char *)0,(_via) ? (const char *)0 : _device);
-	}
-	if (rightt && !_applied.count(rightt)) {
-		_applied[rightt] = !_via;
-		//_routeCmd("delete",rightt,_via,(const char *)0,(_via) ? (const char *)0 : _device);
-		_routeCmd("add",rightt,_via,(const char *)0,(_via) ? (const char *)0 : _device);
-		//_routeCmd("change",rightt,_via,(const char *)0,(_via) ? (const char *)0 : _device);
-	}
 
 
 #endif // __BSD__ ------------------------------------------------------------
 #endif // __BSD__ ------------------------------------------------------------
 
 
@@ -565,18 +575,22 @@ void ManagedRoute::remove()
 #endif
 #endif
 
 
 #ifdef __BSD__
 #ifdef __BSD__
-	if (_systemVia) {
-		InetAddress leftt,rightt;
-		_forkTarget(_target,leftt,rightt);
-		_routeCmd("delete",leftt,_systemVia,_systemDevice,(const char *)0);
-		if (rightt)
-			_routeCmd("delete",rightt,_systemVia,_systemDevice,(const char *)0);
-	}
 #endif // __BSD__ ------------------------------------------------------------
 #endif // __BSD__ ------------------------------------------------------------
 
 
 	for(std::map<InetAddress,bool>::iterator r(_applied.begin());r!=_applied.end();++r) {
 	for(std::map<InetAddress,bool>::iterator r(_applied.begin());r!=_applied.end();++r) {
 #ifdef __BSD__ // ------------------------------------------------------------
 #ifdef __BSD__ // ------------------------------------------------------------
-		_routeCmd("delete",r->first,_via,r->second ? _device : (const char *)0,(_via) ? (const char *)0 : _device);
+		if (_target && _target.netmaskBits() == 0) {
+			if (_systemVia) {
+				_routeCmd("delete",_target,_via,(const char *)0,(const char *)0);
+				_routeCmd("delete",_target,_systemVia,_systemDevice,(const char *)0);
+
+				_routeCmd("add",_target,_systemVia,(const char *)0,(const char *)0);
+
+			}
+		} else {
+		_routeCmd("delete",_target,_via, (const char *)0, _via ? (const char *)0 : _device);
+	}
+	break;
 #endif // __BSD__ ------------------------------------------------------------
 #endif // __BSD__ ------------------------------------------------------------
 
 
 #ifdef __LINUX__ // ----------------------------------------------------------
 #ifdef __LINUX__ // ----------------------------------------------------------