|
@@ -13,6 +13,8 @@
|
|
|
|
|
|
#include "../node/Constants.hpp"
|
|
|
|
|
|
+//#define ZT_NETLINK_TRACE
|
|
|
+
|
|
|
#ifdef __LINUX__
|
|
|
|
|
|
#include "LinuxNetLink.hpp"
|
|
@@ -43,10 +45,6 @@ struct nl_adr_req {
|
|
|
LinuxNetLink::LinuxNetLink()
|
|
|
: _t()
|
|
|
, _running(false)
|
|
|
- , _routes_ipv4()
|
|
|
- , _rv4_m()
|
|
|
- , _routes_ipv6()
|
|
|
- , _rv6_m()
|
|
|
, _seq(0)
|
|
|
, _interfaces()
|
|
|
, _if_m()
|
|
@@ -85,7 +83,7 @@ void LinuxNetLink::_setSocketTimeout(int fd, int seconds)
|
|
|
tv.tv_sec = seconds;
|
|
|
tv.tv_usec = 0;
|
|
|
if(setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv)) != 0) {
|
|
|
-#ifdef ZT_TRACE
|
|
|
+#ifdef ZT_NETLINK_TRACE
|
|
|
fprintf(stderr, "setsockopt failed: %s\n", strerror(errno));
|
|
|
#endif
|
|
|
}
|
|
@@ -119,8 +117,8 @@ int LinuxNetLink::_doRecv(int fd)
|
|
|
if(nlp->nlmsg_type == NLMSG_ERROR && (nlp->nlmsg_flags & NLM_F_ACK) != NLM_F_ACK) {
|
|
|
struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(nlp);
|
|
|
if (err->error != 0) {
|
|
|
-#ifdef ZT_TRACE
|
|
|
- //fprintf(stderr, "rtnetlink error: %s\n", strerror(-(err->error)));
|
|
|
+#ifdef ZT_NETLINK_TRACE
|
|
|
+ fprintf(stderr, "rtnetlink error: %s\n", strerror(-(err->error)));
|
|
|
#endif
|
|
|
}
|
|
|
p = buf;
|
|
@@ -145,9 +143,9 @@ int LinuxNetLink::_doRecv(int fd)
|
|
|
}
|
|
|
|
|
|
if (nlp->nlmsg_type == NLMSG_OVERRUN) {
|
|
|
-//#ifdef ZT_TRACE
|
|
|
+#ifdef ZT_NETLINK_TRACE
|
|
|
fprintf(stderr, "NLMSG_OVERRUN: Data lost\n");
|
|
|
-//#endif
|
|
|
+#endif
|
|
|
p = buf;
|
|
|
nll = 0;
|
|
|
break;
|
|
@@ -173,11 +171,10 @@ int LinuxNetLink::_doRecv(int fd)
|
|
|
void LinuxNetLink::threadMain() throw()
|
|
|
{
|
|
|
int rtn = 0;
|
|
|
-
|
|
|
while(_running) {
|
|
|
rtn = _doRecv(_fd);
|
|
|
if (rtn <= 0) {
|
|
|
- Thread::sleep(100);
|
|
|
+ Thread::sleep(250);
|
|
|
continue;
|
|
|
}
|
|
|
}
|
|
@@ -215,6 +212,7 @@ void LinuxNetLink::_processMessage(struct nlmsghdr *nlp, int nll)
|
|
|
|
|
|
void LinuxNetLink::_ipAddressAdded(struct nlmsghdr *nlp)
|
|
|
{
|
|
|
+#ifdef ZT_NETLINK_TRACE
|
|
|
struct ifaddrmsg *ifap = (struct ifaddrmsg *)NLMSG_DATA(nlp);
|
|
|
struct rtattr *rtap = (struct rtattr *)IFA_RTA(ifap);
|
|
|
int ifal = IFA_PAYLOAD(nlp);
|
|
@@ -242,13 +240,13 @@ void LinuxNetLink::_ipAddressAdded(struct nlmsghdr *nlp)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-#ifdef ZT_TRACE
|
|
|
- //fprintf(stderr,"Added IP Address %s local: %s label: %s broadcast: %s\n", addr, local, label, bcast);
|
|
|
+ fprintf(stderr,"Added IP Address %s local: %s label: %s broadcast: %s\n", addr, local, label, bcast);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
void LinuxNetLink::_ipAddressDeleted(struct nlmsghdr *nlp)
|
|
|
{
|
|
|
+#ifdef ZT_NETLINK_TRACE
|
|
|
struct ifaddrmsg *ifap = (struct ifaddrmsg *)NLMSG_DATA(nlp);
|
|
|
struct rtattr *rtap = (struct rtattr *)IFA_RTA(ifap);
|
|
|
int ifal = IFA_PAYLOAD(nlp);
|
|
@@ -276,8 +274,7 @@ void LinuxNetLink::_ipAddressDeleted(struct nlmsghdr *nlp)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-#ifdef ZT_TRACE
|
|
|
- //fprintf(stderr, "Removed IP Address %s local: %s label: %s broadcast: %s\n", addr, local, label, bcast);
|
|
|
+ fprintf(stderr, "Removed IP Address %s local: %s label: %s broadcast: %s\n", addr, local, label, bcast);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
@@ -293,28 +290,79 @@ void LinuxNetLink::_routeAdded(struct nlmsghdr *nlp)
|
|
|
struct rtattr *rtap = (struct rtattr *)RTM_RTA(rtp);
|
|
|
int rtl = RTM_PAYLOAD(nlp);
|
|
|
|
|
|
+ Route r;
|
|
|
+ bool wecare = false;
|
|
|
+
|
|
|
for(;RTA_OK(rtap, rtl); rtap=RTA_NEXT(rtap, rtl))
|
|
|
{
|
|
|
switch(rtap->rta_type)
|
|
|
{
|
|
|
case RTA_DST:
|
|
|
- inet_ntop(rtp->rtm_family, RTA_DATA(rtap), dsts, rtp->rtm_family == AF_INET ? 24 : 40);
|
|
|
+ switch(rtp->rtm_family) {
|
|
|
+ case AF_INET:
|
|
|
+ inet_ntop(rtp->rtm_family, RTA_DATA(rtap), dsts, 24);
|
|
|
+ r.target.set(RTA_DATA(rtap), 4, 0);
|
|
|
+ wecare = true;
|
|
|
+ break;
|
|
|
+ case AF_INET6:
|
|
|
+ inet_ntop(rtp->rtm_family, RTA_DATA(rtap), dsts, 24);
|
|
|
+ r.target.set(RTA_DATA(rtap), 16, 0);
|
|
|
+ wecare = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
break;
|
|
|
case RTA_SRC:
|
|
|
- inet_ntop(rtp->rtm_family, RTA_DATA(rtap), srcs, rtp->rtm_family == AF_INET ? 24: 40);
|
|
|
+ switch(rtp->rtm_family) {
|
|
|
+ case AF_INET:
|
|
|
+ inet_ntop(rtp->rtm_family, RTA_DATA(rtap), srcs, 24);
|
|
|
+ r.src.set(RTA_DATA(rtap), 4, 0);
|
|
|
+ wecare = true;
|
|
|
+ break;
|
|
|
+ case AF_INET6:
|
|
|
+ inet_ntop(rtp->rtm_family, RTA_DATA(rtap), srcs, 24);
|
|
|
+ r.src.set(RTA_DATA(rtap), 16, 0);
|
|
|
+ wecare = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
break;
|
|
|
case RTA_GATEWAY:
|
|
|
- inet_ntop(rtp->rtm_family, RTA_DATA(rtap), gws, rtp->rtm_family == AF_INET ? 24 : 40);
|
|
|
+ switch(rtp->rtm_family) {
|
|
|
+ case AF_INET:
|
|
|
+ inet_ntop(rtp->rtm_family, RTA_DATA(rtap), gws, 24);
|
|
|
+ r.via.set(RTA_DATA(rtap), 4, 0);
|
|
|
+ wecare = true;
|
|
|
+ break;
|
|
|
+ case AF_INET6:
|
|
|
+ inet_ntop(rtp->rtm_family, RTA_DATA(rtap), gws, 24);
|
|
|
+ r.via.set(RTA_DATA(rtap), 16, 0);
|
|
|
+ wecare = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
break;
|
|
|
case RTA_OIF:
|
|
|
+ switch(rtp->rtm_family) {
|
|
|
+ case AF_INET:
|
|
|
+ r.ifidx = *((int*)RTA_DATA(rtap));
|
|
|
+ wecare = true;
|
|
|
+ break;
|
|
|
+ case AF_INET6:
|
|
|
+ r.ifidx = *((int*)RTA_DATA(rtap));
|
|
|
+ wecare = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
sprintf(ifs, "%d", *((int*)RTA_DATA(rtap)));
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
- sprintf(ms, "%d", rtp->rtm_dst_len);
|
|
|
|
|
|
-#ifdef ZT_TRACE
|
|
|
- //fprintf(stderr, "Route Added: dst %s/%s gw %s src %s if %s\n", dsts, ms, gws, srcs, ifs);
|
|
|
+ if (wecare) {
|
|
|
+ Mutex::Lock rl(_routes_m);
|
|
|
+ _routes[r.target].insert(r);
|
|
|
+ }
|
|
|
+
|
|
|
+#ifdef ZT_NETLINK_TRACE
|
|
|
+ sprintf(ms, "%d", rtp->rtm_dst_len);
|
|
|
+ fprintf(stderr, "Route Added: dst %s/%s gw %s src %s if %s\n", dsts, ms, gws, srcs, ifs);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
@@ -330,28 +378,79 @@ void LinuxNetLink::_routeDeleted(struct nlmsghdr *nlp)
|
|
|
struct rtattr *rtap = (struct rtattr *)RTM_RTA(rtp);
|
|
|
int rtl = RTM_PAYLOAD(nlp);
|
|
|
|
|
|
+ Route r;
|
|
|
+ bool wecare = false;
|
|
|
+
|
|
|
for(;RTA_OK(rtap, rtl); rtap=RTA_NEXT(rtap, rtl))
|
|
|
{
|
|
|
switch(rtap->rta_type)
|
|
|
{
|
|
|
case RTA_DST:
|
|
|
- inet_ntop(rtp->rtm_family, RTA_DATA(rtap), dsts, rtp->rtm_family == AF_INET ? 24 : 40);
|
|
|
+ switch(rtp->rtm_family) {
|
|
|
+ case AF_INET:
|
|
|
+ inet_ntop(rtp->rtm_family, RTA_DATA(rtap), dsts, 24);
|
|
|
+ r.target.set(RTA_DATA(rtap), 4, 0);
|
|
|
+ wecare = true;
|
|
|
+ break;
|
|
|
+ case AF_INET6:
|
|
|
+ inet_ntop(rtp->rtm_family, RTA_DATA(rtap), dsts, 24);
|
|
|
+ r.target.set(RTA_DATA(rtap), 16, 0);
|
|
|
+ wecare = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
break;
|
|
|
case RTA_SRC:
|
|
|
- inet_ntop(rtp->rtm_family, RTA_DATA(rtap), srcs, rtp->rtm_family == AF_INET ? 24 : 40);
|
|
|
+ switch(rtp->rtm_family) {
|
|
|
+ case AF_INET:
|
|
|
+ inet_ntop(rtp->rtm_family, RTA_DATA(rtap), srcs, 24);
|
|
|
+ r.src.set(RTA_DATA(rtap), 4, 0);
|
|
|
+ wecare = true;
|
|
|
+ break;
|
|
|
+ case AF_INET6:
|
|
|
+ inet_ntop(rtp->rtm_family, RTA_DATA(rtap), srcs, 24);
|
|
|
+ r.src.set(RTA_DATA(rtap), 16, 0);
|
|
|
+ wecare = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
break;
|
|
|
case RTA_GATEWAY:
|
|
|
- inet_ntop(rtp->rtm_family, RTA_DATA(rtap), gws, rtp->rtm_family == AF_INET ? 24 : 40);
|
|
|
+ switch(rtp->rtm_family) {
|
|
|
+ case AF_INET:
|
|
|
+ inet_ntop(rtp->rtm_family, RTA_DATA(rtap), gws, 24);
|
|
|
+ r.via.set(RTA_DATA(rtap), 4, 0);
|
|
|
+ wecare = true;
|
|
|
+ break;
|
|
|
+ case AF_INET6:
|
|
|
+ inet_ntop(rtp->rtm_family, RTA_DATA(rtap), gws, 24);
|
|
|
+ r.via.set(RTA_DATA(rtap), 16, 0);
|
|
|
+ wecare = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
break;
|
|
|
case RTA_OIF:
|
|
|
+ switch(rtp->rtm_family) {
|
|
|
+ case AF_INET:
|
|
|
+ r.ifidx = *((int*)RTA_DATA(rtap));
|
|
|
+ wecare = true;
|
|
|
+ break;
|
|
|
+ case AF_INET6:
|
|
|
+ r.ifidx = *((int*)RTA_DATA(rtap));
|
|
|
+ wecare = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
sprintf(ifs, "%d", *((int*)RTA_DATA(rtap)));
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
- sprintf(ms, "%d", rtp->rtm_dst_len);
|
|
|
|
|
|
-#ifdef ZT_TRACE
|
|
|
- //fprintf(stderr, "Route Deleted: dst %s/%s gw %s src %s if %s\n", dsts, ms, gws, srcs, ifs);
|
|
|
+ if (wecare) {
|
|
|
+ Mutex::Lock rl(_routes_m);
|
|
|
+ _routes[r.target].erase(r);
|
|
|
+ }
|
|
|
+
|
|
|
+#ifdef ZT_NETLINK_TRACE
|
|
|
+ sprintf(ms, "%d", rtp->rtm_dst_len);
|
|
|
+ fprintf(stderr, "Route Deleted: dst %s/%s gw %s src %s if %s\n", dsts, ms, gws, srcs, ifs);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
@@ -605,11 +704,11 @@ void LinuxNetLink::addRoute(const InetAddress &target, const InetAddress &via, c
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
-#ifdef ZT_TRACE
|
|
|
- //char tmp[64];
|
|
|
- //char tmp2[64];
|
|
|
- //char tmp3[64];
|
|
|
- //fprintf(stderr, "Adding Route. target: %s via: %s src: %s iface: %s\n", target.toString(tmp), via.toString(tmp2), src.toString(tmp3), ifaceName);
|
|
|
+#ifdef ZT_NETLINK_TRACE
|
|
|
+ char tmp[64];
|
|
|
+ char tmp2[64];
|
|
|
+ char tmp3[64];
|
|
|
+ fprintf(stderr, "Adding Route. target: %s via: %s src: %s iface: %s\n", target.toString(tmp), via.toString(tmp2), src.toString(tmp3), ifaceName);
|
|
|
#endif
|
|
|
|
|
|
int rtl = sizeof(struct rtmsg);
|
|
@@ -720,11 +819,11 @@ void LinuxNetLink::delRoute(const InetAddress &target, const InetAddress &via, c
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
-#ifdef ZT_TRACE
|
|
|
- //char tmp[64];
|
|
|
- //char tmp2[64];
|
|
|
- //char tmp3[64];
|
|
|
- //fprintf(stderr, "Removing Route. target: %s via: %s src: %s iface: %s\n", target.toString(tmp), via.toString(tmp2), src.toString(tmp3), ifaceName);
|
|
|
+#ifdef ZT_NETLINK_TRACE
|
|
|
+ char tmp[64];
|
|
|
+ char tmp2[64];
|
|
|
+ char tmp3[64];
|
|
|
+ fprintf(stderr, "Removing Route. target: %s via: %s src: %s iface: %s\n", target.toString(tmp), via.toString(tmp2), src.toString(tmp3), ifaceName);
|
|
|
#endif
|
|
|
|
|
|
int rtl = sizeof(struct rtmsg);
|
|
@@ -839,9 +938,9 @@ void LinuxNetLink::addAddress(const InetAddress &addr, const char *iface)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
-#ifdef ZT_TRACE
|
|
|
- //char tmp[128];
|
|
|
- //fprintf(stderr, "Adding IP address %s to interface %s", addr.toString(tmp), iface);
|
|
|
+#ifdef ZT_NETLINK_TRACE
|
|
|
+ char tmp[128];
|
|
|
+ fprintf(stderr, "Adding IP address %s to interface %s\n", addr.toString(tmp), iface);
|
|
|
#endif
|
|
|
|
|
|
int interface_index = _indexForInterface(iface);
|
|
@@ -955,9 +1054,9 @@ void LinuxNetLink::removeAddress(const InetAddress &addr, const char *iface)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
-#ifdef ZT_TRACE
|
|
|
- //char tmp[128];
|
|
|
- //fprintf(stderr, "Removing IP address %s from interface %s", addr.toString(tmp), iface);
|
|
|
+#ifdef ZT_NETLINK_TRACE
|
|
|
+ char tmp[128];
|
|
|
+ fprintf(stderr, "Removing IP address %s from interface %s\n", addr.toString(tmp), iface);
|
|
|
#endif
|
|
|
|
|
|
int interface_index = _indexForInterface(iface);
|
|
@@ -1043,14 +1142,23 @@ void LinuxNetLink::removeAddress(const InetAddress &addr, const char *iface)
|
|
|
close(fd);
|
|
|
}
|
|
|
|
|
|
-RouteList LinuxNetLink::getIPV4Routes() const
|
|
|
-{
|
|
|
- return _routes_ipv4;
|
|
|
-}
|
|
|
-
|
|
|
-RouteList LinuxNetLink::getIPV6Routes() const
|
|
|
+bool LinuxNetLink::routeIsSet(const InetAddress &target, const InetAddress &via, const InetAddress &src, const char *ifname)
|
|
|
{
|
|
|
- return _routes_ipv6;
|
|
|
+ Mutex::Lock rl(_routes_m);
|
|
|
+ const std::set<LinuxNetLink::Route> &rs = _routes[target];
|
|
|
+ for(std::set<LinuxNetLink::Route>::const_iterator ri(rs.begin());ri!=rs.end();++ri) {
|
|
|
+ if ((ri->via == via)&&(ri->src == src)) {
|
|
|
+ if (ifname) {
|
|
|
+ Mutex::Lock ifl(_if_m);
|
|
|
+ const iface_entry *ife = _interfaces.get(ri->ifidx);
|
|
|
+ if ((ife)&&(!strncmp(ife->ifacename,ifname,IFNAMSIZ)))
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
int LinuxNetLink::_indexForInterface(const char *iface)
|