diff options
-rw-r--r-- | node/Node.cpp | 2 | ||||
-rw-r--r-- | one.cpp | 2 | ||||
-rw-r--r-- | osdep/LinuxEthernetTap.cpp | 117 | ||||
-rw-r--r-- | osdep/LinuxEthernetTap.hpp | 37 | ||||
-rw-r--r-- | osdep/OSXEthernetTap.cpp | 2 | ||||
-rw-r--r-- | selftest.cpp | 4 | ||||
-rw-r--r-- | service/OneService.cpp | 5 |
7 files changed, 93 insertions, 76 deletions
diff --git a/node/Node.cpp b/node/Node.cpp index 09ad729e..2ffdeb96 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -137,6 +137,8 @@ Node::Node( Node::~Node() { + Mutex::Lock _l(_networks_m); + _networks.clear(); // delete these before we delete RR delete RR->sa; delete RR->topology; delete RR->antiRec; @@ -381,7 +381,7 @@ static int cli(int argc,char **argv) verstr[0] = '-'; verstr[1] = (char)0; } - printf("200 listpeers %s %s %lld %s %s"ZT_EOL_S,address,(paths.length()) ? paths.c_str() : "-",latency,verstr,role); + printf("200 listpeers %s %s %lld %s %s"ZT_EOL_S,address,(paths.length()) ? paths.c_str() : "-",(long long)latency,verstr,role); } } } diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index ee89159e..73eb0cc5 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -47,14 +47,14 @@ #include <linux/if_ether.h> #include <ifaddrs.h> -#include <string> -#include <map> -#include <set> #include <algorithm> +#include <utility> #include "../node/Constants.hpp" #include "../node/Utils.hpp" #include "../node/Mutex.hpp" +#include "../node/Dictionary.hpp" +#include "OSUtils.hpp" #include "LinuxEthernetTap.hpp" // ff:ff:ff:ff:ff:ff with no ADI @@ -65,23 +65,27 @@ namespace ZeroTier { static Mutex __tapCreateLock; LinuxEthernetTap::LinuxEthernetTap( + const char *homePath, const MAC &mac, unsigned int mtu, unsigned int metric, uint64_t nwid, - const char *desiredDevice, const char *friendlyName, - void (*handler)(void *,const MAC &,const MAC &,unsigned int,const Buffer<4096> &), + void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), void *arg) : - EthernetTap("LinuxEthernetTap",mac,mtu,metric), _handler(handler), _arg(arg), + _nwid(nwid), + _homePath(homePath), + _mtu(mtu), _fd(0), _enabled(true) { - char procpath[128]; + char procpath[128],nwids[32]; struct stat sbuf; + Utils::snprintf(nwids,sizeof(nwids),"%.16llx",nwid); + Mutex::Lock _l(__tapCreateLock); // create only one tap at a time, globally if (mtu > 2800) @@ -96,11 +100,18 @@ LinuxEthernetTap::LinuxEthernetTap( // Try to recall our last device name, or pick an unused one if that fails. bool recalledDevice = false; - if ((desiredDevice)&&(desiredDevice[0])) { - Utils::scopy(ifr.ifr_name,sizeof(ifr.ifr_name),desiredDevice); - Utils::snprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); - recalledDevice = (stat(procpath,&sbuf) != 0); + std::string devmapbuf; + Dictionary devmap; + if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(),devmapbuf)) { + devmap.fromString(devmapbuf); + std::string desiredDevice(devmap.get(nwids,"")); + if (desiredDevice.length() > 2) { + Utils::scopy(ifr.ifr_name,sizeof(ifr.ifr_name),desiredDevice.c_str()); + Utils::snprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name); + recalledDevice = (stat(procpath,&sbuf) != 0); + } } + if (!recalledDevice) { int devno = 0; do { @@ -169,6 +180,9 @@ LinuxEthernetTap::LinuxEthernetTap( ::pipe(_shutdownSignalPipe); + devmap[nwids] = _dev; + OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(),devmap.toString()); + _thread = Thread::start(this); } @@ -184,7 +198,6 @@ LinuxEthernetTap::~LinuxEthernetTap() void LinuxEthernetTap::setEnabled(bool en) { _enabled = en; - // TODO: interface status change } bool LinuxEthernetTap::enabled() const @@ -196,7 +209,7 @@ static bool ___removeIp(const std::string &_dev,const InetAddress &ip) { long cpid = (long)vfork(); if (cpid == 0) { - Utils::redirectUnixOutputs("/dev/null",(const char *)0); + OSUtils::redirectUnixOutputs("/dev/null",(const char *)0); ::execl("/sbin/ip","/sbin/ip","addr","del",ip.toString().c_str(),"dev",_dev.c_str(),(const char *)0); ::execl("/usr/sbin/ip","/usr/sbin/ip","addr","del",ip.toString().c_str(),"dev",_dev.c_str(),(const char *)0); ::_exit(-1); @@ -207,23 +220,24 @@ static bool ___removeIp(const std::string &_dev,const InetAddress &ip) } } -bool LinuxEthernetTap::addIP(const InetAddress &ip) +bool LinuxEthernetTap::addIp(const InetAddress &ip) { if (!ip) return false; - std::set<InetAddress> allIps(ips()); - if (allIps.count(ip) > 0) + + std::vector<InetAddress> allIps(ips()); + if (std::binary_search(allIps.begin(),allIps.end(),ip)) return true; // Remove and reconfigure if address is the same but netmask is different - for(std::set<InetAddress>::iterator i(allIps.begin());i!=allIps.end();++i) { + for(std::vector<InetAddress>::iterator i(allIps.begin());i!=allIps.end();++i) { if (i->ipsEqual(ip)) ___removeIp(_dev,*i); } long cpid = (long)vfork(); if (cpid == 0) { - Utils::redirectUnixOutputs("/dev/null",(const char *)0); + OSUtils::redirectUnixOutputs("/dev/null",(const char *)0); if (ip.isV4()) { ::execl("/sbin/ip","/sbin/ip","addr","add",ip.toString().c_str(),"broadcast",ip.broadcast().toIpString().c_str(),"dev",_dev.c_str(),(const char *)0); ::execl("/usr/sbin/ip","/usr/sbin/ip","addr","add",ip.toString().c_str(),"broadcast",ip.broadcast().toIpString().c_str(),"dev",_dev.c_str(),(const char *)0); @@ -241,22 +255,25 @@ bool LinuxEthernetTap::addIP(const InetAddress &ip) return false; } -bool LinuxEthernetTap::removeIP(const InetAddress &ip) +bool LinuxEthernetTap::removeIp(const InetAddress &ip) { - if (ips().count(ip) > 0) { + if (!ip) + return true; + std::vector<InetAddress> allIps(ips()); + if (!std::binary_search(allIps.begin(),allIps.end(),ip)) { if (___removeIp(_dev,ip)) return true; } return false; } -std::set<InetAddress> LinuxEthernetTap::ips() const +std::vector<InetAddress> LinuxEthernetTap::ips() const { struct ifaddrs *ifa = (struct ifaddrs *)0; if (getifaddrs(&ifa)) - return std::set<InetAddress>(); + return std::vector<InetAddress>(); - std::set<InetAddress> r; + std::vector<InetAddress> r; struct ifaddrs *p = ifa; while (p) { @@ -265,14 +282,14 @@ std::set<InetAddress> LinuxEthernetTap::ips() const case AF_INET: { struct sockaddr_in *sin = (struct sockaddr_in *)p->ifa_addr; struct sockaddr_in *nm = (struct sockaddr_in *)p->ifa_netmask; - r.insert(InetAddress(&(sin->sin_addr.s_addr),4,Utils::countBits((uint32_t)nm->sin_addr.s_addr))); + r.push_back(InetAddress(&(sin->sin_addr.s_addr),4,Utils::countBits((uint32_t)nm->sin_addr.s_addr))); } break; case AF_INET6: { struct sockaddr_in6 *sin = (struct sockaddr_in6 *)p->ifa_addr; struct sockaddr_in6 *nm = (struct sockaddr_in6 *)p->ifa_netmask; uint32_t b[4]; memcpy(b,nm->sin6_addr.s6_addr,sizeof(b)); - r.insert(InetAddress(sin->sin6_addr.s6_addr,16,Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3]))); + r.push_back(InetAddress(sin->sin6_addr.s6_addr,16,Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3]))); } break; } } @@ -282,6 +299,9 @@ std::set<InetAddress> LinuxEthernetTap::ips() const if (ifa) freeifaddrs(ifa); + std::sort(r.begin(),r.end()); + std::unique(r.begin(),r.end()); + return r; } @@ -307,11 +327,11 @@ void LinuxEthernetTap::setFriendlyName(const char *friendlyName) { } -bool LinuxEthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups) +void LinuxEthernetTap::scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed) { char *ptr,*ptr2; unsigned char mac[6]; - std::set<MulticastGroup> newGroups; + std::vector<MulticastGroup> newGroups; int fd = ::open("/proc/net/dev_mcast",O_RDONLY); if (fd > 0) { @@ -331,39 +351,29 @@ bool LinuxEthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups) ++fno; } if ((devname)&&(!strcmp(devname,_dev.c_str()))&&(mcastmac)&&(Utils::unhex(mcastmac,mac,6) == 6)) - newGroups.insert(MulticastGroup(MAC(mac,6),0)); + newGroups.push_back(MulticastGroup(MAC(mac,6),0)); } } ::close(fd); } - { - std::set<InetAddress> allIps(ips()); - for(std::set<InetAddress>::const_iterator i(allIps.begin());i!=allIps.end();++i) - newGroups.insert(MulticastGroup::deriveMulticastGroupForAddressResolution(*i)); - } + std::vector<InetAddress> allIps(ips()); + for(std::vector<InetAddress>::iterator ip(allIps.begin());ip!=allIps.end();++ip) + newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip)); - bool changed = false; + std::sort(newGroups.begin(),newGroups.end()); + std::unique(newGroups.begin(),newGroups.end()); - for(std::set<MulticastGroup>::iterator mg(newGroups.begin());mg!=newGroups.end();++mg) { - if (!groups.count(*mg)) { - groups.insert(*mg); - changed = true; - } + for(std::vector<MulticastGroup>::iterator m(newGroups.begin());m!=newGroups.end();++m) { + if (!std::binary_search(_multicastGroups.begin(),_multicastGroups.end(),*m)) + added.push_back(*m); } - for(std::set<MulticastGroup>::iterator mg(groups.begin());mg!=groups.end();) { - if ((!newGroups.count(*mg))&&(*mg != _blindWildcardMulticastGroup)) { - groups.erase(mg++); - changed = true; - } else ++mg; + for(std::vector<MulticastGroup>::iterator m(_multicastGroups.begin());m!=_multicastGroups.end();++m) { + if (!std::binary_search(newGroups.begin(),newGroups.end(),*m)) + removed.push_back(*m); } - return changed; -} - -bool LinuxEthernetTap::injectPacketFromHost(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) -{ - return false; + _multicastGroups.swap(newGroups); } void LinuxEthernetTap::threadMain() @@ -373,10 +383,7 @@ void LinuxEthernetTap::threadMain() MAC to,from; int n,nfds,r; char getBuf[8194]; - Buffer<4096> data; - // Wait for a moment after startup -- wait for Network to finish - // constructing itself. Thread::sleep(500); FD_ZERO(&readfds); @@ -410,8 +417,8 @@ void LinuxEthernetTap::threadMain() to.setTo(getBuf,6); from.setTo(getBuf + 6,6); unsigned int etherType = ntohs(((const uint16_t *)getBuf)[6]); - data.copyFrom(getBuf + 14,(unsigned int)r - 14); - _handler(_arg,from,to,etherType,data); + // TODO: VLAN support + _handler(_arg,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14); } r = 0; diff --git a/osdep/LinuxEthernetTap.hpp b/osdep/LinuxEthernetTap.hpp index ed1b8b45..441f80bc 100644 --- a/osdep/LinuxEthernetTap.hpp +++ b/osdep/LinuxEthernetTap.hpp @@ -31,9 +31,11 @@ #include <stdio.h> #include <stdlib.h> +#include <string> +#include <vector> #include <stdexcept> -#include "EthernetTap.hpp" +#include "../node/MulticastGroup.hpp" #include "Thread.hpp" namespace ZeroTier { @@ -41,40 +43,43 @@ namespace ZeroTier { /** * Linux Ethernet tap using kernel tun/tap driver */ -class LinuxEthernetTap : public EthernetTap +class LinuxEthernetTap { public: LinuxEthernetTap( + const char *homePath, const MAC &mac, unsigned int mtu, unsigned int metric, uint64_t nwid, - const char *desiredDevice, const char *friendlyName, - void (*handler)(void *,const MAC &,const MAC &,unsigned int,const Buffer<4096> &), + void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int), void *arg); - virtual ~LinuxEthernetTap(); + ~LinuxEthernetTap(); - virtual void setEnabled(bool en); - virtual bool enabled() const; - virtual bool addIP(const InetAddress &ip); - virtual bool removeIP(const InetAddress &ip); - virtual std::set<InetAddress> ips() const; - virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); - virtual std::string deviceName() const; - virtual void setFriendlyName(const char *friendlyName); - virtual bool updateMulticastGroups(std::set<MulticastGroup> &groups); - virtual bool injectPacketFromHost(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); + void setEnabled(bool en); + bool enabled() const; + bool addIp(const InetAddress &ip); + bool removeIp(const InetAddress &ip); + std::vector<InetAddress> ips() const; + void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); + std::string deviceName() const; + void setFriendlyName(const char *friendlyName); + void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed); void threadMain() throw(); private: - void (*_handler)(void *,const MAC &,const MAC &,unsigned int,const Buffer<4096> &); + void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int); void *_arg; + uint64_t _nwid; Thread _thread; + std::string _homePath; std::string _dev; + std::vector<MulticastGroup> _multicastGroups; + unsigned int _mtu; int _fd; int _shutdownSignalPipe[2]; volatile bool _enabled; diff --git a/osdep/OSXEthernetTap.cpp b/osdep/OSXEthernetTap.cpp index d1c82fce..6b6f360b 100644 --- a/osdep/OSXEthernetTap.cpp +++ b/osdep/OSXEthernetTap.cpp @@ -637,8 +637,6 @@ void OSXEthernetTap::threadMain() int n,nfds,r; char getBuf[8194]; - // Wait for a moment after startup -- wait for Network to finish - // constructing itself. Thread::sleep(500); FD_ZERO(&readfds); diff --git a/selftest.cpp b/selftest.cpp index 53f0654f..21e75924 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -833,14 +833,14 @@ int main(int argc,char **argv) srand((unsigned int)time(0)); - //r |= testPhy(); - //r |= testHttp(); r |= testSqliteNetworkController(); r |= testCrypto(); r |= testPacket(); r |= testOther(); r |= testIdentity(); r |= testCertificate(); + r |= testPhy(); + r |= testHttp(); if (r) std::cout << std::endl << "SOMETHING FAILED!" << std::endl; diff --git a/service/OneService.cpp b/service/OneService.cpp index 5ab66e72..5b0199ac 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -53,10 +53,15 @@ #include "OneService.hpp" #include "ControlPlane.hpp" +// Include the right tap device driver for this platform -- add new platforms here #ifdef __APPLE__ #include "../osdep/OSXEthernetTap.hpp" namespace ZeroTier { typedef OSXEthernetTap EthernetTap; } #endif +#ifdef __LINUX__ +#include "../osdep/LinuxEthernetTap.hpp" +namespace ZeroTier { typedef LinuxEthernetTap EthernetTap; } +#endif // Sanity limits for HTTP #define ZT_MAX_HTTP_MESSAGE_SIZE (1024 * 1024 * 8) |