diff options
Diffstat (limited to 'node')
-rw-r--r-- | node/EthernetTap.hpp | 13 | ||||
-rw-r--r-- | node/EthernetTapFactory.hpp | 11 | ||||
-rw-r--r-- | node/osdep/BSDRoutingTable.cpp | 5 | ||||
-rw-r--r-- | node/osdep/BSDRoutingTable.hpp | 2 | ||||
-rw-r--r-- | node/osdep/LinuxEthernetTap.cpp | 26 | ||||
-rw-r--r-- | node/osdep/LinuxEthernetTapFactory.cpp | 83 | ||||
-rw-r--r-- | node/osdep/LinuxEthernetTapFactory.hpp | 64 | ||||
-rw-r--r-- | node/osdep/LinuxRoutingTable.cpp | 0 | ||||
-rw-r--r-- | node/osdep/LinuxRoutingTable.hpp | 0 | ||||
-rw-r--r-- | node/osdep/OSXEthernetTap.cpp | 122 | ||||
-rw-r--r-- | node/osdep/OSXEthernetTapFactory.cpp | 126 | ||||
-rw-r--r-- | node/osdep/OSXEthernetTapFactory.hpp | 77 | ||||
-rw-r--r-- | node/osdep/WindowsEthernetTap.cpp | 10 | ||||
-rw-r--r-- | node/osdep/WindowsEthernetTap.hpp | 16 | ||||
-rw-r--r-- | node/osdep/WindowsEthernetTapFactory.cpp | 0 | ||||
-rw-r--r-- | node/osdep/WindowsEthernetTapFactory.hpp | 0 | ||||
-rw-r--r-- | node/osdep/WindowsRoutingTable.cpp | 0 | ||||
-rw-r--r-- | node/osdep/WindowsRoutingTable.hpp | 0 |
18 files changed, 419 insertions, 136 deletions
diff --git a/node/EthernetTap.hpp b/node/EthernetTap.hpp index ab59c957..ba534a7e 100644 --- a/node/EthernetTap.hpp +++ b/node/EthernetTap.hpp @@ -48,6 +48,13 @@ namespace ZeroTier { */ class EthernetTap : NonCopyable { +protected: + EthernetTap(const char *cn,const MAC &m,unsigned int mt,unsigned int met) : + _implName(cn), + _mac(m), + _mtu(mt), + _metric(met) {} + public: virtual ~EthernetTap() {} @@ -188,12 +195,6 @@ public: virtual bool updateMulticastGroups(std::set<MulticastGroup> &groups) = 0; protected: - EthernetTap(const char *cn,const MAC &m,unsigned int mt,unsigned int met) : - _implName(cn), - _mac(m), - _mtu(mt), - _metric(met) {} - const char *_implName; MAC _mac; unsigned int _mtu; diff --git a/node/EthernetTapFactory.hpp b/node/EthernetTapFactory.hpp index 94d13ba6..fde458f9 100644 --- a/node/EthernetTapFactory.hpp +++ b/node/EthernetTapFactory.hpp @@ -31,8 +31,12 @@ #include <stdint.h> #include <stdexcept> +#include <vector> +#include <string> #include "MAC.hpp" +#include "NonCopyable.hpp" +#include "Buffer.hpp" namespace ZeroTier { @@ -49,7 +53,7 @@ class EthernetTap; * as well as moving toward a design that makes unit testing the entire app * quite a bit easier. */ -class EthernetTapFactory +class EthernetTapFactory : NonCopyable { public: EthernetTapFactory() {} @@ -90,6 +94,11 @@ public: * @param tap Tap instance */ virtual void close(EthernetTap *tap) = 0; + + /** + * @return All currently open tap device names + */ + virtual std::vector<std::string> allTapDeviceNames() const = 0; }; } // namespace ZeroTier diff --git a/node/osdep/BSDRoutingTable.cpp b/node/osdep/BSDRoutingTable.cpp index 92a87da0..fede9cce 100644 --- a/node/osdep/BSDRoutingTable.cpp +++ b/node/osdep/BSDRoutingTable.cpp @@ -43,7 +43,7 @@ #include <algorithm> #include <utility> -#include "Constants.hpp" +#include "../Constants.hpp" #include "BSDRoutingTable.hpp" // All I wanted was the bloody rounting table. I didn't expect the Spanish inquisition. @@ -115,6 +115,9 @@ std::vector<RoutingTable::Entry> BSDRoutingTable::get(bool includeLinkLocal,bool // Nobody expects the Spanish inquisition! if ((sin6->sin6_addr.s6_addr[0] == 0xfe)&&((sin6->sin6_addr.s6_addr[1] & 0xc0) == 0x80)) { // Our chief weapon is... in-band signaling! + // Seriously who in the living fuck thought this was a good idea and + // then had the sadistic idea to not document it anywhere? Of course it's + // not like there is any documentation on BSD sysctls anyway. unsigned int interfaceIndex = ((((unsigned int)sin6->sin6_addr.s6_addr[2]) << 8) & 0xff) | (((unsigned int)sin6->sin6_addr.s6_addr[3]) & 0xff); sin6->sin6_addr.s6_addr[2] = 0; sin6->sin6_addr.s6_addr[3] = 0; diff --git a/node/osdep/BSDRoutingTable.hpp b/node/osdep/BSDRoutingTable.hpp index 26237b12..c0e98943 100644 --- a/node/osdep/BSDRoutingTable.hpp +++ b/node/osdep/BSDRoutingTable.hpp @@ -28,7 +28,7 @@ #ifndef ZT_BSDROUTINGTABLE_HPP #define ZT_BSDROUTINGTABLE_HPP -#include "RoutingTable.hpp" +#include "../RoutingTable.hpp" namespace ZeroTier { diff --git a/node/osdep/LinuxEthernetTap.cpp b/node/osdep/LinuxEthernetTap.cpp index a4414cc6..0b0c1c4f 100644 --- a/node/osdep/LinuxEthernetTap.cpp +++ b/node/osdep/LinuxEthernetTap.cpp @@ -215,8 +215,6 @@ LinuxEthernetTap::LinuxEthernetTap( ::pipe(_shutdownSignalPipe); - TRACE("tap %s created",_dev.c_str()); - _thread = Thread::start(this); } @@ -341,22 +339,14 @@ std::set<InetAddress> LinuxEthernetTap::ips() const void LinuxEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) { - char putBuf[4096 + 14]; - if ((_fd > 0)&&(len <= _mtu)) { + char putBuf[8194]; + if ((_fd > 0)&&(len <= _mtu)&&(_enabled)) { to.copyTo(putBuf,6); from.copyTo(putBuf + 6,6); *((uint16_t *)(putBuf + 12)) = htons((uint16_t)etherType); memcpy(putBuf + 14,data,len); len += 14; - - int n = ::write(_fd,putBuf,len); - if (n <= 0) { - LOG("error writing packet to Ethernet tap device: %s",strerror(errno)); - } else if (n != (int)len) { - // Saw this gremlin once, so log it if we see it again... OSX tap - // or something seems to have goofy issues with certain MTUs. - LOG("ERROR: write underrun: %s tap write() wrote %d of %u bytes of frame",_dev.c_str(),n,len); - } + ::write(_fd,putBuf,len); } } @@ -465,13 +455,15 @@ void LinuxEthernetTap::threadMain() if (r > 14) { if (r > ((int)_mtu + 14)) // sanity check for weird TAP behavior on some platforms r = _mtu + 14; - to.setTo(getBuf,6); - from.setTo(getBuf + 6,6); - unsigned int etherType = ntohs(((const uint16_t *)getBuf)[6]); - if (etherType != 0x8100) { // VLAN tagged frames are not supported! + + if (_enabled) { + 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); } + r = 0; } } diff --git a/node/osdep/LinuxEthernetTapFactory.cpp b/node/osdep/LinuxEthernetTapFactory.cpp new file mode 100644 index 00000000..fccb6bd5 --- /dev/null +++ b/node/osdep/LinuxEthernetTapFactory.cpp @@ -0,0 +1,83 @@ +/* + * ZeroTier One - Global Peer to Peer Ethernet + * Copyright (C) 2011-2014 ZeroTier Networks LLC + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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/>. + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +#include "LinuxEthernetTapFactory.hpp" +#include "LinuxEthernetTap.hpp" + +namespace ZeroTier { + +LinuxEthernetTapFactory::LinuxEthernetTapFactory() +{ +} + +LinuxEthernetTapFactory::~LinuxEthernetTapFactory() +{ + Mutex::Lock _l(_devices_m); + for(std::vector<EthernetTap *>::iterator d(_devices.begin());d!=_devices.end();++d) + delete *d; +} + +EthernetTap *LinuxEthernetTapFactory::open( + 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 *arg) +{ + Mutex::Lock _l(_devices_m); + EthernetTap *t = new LinuxEthernetTap(mac,mtu,metric,nwid,desiredDevice,friendlyName,handler,arg); + _devices.push_back(t); + return t; +} + +void LinuxEthernetTapFactory::close(EthernetTap *tap) +{ + { + Mutex::Lock _l(_devices_m); + for(std::vector<EthernetTap *>::iterator d(_devices.begin());d!=_devices.end();++d) { + if (*d == tap) { + _devices.erase(d); + break; + } + } + } + delete tap; +} + +std::vector<std::string> allTapDeviceNames() const +{ + std::vector<std::string> dn; + Mutex::Lock _l(_devices_m); + for(std::vector<EthernetTap *>::const_iterator d(_devices.begin());d!=_devices.end();++d) + dn.push_back(d->deviceName()); + return dn; +} + +} // namespace ZeroTier diff --git a/node/osdep/LinuxEthernetTapFactory.hpp b/node/osdep/LinuxEthernetTapFactory.hpp new file mode 100644 index 00000000..a5d13216 --- /dev/null +++ b/node/osdep/LinuxEthernetTapFactory.hpp @@ -0,0 +1,64 @@ +/* + * ZeroTier One - Global Peer to Peer Ethernet + * Copyright (C) 2011-2014 ZeroTier Networks LLC + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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/>. + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +#ifndef ZT_LINUXETHERNETTAPFACTORY_HPP +#define ZT_LINUXETHERNETTAPFACTORY_HPP + +#include <vector> +#include <string> + +#include "../EthernetTapFactory.hpp" +#include "../Mutex.hpp" + +namespace ZeroTier { + +class LinuxEthernetTapFactory : public EthernetTapFactory +{ +public: + LinuxEthernetTapFactory(); + virtual ~LinuxEthernetTapFactory(); + + virtual EthernetTap *open( + 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 *arg); + virtual void close(EthernetTap *tap); + virtual std::vector<std::string> allTapDeviceNames() const; + +private: + std::vector<EthernetTap *> _devices; + Mutex _devices_m; +}; + +} // namespace ZeroTier + +#endif diff --git a/node/osdep/LinuxRoutingTable.cpp b/node/osdep/LinuxRoutingTable.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/node/osdep/LinuxRoutingTable.cpp diff --git a/node/osdep/LinuxRoutingTable.hpp b/node/osdep/LinuxRoutingTable.hpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/node/osdep/LinuxRoutingTable.hpp diff --git a/node/osdep/OSXEthernetTap.cpp b/node/osdep/OSXEthernetTap.cpp index d5d02f40..1e2ddbed 100644 --- a/node/osdep/OSXEthernetTap.cpp +++ b/node/osdep/OSXEthernetTap.cpp @@ -328,28 +328,12 @@ OSXEthernetTap::OSXEthernetTap( _fd(0), _enabled(true) { - char devpath[64],ethaddr[64],mtustr[16],tmp[4096]; + char devpath[64],ethaddr[64],mtustr[32],metstr[32]; struct stat stattmp; Mutex::Lock _l(__tapCreateLock); // create only one tap at a time, globally if (mtu > 2800) throw std::runtime_error("max tap MTU is 2800"); - - // Check for existence of ZT tap devices, try to load module if not there - const char *kextload = UNIX_COMMANDS[ZT_MAC_KEXTLOAD_COMMAND]; - if ((stat("/dev/zt0",&stattmp))&&(kextload)) { - strcpy(tmp,_r->homePath.c_str()); - long kextpid = (long)vfork(); - if (kextpid == 0) { - chdir(tmp); - execl(kextload,kextload,"-q","-repository",tmp,"tap.kext",(const char *)0); - _exit(-1); - } else if (kextpid > 0) { - int exitcode = -1; - waitpid(kextpid,&exitcode,0); - usleep(500); - } else throw std::runtime_error("unable to create subprocess with fork()"); - } if (stat("/dev/zt0",&stattmp)) throw std::runtime_error("/dev/zt# tap devices do not exist and unable to load kernel extension"); @@ -390,22 +374,17 @@ OSXEthernetTap::OSXEthernetTap( throw std::runtime_error("unable to set flags on file descriptor for TAP device"); } - const char *ifconfig = UNIX_COMMANDS[ZT_UNIX_IFCONFIG_COMMAND]; - if (!ifconfig) { - ::close(_fd); - throw std::runtime_error("unable to find 'ifconfig' command on system"); - } - // Configure MAC address and MTU, bring interface up Utils::snprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]); - Utils::snprintf(mtustr,sizeof(mtustr),"%u",mtu); - long cpid; - if ((cpid = (long)vfork()) == 0) { - execl(ifconfig,ifconfig,_dev.c_str(),"lladdr",ethaddr,"mtu",mtustr,"up",(const char *)0); - _exit(-1); - } else { + Utils::snprintf(mtustr,sizeof(mtustr),"%u",_mtu); + Utils::snprintf(metstr,sizeof(metstr),"%u",_metric) + long cpid = (long)vfork(); + if (cpid == 0) { + ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"lladdr",ethaddr,"mtu",mtustr,"metric",metstr,"up",(const char *)0); + ::_exit(-1); + } else if (cpid > 0) { int exitcode = -1; - waitpid(cpid,&exitcode,0); + ::waitpid(cpid,&exitcode,0); if (exitcode) { ::close(_fd); throw std::runtime_error("ifconfig failure setting link-layer address and activating tap interface"); @@ -420,10 +399,6 @@ OSXEthernetTap::OSXEthernetTap( ::pipe(_shutdownSignalPipe); _thread = Thread::start(this); - - EthernetTap_instances_m.lock(); - ++EthernetTap_instances; - EthernetTap_instances_m.unlock(); } OSXEthernetTap::~OSXEthernetTap() @@ -433,27 +408,6 @@ OSXEthernetTap::~OSXEthernetTap() ::close(_fd); ::close(_shutdownSignalPipe[0]); ::close(_shutdownSignalPipe[1]); - - EthernetTap_instances_m.lock(); - int instances = --EthernetTap_instances; - EthernetTap_instances_m.unlock(); - if (instances <= 0) { - // Unload OSX kernel extension on the deletion of the last EthernetTap - // instance. - const char *kextunload = UNIX_COMMANDS[ZT_MAC_KEXTUNLOAD_COMMAND]; - if (kextunload) { - char tmp[4096]; - sprintf(tmp,"%s/tap.kext",_r->homePath.c_str()); - long kextpid = (long)vfork(); - if (kextpid == 0) { - execl(kextunload,kextunload,tmp,(const char *)0); - _exit(-1); - } else if (kextpid > 0) { - int exitcode = -1; - waitpid(kextpid,&exitcode,0); - } - } - } } void OSXEthernetTap::setEnabled(bool en) @@ -469,14 +423,11 @@ bool OSXEthernetTap::enabled() const static bool ___removeIp(const std::string &_dev,const InetAddress &ip) { - const char *ifconfig = UNIX_COMMANDS[ZT_UNIX_IFCONFIG_COMMAND]; - if (!ifconfig) - return false; - long cpid; - if ((cpid = (long)vfork()) == 0) { - execl(ifconfig,ifconfig,_dev.c_str(),"inet",ip.toIpString().c_str(),"-alias",(const char *)0); + long cpid = (long)vfork(); + if (cpid == 0) { + execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"inet",ip.toIpString().c_str(),"-alias",(const char *)0); _exit(-1); - } else { + } else (cpid > 0) { int exitcode = -1; waitpid(cpid,&exitcode,0); return (exitcode == 0); @@ -486,12 +437,6 @@ static bool ___removeIp(const std::string &_dev,const InetAddress &ip) bool OSXEthernetTap::addIP(const InetAddress &ip) { - const char *ifconfig = UNIX_COMMANDS[ZT_UNIX_IFCONFIG_COMMAND]; - if (!ifconfig) { - LOG("ERROR: could not configure IP address for %s: unable to find 'ifconfig' command on system (checked /sbin, /bin, /usr/sbin, /usr/bin)",_dev.c_str()); - return false; - } - if (!ip) return false; @@ -510,16 +455,15 @@ bool OSXEthernetTap::addIP(const InetAddress &ip) } } - long cpid; - if ((cpid = (long)vfork()) == 0) { - execl(ifconfig,ifconfig,_dev.c_str(),ip.isV4() ? "inet" : "inet6",ip.toString().c_str(),"alias",(const char *)0); - _exit(-1); - } else { + long cpid = (long)vfork(); + if (cpid == 0) { + ::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),ip.isV4() ? "inet" : "inet6",ip.toString().c_str(),"alias",(const char *)0); + ::_exit(-1); + } else if (cpid > 0) { int exitcode = -1; - waitpid(cpid,&exitcode,0); + ::waitpid(cpid,&exitcode,0); return (exitcode == 0); } - return false; } @@ -569,22 +513,14 @@ std::set<InetAddress> OSXEthernetTap::ips() const void OSXEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) { - char putBuf[4096 + 14]; - if ((_fd > 0)&&(len <= _mtu)) { + char putBuf[4096]; + if ((_fd > 0)&&(len <= _mtu)&&(_enabled)) { to.copyTo(putBuf,6); from.copyTo(putBuf + 6,6); *((uint16_t *)(putBuf + 12)) = htons((uint16_t)etherType); memcpy(putBuf + 14,data,len); len += 14; - - int n = ::write(_fd,putBuf,len); - if (n <= 0) { - LOG("error writing packet to Ethernet tap device: %s",strerror(errno)); - } else if (n != (int)len) { - // Saw this gremlin once, so log it if we see it again... OSX tap - // or something seems to have goofy issues with certain MTUs. - LOG("ERROR: write underrun: %s tap write() wrote %d of %u bytes of frame",_dev.c_str(),n,len); - } + ::write(_fd,putBuf,len); } } @@ -669,10 +605,8 @@ void OSXEthernetTap::threadMain() if (FD_ISSET(_fd,&readfds)) { n = (int)::read(_fd,getBuf + r,sizeof(getBuf) - r); if (n < 0) { - if ((errno != EINTR)&&(errno != ETIMEDOUT)) { - TRACE("unexpected error reading from tap: %s",strerror(errno)); + if ((errno != EINTR)&&(errno != ETIMEDOUT)) break; - } } else { // Some tap drivers like to send the ethernet frame and the // payload in two chunks, so handle that by accumulating @@ -681,13 +615,15 @@ void OSXEthernetTap::threadMain() if (r > 14) { if (r > ((int)_mtu + 14)) // sanity check for weird TAP behavior on some platforms r = _mtu + 14; - to.setTo(getBuf,6); - from.setTo(getBuf + 6,6); - unsigned int etherType = ntohs(((const uint16_t *)getBuf)[6]); - if (etherType != 0x8100) { // VLAN tagged frames are not supported! + + if (_enabled) { + 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); } + r = 0; } } diff --git a/node/osdep/OSXEthernetTapFactory.cpp b/node/osdep/OSXEthernetTapFactory.cpp new file mode 100644 index 00000000..4d0f2069 --- /dev/null +++ b/node/osdep/OSXEthernetTapFactory.cpp @@ -0,0 +1,126 @@ +/* + * ZeroTier One - Global Peer to Peer Ethernet + * Copyright (C) 2011-2014 ZeroTier Networks LLC + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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/>. + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "OSXEthernetTapFactory.hpp" +#include "OSXEthernetTap.hpp" + +namespace ZeroTier { + +OSXEthernetTapFactory::OSXEthernetTapFactory(const char *pathToTapKext,const char *tapKextName) + _pathToTapKext((pathToTapKext) ? pathToTapKext : ""), + _tapKextName((tapKextName) ? tapKextName : "") +{ + struct stat stattmp; + + if ((_pathToTapKext.length())&&(_tapKextName.length())) { + if (stat("/dev/zt0",&stattmp)) { + long kextpid = (long)vfork(); + if (kextpid == 0) { + ::chdir(_pathToTapKext.c_str()); + ::execl("/sbin/kextload","/sbin/kextload","-q","-repository",_pathToTapKext.c_str(),_tapKextName.c_str(),(const char *)0); + ::_exit(-1); + } else if (kextpid > 0) { + int exitcode = -1; + ::waitpid(kextpid,&exitcode,0); + } else throw std::runtime_error("unable to create subprocess with fork()"); + } + } + + if (stat("/dev/zt0",&stattmp)) { + ::usleep(500); // give tap device driver time to start up and try again + if (stat("/dev/zt0",&stattmp)) + throw std::runtime_error("/dev/zt# tap devices do not exist and unable to load kernel extension"); + } +} + +OSXEthernetTapFactory::~OSXEthernetTapFactory() +{ + Mutex::Lock _l(_devices_m); + for(std::vector<EthernetTap *>::iterator d(_devices.begin());d!=_devices.end();++d) + delete *d; + + if ((_pathToTapKext.length())&&(_tapKextName.length())) { + // Attempt to unload kext. If anything else is using a /dev/zt# node, this + // fails and the kext stays in the kernel. + char tmp[16384]; + sprintf(tmp,"%s/%s",_pathToTapKext.c_str(),_tapKextName.c_str()); + long kextpid = (long)vfork(); + if (kextpid == 0) { + ::execl("/sbin/kextunload","/sbin/kextunload",tmp,(const char *)0); + ::_exit(-1); + } else if (kextpid > 0) { + int exitcode = -1; + ::waitpid(kextpid,&exitcode,0); + } + } +} + +EthernetTap *OSXEthernetTapFactory::open( + 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 *arg) +{ + Mutex::Lock _l(_devices_m); + EthernetTap *t = new OSXEthernetTap(mac,mtu,metric,nwid,desiredDevice,friendlyName,handler,arg); + _devices.push_back(t); + return t; +} + +void OSXEthernetTapFactory::close(EthernetTap *tap) +{ + { + Mutex::Lock _l(_devices_m); + for(std::vector<EthernetTap *>::iterator d(_devices.begin());d!=_devices.end();++d) { + if (*d == tap) { + _devices.erase(d); + break; + } + } + } + delete tap; +} + +std::vector<std::string> allTapDeviceNames() const +{ + std::vector<std::string> dn; + Mutex::Lock _l(_devices_m); + for(std::vector<EthernetTap *>::const_iterator d(_devices.begin());d!=_devices.end();++d) + dn.push_back(d->deviceName()); + return dn; +} + +} // namespace ZeroTier diff --git a/node/osdep/OSXEthernetTapFactory.hpp b/node/osdep/OSXEthernetTapFactory.hpp new file mode 100644 index 00000000..720e038a --- /dev/null +++ b/node/osdep/OSXEthernetTapFactory.hpp @@ -0,0 +1,77 @@ +/* + * ZeroTier One - Global Peer to Peer Ethernet + * Copyright (C) 2011-2014 ZeroTier Networks LLC + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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/>. + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +#ifndef ZT_LINUXETHERNETTAPFACTORY_HPP +#define ZT_LINUXETHERNETTAPFACTORY_HPP + +#include <vector> +#include <string> + +#include "../EthernetTapFactory.hpp" +#include "../Mutex.hpp" + +namespace ZeroTier { + +class OSXEthernetTapFactory : public EthernetTapFactory +{ +public: + /** + * Create OSX ethernet tap factory + * + * If kext paths are specified, an attempt will be made to load the kext + * on launch if not present and unload it on shutdown. + * + * @param pathToTapKext Full path to the location of the tap kext + * @param tapKextName Name of tap kext as found within tap kext path (usually "tap.kext") + * @throws std::runtime_error Tap not available and unable to load kext + */ + OSXEthernetTapFactory(const char *pathToTapKext,const char *tapKextName); + + virtual ~OSXEthernetTapFactory(); + + virtual EthernetTap *open( + 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 *arg); + virtual void close(EthernetTap *tap); + virtual std::vector<std::string> allTapDeviceNames() const; + +private: + std::vector<EthernetTap *> _devices; + Mutex _devices_m; + std::string _pathToTapKext; + std::string _tapKextName; +}; + +} // namespace ZeroTier + +#endif diff --git a/node/osdep/WindowsEthernetTap.cpp b/node/osdep/WindowsEthernetTap.cpp index 5ea3d2a9..8541ce7c 100644 --- a/node/osdep/WindowsEthernetTap.cpp +++ b/node/osdep/WindowsEthernetTap.cpp @@ -25,7 +25,7 @@ * LLC. Start here: http://www.zerotier.com/ */ -#include "Constants.hpp" +#include "../Constants.hpp" #include <stdio.h> #include <stdlib.h> @@ -42,12 +42,10 @@ #include <nldef.h> #include <netioapi.h> -#include "EthernetTap.hpp" +#include "../EthernetTap.hpp" +#include "../Utils.hpp" +#include "../Mutex.hpp" #include "WindowsEthernetTap.hpp" -#include "Logger.hpp" -#include "RuntimeEnvironment.hpp" -#include "Utils.hpp" -#include "Mutex.hpp" #include "..\windows\TapDriver\tap-windows.h" diff --git a/node/osdep/WindowsEthernetTap.hpp b/node/osdep/WindowsEthernetTap.hpp index 80db453e..74c56621 100644 --- a/node/osdep/WindowsEthernetTap.hpp +++ b/node/osdep/WindowsEthernetTap.hpp @@ -35,19 +35,14 @@ #include <queue> #include <stdexcept> -#include "Constants.hpp" -#include "EthernetTap.hpp" -#include "Mutex.hpp" -#include "Thread.hpp" -#include "Array.hpp" - -#include <WinSock2.h> -#include <Windows.h> +#include "../Constants.hpp" +#include "../EthernetTap.hpp" +#include "../Mutex.hpp" +#include "../Thread.hpp" +#include "../Array.hpp" namespace ZeroTier { -class RuntimeEnvironment; - /** * Windows Ethernet tap device using bundled ztTap driver */ @@ -114,7 +109,6 @@ public: static int cleanPersistentTapDevices(const RuntimeEnvironment *_r,const std::set<std::string> &exceptThese,bool alsoRemoveUnassociatedDevices); private: - const RuntimeEnvironment *_r; void (*_handler)(void *,const MAC &,const MAC &,unsigned int,const Buffer<4096> &); void *_arg; Thread _thread; diff --git a/node/osdep/WindowsEthernetTapFactory.cpp b/node/osdep/WindowsEthernetTapFactory.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/node/osdep/WindowsEthernetTapFactory.cpp diff --git a/node/osdep/WindowsEthernetTapFactory.hpp b/node/osdep/WindowsEthernetTapFactory.hpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/node/osdep/WindowsEthernetTapFactory.hpp diff --git a/node/osdep/WindowsRoutingTable.cpp b/node/osdep/WindowsRoutingTable.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/node/osdep/WindowsRoutingTable.cpp diff --git a/node/osdep/WindowsRoutingTable.hpp b/node/osdep/WindowsRoutingTable.hpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/node/osdep/WindowsRoutingTable.hpp |