Merge master into multipath

This commit is contained in:
Joseph Henry 2019-08-12 11:40:13 -07:00
commit 77ae929eb3
300 changed files with 20343 additions and 34032 deletions

View file

@ -1,6 +1,6 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/
* Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* --
*
@ -29,19 +29,18 @@
#include <unistd.h>
#include <linux/if_tun.h>
namespace ZeroTier {
struct nl_route_req {
struct nlmsghdr nl;
struct rtmsg rt;
char buf[8192];
struct nlmsghdr nl;
struct rtmsg rt;
char buf[8192];
};
struct nl_if_req {
struct nlmsghdr nl;
struct ifinfomsg ifa;
char buf[8192];
struct nlmsghdr nl;
struct ifinfomsg ifa;
char buf[8192];
};
struct nl_adr_req {
@ -63,7 +62,6 @@ LinuxNetLink::LinuxNetLink()
, _fd(socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE))
, _la({0})
{
// set socket timeout to 1 sec so we're not permablocking recv() calls
_setSocketTimeout(_fd, 1);
int yes=1;
@ -77,11 +75,8 @@ LinuxNetLink::LinuxNetLink()
::exit(1);
}
fprintf(stderr, "Requesting IPV4 Routes\n");
_requestIPv4Routes();
fprintf(stderr, "Requesting IPV6 Routes\n");
_requestIPv6Routes();
fprintf(stderr, "Requesting Interface List\n");
_requestInterfaceList();
_running = true;
@ -92,7 +87,6 @@ LinuxNetLink::~LinuxNetLink()
{
_running = false;
Thread::join(_t);
::close(_fd);
}
@ -108,17 +102,23 @@ void LinuxNetLink::_setSocketTimeout(int fd, int seconds)
}
}
#define ZT_NL_BUF_SIZE 16384
int LinuxNetLink::_doRecv(int fd)
{
char buf[8192];
char *const buf = (char *)valloc(ZT_NL_BUF_SIZE);
if (!buf) {
fprintf(stderr,"malloc failed!\n");
::exit(1);
}
char *p = NULL;
struct nlmsghdr *nlp;
int nll = 0;
int rtn = 0;
p = buf;
while(true) {
rtn = recv(fd, p, sizeof(buf) - nll, 0);
for(;;) {
rtn = recv(fd, p, ZT_NL_BUF_SIZE - nll, 0);
if (rtn > 0) {
nlp = (struct nlmsghdr *)p;
@ -127,7 +127,7 @@ int LinuxNetLink::_doRecv(int fd)
struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(nlp);
if (err->error != 0) {
#ifdef ZT_TRACE
fprintf(stderr, "rtnetlink error: %s\n", strerror(-(err->error)));
//fprintf(stderr, "rtnetlink error: %s\n", strerror(-(err->error)));
#endif
}
p = buf;
@ -152,9 +152,9 @@ int LinuxNetLink::_doRecv(int fd)
}
if (nlp->nlmsg_type == NLMSG_OVERRUN) {
#ifdef ZT_TRACE
//#ifdef ZT_TRACE
fprintf(stderr, "NLMSG_OVERRUN: Data lost\n");
#endif
//#endif
p = buf;
nll = 0;
break;
@ -163,6 +163,7 @@ int LinuxNetLink::_doRecv(int fd)
nll += rtn;
_processMessage(nlp, nll);
p = buf;
nll = 0;
break;
@ -170,6 +171,9 @@ int LinuxNetLink::_doRecv(int fd)
break;
}
}
free(buf);
return rtn;
}
@ -244,8 +248,9 @@ void LinuxNetLink::_ipAddressAdded(struct nlmsghdr *nlp)
break;
}
}
#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
}
@ -259,7 +264,7 @@ void LinuxNetLink::_ipAddressDeleted(struct nlmsghdr *nlp)
char local[40] = {0};
char label[40] = {0};
char bcast[40] = {0};
for(;RTA_OK(rtap, ifal); rtap=RTA_NEXT(rtap,ifal))
{
switch(rtap->rta_type) {
@ -277,8 +282,9 @@ void LinuxNetLink::_ipAddressDeleted(struct nlmsghdr *nlp)
break;
}
}
#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
}
@ -290,7 +296,7 @@ void LinuxNetLink::_routeAdded(struct nlmsghdr *nlp)
char ifs[16] = {0};
char ms[24] = {0};
struct rtmsg *rtp = (struct rtmsg *) NLMSG_DATA(nlp);
struct rtmsg *rtp = (struct rtmsg *)NLMSG_DATA(nlp);
struct rtattr *rtap = (struct rtattr *)RTM_RTA(rtp);
int rtl = RTM_PAYLOAD(nlp);
@ -313,8 +319,9 @@ void LinuxNetLink::_routeAdded(struct nlmsghdr *nlp)
}
}
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);
//fprintf(stderr, "Route Added: dst %s/%s gw %s src %s if %s\n", dsts, ms, gws, srcs, ifs);
#endif
}
@ -351,14 +358,13 @@ void LinuxNetLink::_routeDeleted(struct nlmsghdr *nlp)
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);
//fprintf(stderr, "Route Deleted: dst %s/%s gw %s src %s if %s\n", dsts, ms, gws, srcs, ifs);
#endif
}
void LinuxNetLink::_linkAdded(struct nlmsghdr *nlp)
{
char mac[18] = {0};
char mac_bin[6] = {0};
unsigned char mac_bin[6] = {0};
unsigned int mtu = 0;
char ifname[IFNAMSIZ] = {0};
@ -366,19 +372,16 @@ void LinuxNetLink::_linkAdded(struct nlmsghdr *nlp)
struct rtattr *rtap = (struct rtattr *)IFLA_RTA(ifip);
int ifil = RTM_PAYLOAD(nlp);
const char *ptr;
unsigned char *ptr2;
const char *ptr = (const char *)0;
for(;RTA_OK(rtap, ifil);rtap=RTA_NEXT(rtap, ifil))
{
switch(rtap->rta_type) {
case IFLA_ADDRESS:
ptr2 = (unsigned char*)RTA_DATA(rtap);
snprintf(mac, 20, "%02x:%02x:%02x:%02x:%02x:%02x",
ptr2[0], ptr2[1], ptr2[2], ptr2[3], ptr2[4], ptr2[5]);
ptr = (const char *)RTA_DATA(rtap);
memcpy(mac_bin, ptr, 6);
break;
case IFLA_IFNAME:
ptr = (const char*)RTA_DATA(rtap);
ptr = (const char *)RTA_DATA(rtap);
memcpy(ifname, ptr, strlen(ptr));
break;
case IFLA_MTU:
@ -392,18 +395,14 @@ void LinuxNetLink::_linkAdded(struct nlmsghdr *nlp)
struct iface_entry &entry = _interfaces[ifip->ifi_index];
entry.index = ifip->ifi_index;
memcpy(entry.ifacename, ifname, sizeof(ifname));
memcpy(entry.mac, mac, sizeof(mac));
snprintf(entry.mac,sizeof(entry.mac),"%.02x:%.02x:%.02x:%.02x:%.02x:%.02x",(unsigned int)mac_bin[0],(unsigned int)mac_bin[1],(unsigned int)mac_bin[2],(unsigned int)mac_bin[3],(unsigned int)mac_bin[4],(unsigned int)mac_bin[5]);
memcpy(entry.mac_bin, mac_bin, 6);
entry.mtu = mtu;
}
#ifdef ZT_TRACE
fprintf(stderr, "Link Added: %s mac: %s, mtu: %d\n", ifname, mac, mtu);
#endif
}
void LinuxNetLink::_linkDeleted(struct nlmsghdr *nlp)
{
char mac[18] = {0};
unsigned int mtu = 0;
char ifname[40] = {0};
@ -411,16 +410,10 @@ void LinuxNetLink::_linkDeleted(struct nlmsghdr *nlp)
struct rtattr *rtap = (struct rtattr *)IFLA_RTA(ifip);
int ifil = RTM_PAYLOAD(nlp);
const char *ptr;
unsigned char *ptr2;
const char *ptr = (const char *)0;
for(;RTA_OK(rtap, ifil);rtap=RTA_NEXT(rtap, ifil))
{
switch(rtap->rta_type) {
case IFLA_ADDRESS:
ptr2 = (unsigned char*)RTA_DATA(rtap);
snprintf(mac, 20, "%02x:%02x:%02x:%02x:%02x:%02x",
ptr2[0], ptr2[1], ptr2[2], ptr2[3], ptr2[4], ptr2[5]);
break;
case IFLA_IFNAME:
ptr = (const char*)RTA_DATA(rtap);
memcpy(ifname, ptr, strlen(ptr));
@ -430,9 +423,7 @@ void LinuxNetLink::_linkDeleted(struct nlmsghdr *nlp)
break;
}
}
#ifdef ZT_TRACE
fprintf(stderr, "Link Deleted: %s mac: %s, mtu: %d\n", ifname, mac, mtu);
#endif
{
Mutex::Lock l(_if_m);
if(_interfaces.contains(ifip->ifi_index)) {
@ -458,7 +449,8 @@ void LinuxNetLink::_requestIPv4Routes()
la.nl_pid = getpid();
la.nl_groups = RTMGRP_IPV4_ROUTE;
if(bind(fd, (struct sockaddr*)&la, sizeof(la))) {
fprintf(stderr, "Error binding RTNETLINK: %s\n", strerror(errno));
fprintf(stderr, "Error binding RTNETLINK (_requiestIPv4Routes #1): %s\n", strerror(errno));
close(fd);
return;
}
@ -512,7 +504,8 @@ void LinuxNetLink::_requestIPv6Routes()
la.nl_pid = getpid();
la.nl_groups = RTMGRP_IPV6_ROUTE;
if(bind(fd, (struct sockaddr*)&la, sizeof(struct sockaddr_nl))) {
fprintf(stderr, "Error binding RTNETLINK: %s\n", strerror(errno));
fprintf(stderr, "Error binding RTNETLINK (_requestIPv6Routes #1): %s\n", strerror(errno));
close(fd);
return;
}
@ -566,7 +559,8 @@ void LinuxNetLink::_requestInterfaceList()
la.nl_pid = getpid();
la.nl_groups = RTMGRP_LINK;
if(bind(fd, (struct sockaddr*)&la, sizeof(struct sockaddr_nl))) {
fprintf(stderr, "Error binding RTNETLINK: %s\n", strerror(errno));
fprintf(stderr, "Error binding RTNETLINK (_requestInterfaceList #1): %s\n", strerror(errno));
close(fd);
return;
}
@ -603,6 +597,8 @@ void LinuxNetLink::_requestInterfaceList()
void LinuxNetLink::addRoute(const InetAddress &target, const InetAddress &via, const InetAddress &src, const char *ifaceName)
{
if (!target) return;
int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
int yes=1;
setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes));
@ -619,24 +615,18 @@ void LinuxNetLink::addRoute(const InetAddress &target, const InetAddress &via, c
la.nl_pid = getpid();
if(bind(fd, (struct sockaddr*)&la, sizeof(struct sockaddr_nl))) {
fprintf(stderr, "Error binding RTNETLINK: %s\n", strerror(errno));
fprintf(stderr, "Error binding RTNETLINK (addRoute #1): %s\n", strerror(errno));
close(fd);
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);
//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
if(!target) {
#ifdef ZT_TRACE
fprintf(stderr, "Uhhhh adding an empty route?!?!?");
#endif
return;
}
int rtl = sizeof(struct rtmsg);
struct nl_route_req req;
bzero(&req, sizeof(req));
@ -688,8 +678,6 @@ void LinuxNetLink::addRoute(const InetAddress &target, const InetAddress &via, c
}
}
req.nl.nlmsg_len = NLMSG_LENGTH(rtl);
req.nl.nlmsg_flags = NLM_F_REQUEST | NLM_F_EXCL | NLM_F_CREATE | NLM_F_ACK;
req.nl.nlmsg_type = RTM_NEWROUTE;
@ -727,6 +715,8 @@ void LinuxNetLink::addRoute(const InetAddress &target, const InetAddress &via, c
void LinuxNetLink::delRoute(const InetAddress &target, const InetAddress &via, const InetAddress &src, const char *ifaceName)
{
if (!target) return;
int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
int yes=1;
setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes));
@ -742,22 +732,17 @@ void LinuxNetLink::delRoute(const InetAddress &target, const InetAddress &via, c
la.nl_pid = getpid();
if(bind(fd, (struct sockaddr*)&la, sizeof(struct sockaddr_nl))) {
fprintf(stderr, "Error binding RTNETLINK: %s\n", strerror(errno));
fprintf(stderr, "Error binding RTNETLINK (delRoute #1): %s\n", strerror(errno));
close(fd);
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);
#endif
if(!target) {
#ifdef ZT_TRACE
fprintf(stderr, "Uhhhh deleting an empty route?!?!?");
//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
return;
}
int rtl = sizeof(struct rtmsg);
struct nl_route_req req;
@ -810,8 +795,6 @@ void LinuxNetLink::delRoute(const InetAddress &target, const InetAddress &via, c
}
}
req.nl.nlmsg_len = NLMSG_LENGTH(rtl);
req.nl.nlmsg_flags = NLM_F_REQUEST;
req.nl.nlmsg_type = RTM_DELROUTE;
@ -860,6 +843,7 @@ void LinuxNetLink::addAddress(const InetAddress &addr, const char *iface)
_setSocketTimeout(fd);
struct sockaddr_nl la;
memset(&la,0,sizeof(la));
la.nl_family = AF_NETLINK;
la.nl_pid = getpid();
if (addr.isV4()) {
@ -867,18 +851,27 @@ void LinuxNetLink::addAddress(const InetAddress &addr, const char *iface)
} else {
la.nl_groups = RTMGRP_IPV6_IFADDR;
}
if(bind(fd, (struct sockaddr*)&la, sizeof(struct sockaddr_nl))) {
fprintf(stderr, "Error binding RTNETLINK: %s\n", strerror(errno));
fprintf(stderr, "Error binding RTNETLINK (addAddress #1): %s\n", strerror(errno));
close(fd);
return;
}
#ifdef ZT_TRACE
char tmp[128];
fprintf(stderr, "Adding IP address %s to interface %s", addr.toString(tmp), iface);
//char tmp[128];
//fprintf(stderr, "Adding IP address %s to interface %s", addr.toString(tmp), iface);
#endif
int interface_index = _indexForInterface(iface);
for (int reps = 0; interface_index == -1 && reps < 10; ++reps) {
Thread::sleep(100);
interface_index = _indexForInterface(iface);
}
if (interface_index == -1) {
fprintf(stderr, "Unable to find index for interface %s\n", iface);
close(fd);
return;
}
@ -978,17 +971,21 @@ void LinuxNetLink::removeAddress(const InetAddress &addr, const char *iface)
la.nl_groups = RTMGRP_IPV6_IFADDR;
}
if(bind(fd, (struct sockaddr*)&la, sizeof(struct sockaddr_nl))) {
fprintf(stderr, "Error binding RTNETLINK: %s\n", strerror(errno));
fprintf(stderr, "Error binding RTNETLINK (removeAddress #1): %s\n", strerror(errno));
close(fd);
return;
}
#ifdef ZT_TRACE
char tmp[128];
fprintf(stderr, "Removing IP address %s from interface %s", addr.toString(tmp), iface);
//char tmp[128];
//fprintf(stderr, "Removing IP address %s from interface %s", addr.toString(tmp), iface);
#endif
int interface_index = _indexForInterface(iface);
if (interface_index == -1) {
fprintf(stderr, "Unable to find index for interface %s\n", iface);
close(fd);
return;
}