summaryrefslogtreecommitdiff
path: root/osdep/ManagedRoute.cpp
diff options
context:
space:
mode:
authorGrant Limberg <grant.limberg@zerotier.com>2018-06-04 12:24:58 -0700
committerGrant Limberg <grant.limberg@zerotier.com>2018-06-04 12:24:58 -0700
commitb9975845fffc087c138df4934831f9ef40e61ad6 (patch)
tree40af34a6383d3a8d91797c8964f7ce041b2b4f52 /osdep/ManagedRoute.cpp
parent91a22a686a17f8cedc58690592a84f5d4a3ab5e0 (diff)
parentb22405b64b0b26fa1d5d8932cf212e4ae7760632 (diff)
downloadinfinitytier-b9975845fffc087c138df4934831f9ef40e61ad6.tar.gz
infinitytier-b9975845fffc087c138df4934831f9ef40e61ad6.zip
Merge branch 'rtnetlink' into edge
Diffstat (limited to 'osdep/ManagedRoute.cpp')
-rw-r--r--osdep/ManagedRoute.cpp142
1 files changed, 125 insertions, 17 deletions
diff --git a/osdep/ManagedRoute.cpp b/osdep/ManagedRoute.cpp
index d7c80704..99277c9f 100644
--- a/osdep/ManagedRoute.cpp
+++ b/osdep/ManagedRoute.cpp
@@ -48,6 +48,14 @@
#include <arpa/inet.h>
#include <net/route.h>
#include <net/if.h>
+#ifdef __LINUX__
+#include <sys/ioctl.h>
+#include <bits/sockaddr.h>
+#include <asm/types.h>
+#include <linux/rtnetlink.h>
+#include <sys/socket.h>
+#include "../osdep/LinuxNetLink.hpp"
+#endif
#ifdef __BSD__
#include <net/if_dl.h>
#include <sys/sysctl.h>
@@ -277,27 +285,127 @@ static void _routeCmd(const char *op,const InetAddress &target,const InetAddress
#ifdef __LINUX__ // ----------------------------------------------------------
#define ZT_ROUTING_SUPPORT_FOUND 1
-static void _routeCmd(const char *op,const InetAddress &target,const InetAddress &via,const char *localInterface)
+static void _routeCmd(const char *op, const InetAddress &target, const InetAddress &via, const InetAddress &src, const char *localInterface)
{
- long p = (long)fork();
- if (p > 0) {
- int exitcode = -1;
- ::waitpid(p,&exitcode,0);
- } else if (p == 0) {
- ::close(STDOUT_FILENO);
- ::close(STDERR_FILENO);
- char ipbuf[64],ipbuf2[64];
+ char targetStr[64] = {0};
+ char viaStr[64] = {0};
+ InetAddress nmsk = target.netmask();
+ char nmskStr[64] = {0};
+ fprintf(stderr, "Received Route Cmd: %s target: %s via: %s netmask: %s localInterface: %s\n", op, target.toString(targetStr), via.toString(viaStr), nmsk.toString(nmskStr), localInterface);
+
+
+ if ((strcmp(op, "add") == 0 || strcmp(op, "replace") == 0)) {
+ LinuxNetLink::getInstance().addRoute(target, via, src, localInterface);
+ } else if ((strcmp(op, "remove") == 0 || strcmp(op, "del") == 0)) {
+ LinuxNetLink::getInstance().delRoute(target, via, src, localInterface);
+ }
+ return;
+
+
+ int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);;
+ struct rtentry route = {0};
+
+ if (target.ss_family == AF_INET) {
+ struct sockaddr_in *target_in = (struct sockaddr_in*)&target;
+ struct sockaddr_in *via_in = (struct sockaddr_in*)&via;
+ InetAddress netmask = target.netmask();
+ struct sockaddr_in *netmask_in = (struct sockaddr_in*)&netmask;
+
+ struct sockaddr_in *addr = NULL;
+
+ // set target
+ addr = (struct sockaddr_in *)&route.rt_dst;
+ addr->sin_family = AF_INET;
+ addr->sin_addr = target_in->sin_addr;
+
+ // set netmask
+ addr = (struct sockaddr_in *)&route.rt_genmask;
+ addr->sin_family = AF_INET;
+ addr->sin_addr = netmask_in->sin_addr;
+
+ route.rt_dev = const_cast<char*>(localInterface);
+
if (via) {
- ::execl(ZT_LINUX_IP_COMMAND,ZT_LINUX_IP_COMMAND,(target.ss_family == AF_INET6) ? "-6" : "-4","route",op,target.toString(ipbuf),"via",via.toIpString(ipbuf2),(const char *)0);
- ::execl(ZT_LINUX_IP_COMMAND_2,ZT_LINUX_IP_COMMAND_2,(target.ss_family == AF_INET6) ? "-6" : "-4","route",op,target.toString(ipbuf),"via",via.toIpString(ipbuf2),(const char *)0);
+ // set the gateway
+ addr = (struct sockaddr_in *)&route.rt_gateway;
+ addr->sin_family = AF_INET;
+ addr->sin_addr = via_in->sin_addr;
+
+ route.rt_flags = RTF_UP | RTF_GATEWAY;
} else if ((localInterface)&&(localInterface[0])) {
- ::execl(ZT_LINUX_IP_COMMAND,ZT_LINUX_IP_COMMAND,(target.ss_family == AF_INET6) ? "-6" : "-4","route",op,target.toString(ipbuf),"dev",localInterface,(const char *)0);
- ::execl(ZT_LINUX_IP_COMMAND_2,ZT_LINUX_IP_COMMAND_2,(target.ss_family == AF_INET6) ? "-6" : "-4","route",op,target.toString(ipbuf),"dev",localInterface,(const char *)0);
+ route.rt_flags = RTF_UP;//| RTF_HOST;
+ }
+ }
+ else if (target.ss_family == AF_INET6)
+ {
+ struct sockaddr_in6 *addr = NULL;
+
+ // set target
+ addr = (struct sockaddr_in6 *)&route.rt_dst;
+ addr->sin6_family = AF_INET6;
+ memcpy(&addr->sin6_addr, &((struct sockaddr_in6*)&target)->sin6_addr, sizeof(struct in6_addr));
+
+ //set netmask
+ addr = (struct sockaddr_in6 *)&route.rt_genmask;
+ addr->sin6_family = AF_INET6;
+ InetAddress netmask = target.netmask();
+ memcpy(&addr->sin6_addr, &((struct sockaddr_in6*)&netmask)->sin6_addr, sizeof(struct in6_addr));
+
+ if (via) {
+ // set the gateway
+ addr = (struct sockaddr_in6*)&route.rt_gateway;
+ addr->sin6_family = AF_INET;
+ memcpy(&addr->sin6_addr, &((struct sockaddr_in6*)&via)->sin6_addr, sizeof(struct in6_addr));
+
+ route.rt_flags = RTF_UP | RTF_GATEWAY;
+ } else if ((localInterface)&&(localInterface[0])) {
+ route.rt_dev = const_cast<char*>(localInterface);
+ route.rt_flags = RTF_UP;
}
- ::_exit(-1);
}
+
+ unsigned long ctl = -1;
+ if (strcmp(op, "add") == 0 || strcmp(op, "replace") == 0) {
+ ctl = SIOCADDRT;
+ } else if (strcmp(op, "remove") == 0 || strcmp(op, "del") == 0) {
+ ctl = SIOCDELRT;
+ } else {
+ close(fd);
+ return;
+ }
+
+ if ( ioctl(fd, ctl, &route)) {
+ fprintf(stderr, "Error adding route: %s\n", strerror(errno));
+ close(fd);
+ ::exit(1);
+ }
+ close(fd);
}
+// static void _routeCmd(const char *op,const InetAddress &target,const InetAddress &via,const char *localInterface)
+// {
+// // long p = (long)fork();
+// // if (p > 0) {
+// // int exitcode = -1;
+// // ::waitpid(p,&exitcode,0);
+// // } else if (p == 0) {
+// // ::close(STDOUT_FILENO);
+// // ::close(STDERR_FILENO);
+// char ipbuf[64],ipbuf2[64];
+
+
+
+// if (via) {
+// ::execl(ZT_LINUX_IP_COMMAND,ZT_LINUX_IP_COMMAND,(target.ss_family == AF_INET6) ? "-6" : "-4","route",op,target.toString(ipbuf),"via",via.toIpString(ipbuf2),(const char *)0);
+// ::execl(ZT_LINUX_IP_COMMAND_2,ZT_LINUX_IP_COMMAND_2,(target.ss_family == AF_INET6) ? "-6" : "-4","route",op,target.toString(ipbuf),"via",via.toIpString(ipbuf2),(const char *)0);
+// } else if ((localInterface)&&(localInterface[0])) {
+// ::execl(ZT_LINUX_IP_COMMAND,ZT_LINUX_IP_COMMAND,(target.ss_family == AF_INET6) ? "-6" : "-4","route",op,target.toString(ipbuf),"dev",localInterface,(const char *)0);
+// ::execl(ZT_LINUX_IP_COMMAND_2,ZT_LINUX_IP_COMMAND_2,(target.ss_family == AF_INET6) ? "-6" : "-4","route",op,target.toString(ipbuf),"dev",localInterface,(const char *)0);
+// }
+// // ::_exit(-1);
+// // }
+// }
+
#endif // __LINUX__ ----------------------------------------------------------
#ifdef __WINDOWS__ // --------------------------------------------------------
@@ -494,11 +602,11 @@ bool ManagedRoute::sync()
if (!_applied.count(leftt)) {
_applied[leftt] = false; // boolean unused
- _routeCmd("replace",leftt,_via,(_via) ? (const char *)0 : _device);
+ _routeCmd("replace",leftt,_via,_src,_device);
}
if ((rightt)&&(!_applied.count(rightt))) {
_applied[rightt] = false; // boolean unused
- _routeCmd("replace",rightt,_via,(_via) ? (const char *)0 : _device);
+ _routeCmd("replace",rightt,_via,_src,_device);
}
#endif // __LINUX__ ----------------------------------------------------------
@@ -545,7 +653,7 @@ void ManagedRoute::remove()
#endif // __BSD__ ------------------------------------------------------------
#ifdef __LINUX__ // ----------------------------------------------------------
- _routeCmd("del",r->first,_via,(_via) ? (const char *)0 : _device);
+ _routeCmd("del",r->first,_via,_src,_device);
#endif // __LINUX__ ----------------------------------------------------------
#ifdef __WINDOWS__ // --------------------------------------------------------