|
@@ -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__ // ----------------------------------------------------------
|