|
|
|
|
@ -33,6 +33,7 @@
|
|
|
|
|
#include <sys/socket.h> |
|
|
|
|
#include <sys/types.h> |
|
|
|
|
#include <sys/stat.h> |
|
|
|
|
#include <sys/wait.h> |
|
|
|
|
#include <fcntl.h> |
|
|
|
|
#include <netinet/in.h> |
|
|
|
|
#include <arpa/inet.h> |
|
|
|
|
@ -41,8 +42,8 @@
|
|
|
|
|
#include <algorithm> |
|
|
|
|
#include <utility> |
|
|
|
|
|
|
|
|
|
#include "../Constants.hpp" |
|
|
|
|
#include "../Utils.hpp" |
|
|
|
|
#include "../node/Constants.hpp" |
|
|
|
|
#include "../node/Utils.hpp" |
|
|
|
|
#include "LinuxRoutingTable.hpp" |
|
|
|
|
|
|
|
|
|
#define ZT_LINUX_IP_COMMAND "/sbin/ip" |
|
|
|
|
@ -168,24 +169,50 @@ std::vector<RoutingTable::Entry> LinuxRoutingTable::get(bool includeLinkLocal,bo
|
|
|
|
|
|
|
|
|
|
RoutingTable::Entry LinuxRoutingTable::set(const InetAddress &destination,const InetAddress &gateway,const char *device,int metric) |
|
|
|
|
{ |
|
|
|
|
char metstr[128]; |
|
|
|
|
|
|
|
|
|
if ((!gateway)&&((!device)||(!device[0]))) |
|
|
|
|
return RoutingTable::Entry(); |
|
|
|
|
|
|
|
|
|
std::vector<RoutingTable::Entry> rtab(get(true,true)); |
|
|
|
|
Utils::snprintf(metstr,sizeof(metstr),"%d",metric); |
|
|
|
|
|
|
|
|
|
for(std::vector<RoutingTable::Entry>::iterator e(rtab.begin());e!=rtab.end();++e) { |
|
|
|
|
if (e->destination == destination) { |
|
|
|
|
if (((!device)||(!device[0]))||(!strcmp(device,e->device))) { |
|
|
|
|
if (metric < 0) { |
|
|
|
|
long pid = (long)vfork(); |
|
|
|
|
if (pid == 0) { |
|
|
|
|
if (gateway) { |
|
|
|
|
if ((device)&&(device[0])) { |
|
|
|
|
::execl(ZT_LINUX_IP_COMMAND,ZT_LINUX_IP_COMMAND,"route","del",destination.toString().c_str(),"via",gateway.toIpString().c_str(),"dev",device,(const char *)0); |
|
|
|
|
} else { |
|
|
|
|
::execl(ZT_LINUX_IP_COMMAND,ZT_LINUX_IP_COMMAND,"route","del",destination.toString().c_str(),"via",gateway.toIpString().c_str(),(const char *)0); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
::execl(ZT_LINUX_IP_COMMAND,ZT_LINUX_IP_COMMAND,"route","del",destination.toString().c_str(),"dev",device,(const char *)0); |
|
|
|
|
} |
|
|
|
|
::_exit(-1); |
|
|
|
|
} else if (pid > 0) { |
|
|
|
|
int exitcode = -1; |
|
|
|
|
::waitpid(pid,&exitcode,0); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
long pid = (long)vfork(); |
|
|
|
|
if (pid == 0) { |
|
|
|
|
if (gateway) { |
|
|
|
|
if ((device)&&(device[0])) { |
|
|
|
|
::execl(ZT_LINUX_IP_COMMAND,ZT_LINUX_IP_COMMAND,"route","replace",destination.toString().c_str(),"metric",metstr,"via",gateway.toIpString().c_str(),"dev",device,(const char *)0); |
|
|
|
|
} else { |
|
|
|
|
::execl(ZT_LINUX_IP_COMMAND,ZT_LINUX_IP_COMMAND,"route","replace",destination.toString().c_str(),"metric",metstr,"via",gateway.toIpString().c_str(),(const char *)0); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
::execl(ZT_LINUX_IP_COMMAND,ZT_LINUX_IP_COMMAND,"route","replace",destination.toString().c_str(),"metric",metstr,"dev",device,(const char *)0); |
|
|
|
|
} |
|
|
|
|
::_exit(-1); |
|
|
|
|
} else if (pid > 0) { |
|
|
|
|
int exitcode = -1; |
|
|
|
|
::waitpid(pid,&exitcode,0); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (metric < 0) |
|
|
|
|
return RoutingTable::Entry(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rtab = get(true,true); |
|
|
|
|
std::vector<RoutingTable::Entry> rtab(get(true,true)); |
|
|
|
|
std::vector<RoutingTable::Entry>::iterator bestEntry(rtab.end()); |
|
|
|
|
for(std::vector<RoutingTable::Entry>::iterator e(rtab.begin());e!=rtab.end();++e) { |
|
|
|
|
if ((e->destination == destination)&&(e->gateway.ipsEqual(gateway))) { |
|
|
|
|
@ -206,42 +233,3 @@ RoutingTable::Entry LinuxRoutingTable::set(const InetAddress &destination,const
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} // namespace ZeroTier
|
|
|
|
|
|
|
|
|
|
// Enable and build to test routing table interface
|
|
|
|
|
//#if 0
|
|
|
|
|
using namespace ZeroTier; |
|
|
|
|
int main(int argc,char **argv) |
|
|
|
|
{ |
|
|
|
|
LinuxRoutingTable rt; |
|
|
|
|
|
|
|
|
|
printf("<destination> <gateway> <interface> <metric>\n"); |
|
|
|
|
std::vector<RoutingTable::Entry> ents(rt.get()); |
|
|
|
|
for(std::vector<RoutingTable::Entry>::iterator e(ents.begin());e!=ents.end();++e) |
|
|
|
|
printf("%s\n",e->toString().c_str()); |
|
|
|
|
printf("\n"); |
|
|
|
|
|
|
|
|
|
printf("adding 1.1.1.0 and 2.2.2.0...\n"); |
|
|
|
|
rt.set(InetAddress("1.1.1.0",24),InetAddress("1.2.3.4",0),(const char *)0,1); |
|
|
|
|
rt.set(InetAddress("2.2.2.0",24),InetAddress(),"en0",1); |
|
|
|
|
printf("\n"); |
|
|
|
|
|
|
|
|
|
printf("<destination> <gateway> <interface> <metric>\n"); |
|
|
|
|
ents = rt.get(); |
|
|
|
|
for(std::vector<RoutingTable::Entry>::iterator e(ents.begin());e!=ents.end();++e) |
|
|
|
|
printf("%s\n",e->toString().c_str()); |
|
|
|
|
printf("\n"); |
|
|
|
|
|
|
|
|
|
printf("deleting 1.1.1.0 and 2.2.2.0...\n"); |
|
|
|
|
rt.set(InetAddress("1.1.1.0",24),InetAddress("1.2.3.4",0),(const char *)0,-1); |
|
|
|
|
rt.set(InetAddress("2.2.2.0",24),InetAddress(),"en0",-1); |
|
|
|
|
printf("\n"); |
|
|
|
|
|
|
|
|
|
printf("<destination> <gateway> <interface> <metric>\n"); |
|
|
|
|
ents = rt.get(); |
|
|
|
|
for(std::vector<RoutingTable::Entry>::iterator e(ents.begin());e!=ents.end();++e) |
|
|
|
|
printf("%s\n",e->toString().c_str()); |
|
|
|
|
printf("\n"); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
//#endif
|
|
|
|
|
|