summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2014-07-26 13:10:41 -0700
committerAdam Ierymenko <adam.ierymenko@gmail.com>2014-07-26 13:10:41 -0700
commit538e8a86c8b907222303ebec0b97a6a9a87fd849 (patch)
tree0fa6e1ee1d98b95da1c137e5aa6142bee434154c /node
parent27aa6ea44e848bea720c94ccb3cbeb48876cabc9 (diff)
downloadinfinitytier-538e8a86c8b907222303ebec0b97a6a9a87fd849.tar.gz
infinitytier-538e8a86c8b907222303ebec0b97a6a9a87fd849.zip
Move node/osdep/ to sys/
Diffstat (limited to 'node')
-rw-r--r--node/osdep/BSDRoutingTable.cpp329
-rw-r--r--node/osdep/BSDRoutingTable.hpp51
-rw-r--r--node/osdep/LinuxEthernetTap.cpp474
-rw-r--r--node/osdep/LinuxEthernetTap.hpp85
-rw-r--r--node/osdep/LinuxEthernetTapFactory.cpp83
-rw-r--r--node/osdep/LinuxEthernetTapFactory.hpp64
-rw-r--r--node/osdep/LinuxRoutingTable.cpp247
-rw-r--r--node/osdep/LinuxRoutingTable.hpp49
-rw-r--r--node/osdep/OSXEthernetTap.cpp634
-rw-r--r--node/osdep/OSXEthernetTap.hpp89
-rw-r--r--node/osdep/OSXEthernetTapFactory.cpp126
-rw-r--r--node/osdep/OSXEthernetTapFactory.hpp77
-rw-r--r--node/osdep/WindowsEthernetTap.cpp837
-rw-r--r--node/osdep/WindowsEthernetTap.hpp130
-rw-r--r--node/osdep/WindowsEthernetTapFactory.cpp0
-rw-r--r--node/osdep/WindowsEthernetTapFactory.hpp0
-rw-r--r--node/osdep/WindowsRoutingTable.cpp0
-rw-r--r--node/osdep/WindowsRoutingTable.hpp0
18 files changed, 0 insertions, 3275 deletions
diff --git a/node/osdep/BSDRoutingTable.cpp b/node/osdep/BSDRoutingTable.cpp
deleted file mode 100644
index fede9cce..00000000
--- a/node/osdep/BSDRoutingTable.cpp
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * 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 <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <sys/sysctl.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <net/route.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-#include <ifaddrs.h>
-
-#include <algorithm>
-#include <utility>
-
-#include "../Constants.hpp"
-#include "BSDRoutingTable.hpp"
-
-// All I wanted was the bloody rounting table. I didn't expect the Spanish inquisition.
-
-#define ZT_BSD_ROUTE_CMD "/sbin/route"
-
-namespace ZeroTier {
-
-BSDRoutingTable::BSDRoutingTable()
-{
-}
-
-BSDRoutingTable::~BSDRoutingTable()
-{
-}
-
-std::vector<RoutingTable::Entry> BSDRoutingTable::get(bool includeLinkLocal,bool includeLoopback) const
-{
- std::vector<RoutingTable::Entry> entries;
- int mib[6];
- size_t needed;
-
- mib[0] = CTL_NET;
- mib[1] = PF_ROUTE;
- mib[2] = 0;
- mib[3] = 0;
- mib[4] = NET_RT_DUMP;
- mib[5] = 0;
- if (!sysctl(mib,6,NULL,&needed,NULL,0)) {
- if (needed <= 0)
- return entries;
-
- char *buf = (char *)::malloc(needed);
- if (buf) {
- if (!sysctl(mib,6,buf,&needed,NULL,0)) {
- struct rt_msghdr *rtm;
- for(char *next=buf,*end=buf+needed;next<end;) {
- rtm = (struct rt_msghdr *)next;
- char *saptr = (char *)(rtm + 1);
- char *saend = next + rtm->rtm_msglen;
-
- if (((rtm->rtm_flags & RTF_LLINFO) == 0)&&((rtm->rtm_flags & RTF_HOST) == 0)&&((rtm->rtm_flags & RTF_UP) != 0)&&((rtm->rtm_flags & RTF_MULTICAST) == 0)) {
- RoutingTable::Entry e;
- e.deviceIndex = -9999; // unset
-
- int which = 0;
- while (saptr < saend) {
- struct sockaddr *sa = (struct sockaddr *)saptr;
- unsigned int salen = sa->sa_len;
- if (!salen)
- break;
-
- // Skip missing fields in rtm_addrs bit field
- while ((rtm->rtm_addrs & 1) == 0) {
- rtm->rtm_addrs >>= 1;
- ++which;
- if (which > 6)
- break;
- }
- if (which > 6)
- break;
-
- rtm->rtm_addrs >>= 1;
- switch(which++) {
- case 0:
- //printf("RTA_DST\n");
- if (sa->sa_family == AF_INET6) {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
- // 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;
- if (!sin6->sin6_scope_id)
- sin6->sin6_scope_id = interfaceIndex;
- }
- }
- e.destination.set(sa);
- break;
- case 1:
- //printf("RTA_GATEWAY\n");
- switch(sa->sa_family) {
- case AF_LINK:
- e.deviceIndex = (int)((const struct sockaddr_dl *)sa)->sdl_index;
- break;
- case AF_INET:
- case AF_INET6:
- e.gateway.set(sa);
- break;
- }
- break;
- case 2: {
- if (e.destination.isV6()) {
- salen = sizeof(struct sockaddr_in6); // Confess!
- unsigned int bits = 0;
- for(int i=0;i<16;++i) {
- unsigned char c = (unsigned char)((const struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[i];
- if (c == 0xff)
- bits += 8;
- else break;
- /* must they be multiples of 8? Most of the BSD source I can find says yes..?
- else {
- while ((c & 0x80) == 0x80) {
- ++bits;
- c <<= 1;
- }
- break;
- }
- */
- }
- e.destination.setPort(bits);
- } else {
- salen = sizeof(struct sockaddr_in); // Confess!
- e.destination.setPort((unsigned int)Utils::countBits((uint32_t)((const struct sockaddr_in *)sa)->sin_addr.s_addr));
- }
- //printf("RTA_NETMASK\n");
- } break;
- /*
- case 3:
- //printf("RTA_GENMASK\n");
- break;
- case 4:
- //printf("RTA_IFP\n");
- break;
- case 5:
- //printf("RTA_IFA\n");
- break;
- case 6:
- //printf("RTA_AUTHOR\n");
- break;
- */
- }
-
- saptr += salen;
- }
-
- e.metric = (int)rtm->rtm_rmx.rmx_hopcount;
- if (e.metric < 0)
- e.metric = 0;
-
- if (((includeLinkLocal)||(!e.destination.isLinkLocal()))&&((includeLoopback)||((!e.destination.isLoopback())&&(!e.gateway.isLoopback()))))
- entries.push_back(e);
- }
-
- next = saend;
- }
- }
-
- ::free(buf);
- }
- }
-
- for(std::vector<ZeroTier::RoutingTable::Entry>::iterator e1(entries.begin());e1!=entries.end();++e1) {
- if ((!e1->device[0])&&(e1->deviceIndex >= 0))
- if_indextoname(e1->deviceIndex,e1->device);
- }
- for(std::vector<ZeroTier::RoutingTable::Entry>::iterator e1(entries.begin());e1!=entries.end();++e1) {
- if ((!e1->device[0])&&(e1->gateway)) {
- int bestMetric = 9999999;
- for(std::vector<ZeroTier::RoutingTable::Entry>::iterator e2(entries.begin());e2!=entries.end();++e2) {
- if ((e1->gateway.within(e2->destination))&&(e2->metric <= bestMetric)) {
- bestMetric = e2->metric;
- Utils::scopy(e1->device,sizeof(e1->device),e2->device);
- }
- }
- }
- }
-
- std::sort(entries.begin(),entries.end());
-
- return entries;
-}
-
-RoutingTable::Entry BSDRoutingTable::set(const InetAddress &destination,const InetAddress &gateway,const char *device,int metric)
-{
- if ((!gateway)&&((!device)||(!device[0])))
- return RoutingTable::Entry();
-
- std::vector<RoutingTable::Entry> rtab(get(true,true));
-
- for(std::vector<RoutingTable::Entry>::iterator e(rtab.begin());e!=rtab.end();++e) {
- if (e->destination == destination) {
- if (((!device)||(!device[0]))||(!strcmp(device,e->device))) {
- long p = (long)fork();
- if (p > 0) {
- int exitcode = -1;
- ::waitpid(p,&exitcode,0);
- } else if (p == 0) {
- ::close(STDOUT_FILENO);
- ::close(STDERR_FILENO);
- ::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,"delete",(destination.isV6() ? "-inet6" : "-inet"),destination.toString().c_str(),(const char *)0);
- ::_exit(-1);
- }
- }
- }
- }
-
- if (metric < 0)
- return RoutingTable::Entry();
-
- {
- char hcstr[64];
- Utils::snprintf(hcstr,sizeof(hcstr),"%d",metric);
- long p = (long)fork();
- if (p > 0) {
- int exitcode = -1;
- ::waitpid(p,&exitcode,0);
- } else if (p == 0) {
- ::close(STDOUT_FILENO);
- ::close(STDERR_FILENO);
- if (gateway) {
- ::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,"add",(destination.isV6() ? "-inet6" : "-inet"),destination.toString().c_str(),gateway.toIpString().c_str(),"-hopcount",hcstr,(const char *)0);
- } else if ((device)&&(device[0])) {
- ::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,"add",(destination.isV6() ? "-inet6" : "-inet"),destination.toString().c_str(),"-interface",device,"-hopcount",hcstr,(const char *)0);
- }
- ::_exit(-1);
- }
- }
-
- rtab = get(true,true);
- std::vector<RoutingTable::Entry>::iterator bestEntry(rtab.end());
- for(std::vector<RoutingTable::Entry>::iterator e(rtab.begin());e!=rtab.end();++e) {
- if ((e->destination == destination)&&(e->gateway.ipsEqual(gateway))) {
- if ((device)&&(device[0])) {
- if (!strcmp(device,e->device)) {
- if (metric == e->metric)
- bestEntry = e;
- }
- }
- if (bestEntry == rtab.end())
- bestEntry = e;
- }
- }
- if (bestEntry != rtab.end())
- return *bestEntry;
-
- return RoutingTable::Entry();
-}
-
-} // namespace ZeroTier
-
-// Enable and build to test routing table interface
-#if 0
-using namespace ZeroTier;
-int main(int argc,char **argv)
-{
- BSDRoutingTable rt;
-
- printf("<destination> <gateway> <interface> <metric>\n");
- std::vector<RoutingTable::Entry> ents(rt.get());
- for(std::vector<RoutingTable::Entry>::iterator e(ents.begin());e!=ents.end();++e)
- printf("%s\n",e->toString().c_str());
- printf("\n");
-
- printf("adding 1.1.1.0 and 2.2.2.0...\n");
- rt.set(InetAddress("1.1.1.0",24),InetAddress("1.2.3.4",0),(const char *)0,1);
- rt.set(InetAddress("2.2.2.0",24),InetAddress(),"en0",1);
- printf("\n");
-
- printf("<destination> <gateway> <interface> <metric>\n");
- ents = rt.get();
- for(std::vector<RoutingTable::Entry>::iterator e(ents.begin());e!=ents.end();++e)
- printf("%s\n",e->toString().c_str());
- printf("\n");
-
- printf("deleting 1.1.1.0 and 2.2.2.0...\n");
- rt.set(InetAddress("1.1.1.0",24),InetAddress("1.2.3.4",0),(const char *)0,-1);
- rt.set(InetAddress("2.2.2.0",24),InetAddress(),"en0",-1);
- printf("\n");
-
- printf("<destination> <gateway> <interface> <metric>\n");
- ents = rt.get();
- for(std::vector<RoutingTable::Entry>::iterator e(ents.begin());e!=ents.end();++e)
- printf("%s\n",e->toString().c_str());
- printf("\n");
-
- return 0;
-}
-#endif
diff --git a/node/osdep/BSDRoutingTable.hpp b/node/osdep/BSDRoutingTable.hpp
deleted file mode 100644
index c0e98943..00000000
--- a/node/osdep/BSDRoutingTable.hpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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_BSDROUTINGTABLE_HPP
-#define ZT_BSDROUTINGTABLE_HPP
-
-#include "../RoutingTable.hpp"
-
-namespace ZeroTier {
-
-/**
- * Routing table interface for BSD with sysctl() and BSD /sbin/route
- *
- * Has currently only been tested on OSX/Darwin.
- */
-class BSDRoutingTable : public RoutingTable
-{
-public:
- BSDRoutingTable();
- virtual ~BSDRoutingTable();
- virtual std::vector<RoutingTable::Entry> get(bool includeLinkLocal = false,bool includeLoopback = false) const;
- virtual RoutingTable::Entry set(const InetAddress &destination,const InetAddress &gateway,const char *device,int metric);
-};
-
-} // namespace ZeroTier
-
-#endif
diff --git a/node/osdep/LinuxEthernetTap.cpp b/node/osdep/LinuxEthernetTap.cpp
deleted file mode 100644
index 0b0c1c4f..00000000
--- a/node/osdep/LinuxEthernetTap.cpp
+++ /dev/null
@@ -1,474 +0,0 @@
-/*
- * 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 <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/wait.h>
-#include <sys/select.h>
-#include <netinet/in.h>
-#include <net/if_arp.h>
-#include <arpa/inet.h>
-#include <linux/if.h>
-#include <linux/if_tun.h>
-#include <linux/if_addr.h>
-#include <linux/if_ether.h>
-#include <ifaddrs.h>
-
-#include <string>
-#include <map>
-#include <set>
-#include <algorithm>
-
-#include "../Constants.hpp"
-#include "../Utils.hpp"
-#include "../Mutex.hpp"
-#include "LinuxEthernetTap.hpp"
-
-// ff:ff:ff:ff:ff:ff with no ADI
-static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff),0);
-
-// On startup, searches the path for required external utilities (which might vary by Linux distro)
-#define ZT_UNIX_IP_COMMAND 1
-class _CommandFinder
-{
-public:
- _CommandFinder()
- {
- _findCmd(ZT_UNIX_IP_COMMAND,"ip");
- }
- inline const char *operator[](int id) const
- throw()
- {
- std::map<int,std::string>::const_iterator c(_paths.find(id));
- if (c == _paths.end())
- return (const char *)0;
- return c->second.c_str();
- }
-private:
- inline void _findCmd(int id,const char *name)
- {
- char tmp[4096];
- ZeroTier::Utils::snprintf(tmp,sizeof(tmp),"/sbin/%s",name);
- if (ZeroTier::Utils::fileExists(tmp)) {
- _paths[id] = tmp;
- return;
- }
- ZeroTier::Utils::snprintf(tmp,sizeof(tmp),"/usr/sbin/%s",name);
- if (ZeroTier::Utils::fileExists(tmp)) {
- _paths[id] = tmp;
- return;
- }
- ZeroTier::Utils::snprintf(tmp,sizeof(tmp),"/bin/%s",name);
- if (ZeroTier::Utils::fileExists(tmp)) {
- _paths[id] = tmp;
- return;
- }
- ZeroTier::Utils::snprintf(tmp,sizeof(tmp),"/usr/bin/%s",name);
- if (ZeroTier::Utils::fileExists(tmp)) {
- _paths[id] = tmp;
- return;
- }
- }
- std::map<int,std::string> _paths;
-};
-static const _CommandFinder UNIX_COMMANDS;
-
-namespace ZeroTier {
-
-// Only permit one tap to be opened concurrently across the entire process
-static Mutex __tapCreateLock;
-
-LinuxEthernetTap::LinuxEthernetTap(
- const RuntimeEnvironment *renv,
- const char *tryToGetDevice,
- const MAC &mac,
- unsigned int mtu,
- void (*handler)(void *,const MAC &,const MAC &,unsigned int,const Buffer<4096> &),
- void *arg)
- throw(std::runtime_error) :
- EthernetTap("LinuxEthernetTap",mac,mtu),
- _r(renv),
- _handler(handler),
- _arg(arg),
- _fd(0),
- _enabled(true)
-{
- char procpath[128];
- struct stat sbuf;
- Mutex::Lock _l(__tapCreateLock); // create only one tap at a time, globally
-
- if (mtu > 4096)
- throw std::runtime_error("max tap MTU is 4096");
-
- _fd = ::open("/dev/net/tun",O_RDWR);
- if (_fd <= 0)
- throw std::runtime_error(std::string("could not open TUN/TAP device: ") + strerror(errno));
-
- struct ifreq ifr;
- memset(&ifr,0,sizeof(ifr));
-
- // Try to recall our last device name, or pick an unused one if that fails.
- bool recalledDevice = false;
- if ((tryToGetDevice)&&(tryToGetDevice[0])) {
- Utils::scopy(ifr.ifr_name,sizeof(ifr.ifr_name),tryToGetDevice);
- 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 {
- Utils::snprintf(ifr.ifr_name,sizeof(ifr.ifr_name),"zt%d",devno++);
- Utils::snprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name);
- } while (stat(procpath,&sbuf) == 0); // try zt#++ until we find one that does not exist
- }
-
- ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
- if (ioctl(_fd,TUNSETIFF,(void *)&ifr) < 0) {
- ::close(_fd);
- throw std::runtime_error("unable to configure TUN/TAP device for TAP operation");
- }
-
- _dev = ifr.ifr_name;
-
- ioctl(_fd,TUNSETPERSIST,0); // valgrind may generate a false alarm here
-
- // Open an arbitrary socket to talk to netlink
- int sock = socket(AF_INET,SOCK_DGRAM,0);
- if (sock <= 0) {
- ::close(_fd);
- throw std::runtime_error("unable to open netlink socket");
- }
-
- // Set MAC address
- ifr.ifr_ifru.ifru_hwaddr.sa_family = ARPHRD_ETHER;
- mac.copyTo(ifr.ifr_ifru.ifru_hwaddr.sa_data,6);
- if (ioctl(sock,SIOCSIFHWADDR,(void *)&ifr) < 0) {
- ::close(_fd);
- ::close(sock);
- throw std::runtime_error("unable to configure TAP hardware (MAC) address");
- return;
- }
-
- // Set MTU
- ifr.ifr_ifru.ifru_mtu = (int)mtu;
- if (ioctl(sock,SIOCSIFMTU,(void *)&ifr) < 0) {
- ::close(_fd);
- ::close(sock);
- throw std::runtime_error("unable to configure TAP MTU");
- }
-
- if (fcntl(_fd,F_SETFL,fcntl(_fd,F_GETFL) & ~O_NONBLOCK) == -1) {
- ::close(_fd);
- throw std::runtime_error("unable to set flags on file descriptor for TAP device");
- }
-
- /* Bring interface up */
- if (ioctl(sock,SIOCGIFFLAGS,(void *)&ifr) < 0) {
- ::close(_fd);
- ::close(sock);
- throw std::runtime_error("unable to get TAP interface flags");
- }
- ifr.ifr_flags |= IFF_UP;
- if (ioctl(sock,SIOCSIFFLAGS,(void *)&ifr) < 0) {
- ::close(_fd);
- ::close(sock);
- throw std::runtime_error("unable to set TAP interface flags");
- }
-
- ::close(sock);
-
- // Set close-on-exec so that devices cannot persist if we fork/exec for update
- fcntl(_fd,F_SETFD,fcntl(_fd,F_GETFD) | FD_CLOEXEC);
-
- ::pipe(_shutdownSignalPipe);
-
- _thread = Thread::start(this);
-}
-
-LinuxEthernetTap::~LinuxEthernetTap()
-{
- ::write(_shutdownSignalPipe[1],"\0",1); // causes thread to exit
- Thread::join(_thread);
- ::close(_fd);
- ::close(_shutdownSignalPipe[0]);
- ::close(_shutdownSignalPipe[1]);
-}
-
-void LinuxEthernetTap::setEnabled(bool en)
-{
- _enabled = en;
- // TODO: interface status change
-}
-
-bool LinuxEthernetTap::enabled() const
-{
- return _enabled;
-}
-
-static bool ___removeIp(const std::string &_dev,const InetAddress &ip)
-{
- const char *ipcmd = UNIX_COMMANDS[ZT_UNIX_IP_COMMAND];
- if (!ipcmd)
- return false;
- long cpid = (long)vfork();
- if (cpid == 0) {
- execl(ipcmd,ipcmd,"addr","del",ip.toString().c_str(),"dev",_dev.c_str(),(const char *)0);
- _exit(-1);
- } else {
- int exitcode = -1;
- waitpid(cpid,&exitcode,0);
- return (exitcode == 0);
- }
-}
-
-bool LinuxEthernetTap::addIP(const InetAddress &ip)
-{
- const char *ipcmd = UNIX_COMMANDS[ZT_UNIX_IP_COMMAND];
- if (!ipcmd) {
- LOG("ERROR: could not configure IP address for %s: unable to find 'ip' command on system (checked /sbin, /bin, /usr/sbin, /usr/bin)",_dev.c_str());
- return false;
- }
-
- if (!ip)
- return false;
-
- std::set<InetAddress> allIps(ips());
- if (allIps.count(ip) > 0)
- 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) {
- if (i->ipsEqual(ip)) {
- if (___removeIp(_dev,*i)) {
- break;
- } else {
- LOG("WARNING: failed to remove old IP/netmask %s to replace with %s",i->toString().c_str(),ip.toString().c_str());
- }
- }
- }
-
- long cpid;
- if ((cpid = (long)vfork()) == 0) {
- execl(ipcmd,ipcmd,"addr","add",ip.toString().c_str(),"dev",_dev.c_str(),(const char *)0);
- _exit(-1);
- } else if (cpid > 0) {
- int exitcode = -1;
- waitpid(cpid,&exitcode,0);
- return (exitcode == 0);
- }
-
- return false;
-}
-
-bool LinuxEthernetTap::removeIP(const InetAddress &ip)
-{
- if (ips().count(ip) > 0) {
- if (___removeIp(_dev,ip))
- return true;
- }
- return false;
-}
-
-std::set<InetAddress> LinuxEthernetTap::ips() const
-{
- struct ifaddrs *ifa = (struct ifaddrs *)0;
- if (getifaddrs(&ifa))
- return std::set<InetAddress>();
-
- std::set<InetAddress> r;
-
- struct ifaddrs *p = ifa;
- while (p) {
- if ((!strcmp(p->ifa_name,_dev.c_str()))&&(p->ifa_addr)&&(p->ifa_netmask)&&(p->ifa_addr->sa_family == p->ifa_netmask->sa_family)) {
- switch(p->ifa_addr->sa_family) {
- 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)));
- } 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])));
- } break;
- }
- }
- p = p->ifa_next;
- }
-
- if (ifa)
- freeifaddrs(ifa);
-
- return r;
-}
-
-void LinuxEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
-{
- 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;
- ::write(_fd,putBuf,len);
- }
-}
-
-std::string LinuxEthernetTap::deviceName() const
-{
- return _dev;
-}
-
-std::string LinuxEthernetTap::persistentId() const
-{
- return std::string();
-}
-
-bool LinuxEthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups)
-{
- char *ptr,*ptr2;
- unsigned char mac[6];
- std::set<MulticastGroup> newGroups;
-
- int fd = ::open("/proc/net/dev_mcast",O_RDONLY);
- if (fd > 0) {
- char buf[131072];
- int n = (int)::read(fd,buf,sizeof(buf));
- if ((n > 0)&&(n < (int)sizeof(buf))) {
- buf[n] = (char)0;
- for(char *l=strtok_r(buf,"\r\n",&ptr);(l);l=strtok_r((char *)0,"\r\n",&ptr)) {
- int fno = 0;
- char *devname = (char *)0;
- char *mcastmac = (char *)0;
- for(char *f=strtok_r(l," \t",&ptr2);(f);f=strtok_r((char *)0," \t",&ptr2)) {
- if (fno == 1)
- devname = f;
- else if (fno == 4)
- mcastmac = f;
- ++fno;
- }
- if ((devname)&&(!strcmp(devname,_dev.c_str()))&&(mcastmac)&&(Utils::unhex(mcastmac,mac,6) == 6))
- newGroups.insert(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));
- }
-
- bool changed = false;
-
- for(std::set<MulticastGroup>::iterator mg(newGroups.begin());mg!=newGroups.end();++mg) {
- if (!groups.count(*mg)) {
- groups.insert(*mg);
- changed = true;
- }
- }
- for(std::set<MulticastGroup>::iterator mg(groups.begin());mg!=groups.end();) {
- if ((!newGroups.count(*mg))&&(*mg != _blindWildcardMulticastGroup)) {
- groups.erase(mg++);
- changed = true;
- } else ++mg;
- }
-
- return changed;
-}
-
-void LinuxEthernetTap::threadMain()
- throw()
-{
- fd_set readfds,nullfds;
- 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);
- FD_ZERO(&nullfds);
- nfds = (int)std::max(_shutdownSignalPipe[0],_fd) + 1;
-
- r = 0;
- for(;;) {
- FD_SET(_shutdownSignalPipe[0],&readfds);
- FD_SET(_fd,&readfds);
- select(nfds,&readfds,&nullfds,&nullfds,(struct timeval *)0);
-
- if (FD_ISSET(_shutdownSignalPipe[0],&readfds)) // writes to shutdown pipe terminate thread
- break;
-
- 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));
- break;
- }
- } else {
- // Some tap drivers like to send the ethernet frame and the
- // payload in two chunks, so handle that by accumulating
- // data until we have at least a frame.
- r += n;
- if (r > 14) {
- if (r > ((int)_mtu + 14)) // sanity check for weird TAP behavior on some platforms
- r = _mtu + 14;
-
- 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;
- }
- }
- }
- }
-}
-
-} // namespace ZeroTier
diff --git a/node/osdep/LinuxEthernetTap.hpp b/node/osdep/LinuxEthernetTap.hpp
deleted file mode 100644
index e6aea2ec..00000000
--- a/node/osdep/LinuxEthernetTap.hpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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_LINUXETHERNETTAP_HPP
-#define ZT_LINUXETHERNETTAP_HPP
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <stdexcept>
-
-#include "../EthernetTap.hpp"
-#include "../Mutex.hpp"
-#include "../Thread.hpp"
-
-namespace ZeroTier {
-
-/**
- * Linux Ethernet tap using kernel tun/tap driver
- */
-class LinuxEthernetTap : public EthernetTap
-{
-public:
- LinuxEthernetTap(
- 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 ~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 std::string persistentId() const;
- virtual bool updateMulticastGroups(std::set<MulticastGroup> &groups);
-
- void threadMain()
- throw();
-
-private:
- void (*_handler)(void *,const MAC &,const MAC &,unsigned int,const Buffer<4096> &);
- void *_arg;
- Thread _thread;
- std::string _dev;
- int _fd;
- int _shutdownSignalPipe[2];
- volatile bool _enabled;
-};
-
-} // namespace ZeroTier
-
-#endif
diff --git a/node/osdep/LinuxEthernetTapFactory.cpp b/node/osdep/LinuxEthernetTapFactory.cpp
deleted file mode 100644
index fccb6bd5..00000000
--- a/node/osdep/LinuxEthernetTapFactory.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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
deleted file mode 100644
index a5d13216..00000000
--- a/node/osdep/LinuxEthernetTapFactory.hpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 67a5b22d..00000000
--- a/node/osdep/LinuxRoutingTable.cpp
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * 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 <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <ifaddrs.h>
-
-#include <algorithm>
-#include <utility>
-
-#include "../Constants.hpp"
-#include "../Utils.hpp"
-#include "LinuxRoutingTable.hpp"
-
-#define ZT_LINUX_IP_COMMAND "/sbin/ip"
-
-namespace ZeroTier {
-
-LinuxRoutingTable::LinuxRoutingTable()
-{
-}
-
-LinuxRoutingTable::~LinuxRoutingTable()
-{
-}
-
-std::vector<RoutingTable::Entry> LinuxRoutingTable::get(bool includeLinkLocal,bool includeLoopback) const
-{
- char buf[131072];
- char *stmp,*stmp2;
- std::vector<RoutingTable::Entry> entries;
-
- {
- int fd = ::open("/proc/net/route",O_RDONLY);
- if (fd <= 0)
- buf[0] = (char)0;
- else {
- int n = (int)::read(fd,buf,sizeof(buf) - 1);
- ::close(fd);
- if (n < 0) n = 0;
- buf[n] = (char)0;
- }
- }
-
- int lineno = 0;
- for(char *line=Utils::stok(buf,"\r\n",&stmp);(line);line=Utils::stok((char *)0,"\r\n",&stmp)) {
- if (lineno == 0) {
- ++lineno;
- continue; // skip header
- }
-
- char *iface = (char *)0;
- uint32_t destination = 0;
- uint32_t gateway = 0;
- int metric = 0;
- uint32_t mask = 0;
-
- int fno = 0;
- for(char *f=Utils::stok(line,"\t \r\n",&stmp2);(f);f=Utils::stok((char *)0,"\t \r\n",&stmp2)) {
- switch(fno) {
- case 0: iface = f; break;
- case 1: destination = (uint32_t)Utils::hexStrToULong(f); break;
- case 2: gateway = (uint32_t)Utils::hexStrToULong(f); break;
- case 6: metric = (int)Utils::strToInt(f); break;
- case 7: mask = (uint32_t)Utils::hexStrToULong(f); break;
- }
- ++fno;
- }
-
- if ((iface)&&(destination)) {
- RoutingTable::Entry e;
- if (destination)
- e.destination.set(&destination,4,Utils::countBits(mask));
- e.gateway.set(&gateway,4,0);
- e.deviceIndex = 0; // not used on Linux
- e.metric = metric;
- Utils::scopy(e.device,sizeof(e.device),iface);
- if ((e.destination)&&((includeLinkLocal)||(!e.destination.isLinkLocal()))&&((includeLoopback)||((!e.destination.isLoopback())&&(!e.gateway.isLoopback())&&(strcmp(iface,"lo")))))
- entries.push_back(e);
- }
-
- ++lineno;
- }
-
- {
- int fd = ::open("/proc/net/ipv6_route",O_RDONLY);
- if (fd <= 0)
- buf[0] = (char)0;
- else {
- int n = (int)::read(fd,buf,sizeof(buf) - 1);
- ::close(fd);
- if (n < 0) n = 0;
- buf[n] = (char)0;
- }
- }
-
- for(char *line=Utils::stok(buf,"\r\n",&stmp);(line);line=Utils::stok((char *)0,"\r\n",&stmp)) {
- char *destination = (char *)0;
- unsigned int destPrefixLen = 0;
- char *gateway = (char *)0; // next hop in ipv6 terminology
- int metric = 0;
- char *device = (char *)0;
-
- int fno = 0;
- for(char *f=Utils::stok(line,"\t \r\n",&stmp2);(f);f=Utils::stok((char *)0,"\t \r\n",&stmp2)) {
- switch(fno) {
- case 0: destination = f; break;
- case 1: destPrefixLen = (unsigned int)Utils::hexStrToULong(f); break;
- case 4: gateway = f; break;
- case 5: metric = (int)Utils::hexStrToLong(f); break;
- case 9: device = f; break;
- }
- ++fno;
- }
-
- if ((device)&&(destination)) {
- unsigned char tmp[16];
- RoutingTable::Entry e;
- Utils::unhex(destination,tmp,16);
- if ((!Utils::isZero(tmp,16))&&(tmp[0] != 0xff))
- e.destination.set(tmp,16,destPrefixLen);
- Utils::unhex(gateway,tmp,16);
- e.gateway.set(tmp,16,0);
- e.deviceIndex = 0; // not used on Linux
- e.metric = metric;
- Utils::scopy(e.device,sizeof(e.device),device);
- if ((e.destination)&&((includeLinkLocal)||(!e.destination.isLinkLocal()))&&((includeLoopback)||((!e.destination.isLoopback())&&(!e.gateway.isLoopback())&&(strcmp(device,"lo")))))
- entries.push_back(e);
- }
- }
-
- std::sort(entries.begin(),entries.end());
- return entries;
-}
-
-RoutingTable::Entry LinuxRoutingTable::set(const InetAddress &destination,const InetAddress &gateway,const char *device,int metric)
-{
- if ((!gateway)&&((!device)||(!device[0])))
- return RoutingTable::Entry();
-
- std::vector<RoutingTable::Entry> rtab(get(true,true));
-
- for(std::vector<RoutingTable::Entry>::iterator e(rtab.begin());e!=rtab.end();++e) {
- if (e->destination == destination) {
- if (((!device)||(!device[0]))||(!strcmp(device,e->device))) {
- }
- }
- }
-
- if (metric < 0)
- return RoutingTable::Entry();
-
-
-
- rtab = get(true,true);
- std::vector<RoutingTable::Entry>::iterator bestEntry(rtab.end());
- for(std::vector<RoutingTable::Entry>::iterator e(rtab.begin());e!=rtab.end();++e) {
- if ((e->destination == destination)&&(e->gateway.ipsEqual(gateway))) {
- if ((device)&&(device[0])) {
- if (!strcmp(device,e->device)) {
- if (metric == e->metric)
- bestEntry = e;
- }
- }
- if (bestEntry == rtab.end())
- bestEntry = e;
- }
- }
- if (bestEntry != rtab.end())
- return *bestEntry;
-
- return RoutingTable::Entry();
-}
-
-} // namespace ZeroTier
-
-// Enable and build to test routing table interface
-//#if 0
-using namespace ZeroTier;
-int main(int argc,char **argv)
-{
- LinuxRoutingTable rt;
-
- printf("<destination> <gateway> <interface> <metric>\n");
- std::vector<RoutingTable::Entry> ents(rt.get());
- for(std::vector<RoutingTable::Entry>::iterator e(ents.begin());e!=ents.end();++e)
- printf("%s\n",e->toString().c_str());
- printf("\n");
-
- printf("adding 1.1.1.0 and 2.2.2.0...\n");
- rt.set(InetAddress("1.1.1.0",24),InetAddress("1.2.3.4",0),(const char *)0,1);
- rt.set(InetAddress("2.2.2.0",24),InetAddress(),"en0",1);
- printf("\n");
-
- printf("<destination> <gateway> <interface> <metric>\n");
- ents = rt.get();
- for(std::vector<RoutingTable::Entry>::iterator e(ents.begin());e!=ents.end();++e)
- printf("%s\n",e->toString().c_str());
- printf("\n");
-
- printf("deleting 1.1.1.0 and 2.2.2.0...\n");
- rt.set(InetAddress("1.1.1.0",24),InetAddress("1.2.3.4",0),(const char *)0,-1);
- rt.set(InetAddress("2.2.2.0",24),InetAddress(),"en0",-1);
- printf("\n");
-
- printf("<destination> <gateway> <interface> <metric>\n");
- ents = rt.get();
- for(std::vector<RoutingTable::Entry>::iterator e(ents.begin());e!=ents.end();++e)
- printf("%s\n",e->toString().c_str());
- printf("\n");
-
- return 0;
-}
-//#endif
diff --git a/node/osdep/LinuxRoutingTable.hpp b/node/osdep/LinuxRoutingTable.hpp
deleted file mode 100644
index 9a5d3fd6..00000000
--- a/node/osdep/LinuxRoutingTable.hpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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_LINUXROUTINGTABLE_HPP
-#define ZT_LINUXROUTINGTABLE_HPP
-
-#include "../RoutingTable.hpp"
-
-namespace ZeroTier {
-
-/**
- * Routing table interface via /proc/net/route, /proc/net/ipv6_route, and /sbin/route command
- */
-class LinuxRoutingTable : public RoutingTable
-{
-public:
- LinuxRoutingTable();
- virtual ~LinuxRoutingTable();
- virtual std::vector<RoutingTable::Entry> get(bool includeLinkLocal = false,bool includeLoopback = false) const;
- virtual RoutingTable::Entry set(const InetAddress &destination,const InetAddress &gateway,const char *device,int metric);
-};
-
-} // namespace ZeroTier
-
-#endif
diff --git a/node/osdep/OSXEthernetTap.cpp b/node/osdep/OSXEthernetTap.cpp
deleted file mode 100644
index 1e2ddbed..00000000
--- a/node/osdep/OSXEthernetTap.cpp
+++ /dev/null
@@ -1,634 +0,0 @@
-/*
- * 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 <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include <unistd.h>
-#include <signal.h>
-
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/wait.h>
-#include <sys/select.h>
-#include <sys/cdefs.h>
-#include <sys/uio.h>
-#include <sys/param.h>
-#include <sys/sysctl.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <net/route.h>
-#include <net/if.h>
-#include <net/if_arp.h>
-#include <net/if_dl.h>
-#include <net/if_media.h>
-#include <netinet6/in6_var.h>
-#include <netinet/in_var.h>
-#include <netinet/icmp6.h>
-#include <netinet6/nd6.h>
-#include <ifaddrs.h>
-
-// OSX compile fix... in6_var defines this in a struct which namespaces it for C++
-struct prf_ra {
- u_char onlink : 1;
- u_char autonomous : 1;
- u_char reserved : 6;
-} prf_ra;
-
-// These are KERNEL_PRIVATE... why?
-#ifndef SIOCAUTOCONF_START
-#define SIOCAUTOCONF_START _IOWR('i', 132, struct in6_ifreq) /* accept rtadvd on this interface */
-#endif
-#ifndef SIOCAUTOCONF_STOP
-#define SIOCAUTOCONF_STOP _IOWR('i', 133, struct in6_ifreq) /* stop accepting rtadv for this interface */
-#endif
-
-// --------------------------------------------------------------------------
-// --------------------------------------------------------------------------
-// This source is from:
-// http://www.opensource.apple.com/source/Libinfo/Libinfo-406.17/gen.subproj/getifmaddrs.c?txt
-// It's here because OSX 10.6 does not have this convenience function.
-
-#define SALIGN (sizeof(uint32_t) - 1)
-#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : \
-(SALIGN + 1))
-#define MAX_SYSCTL_TRY 5
-#define RTA_MASKS (RTA_GATEWAY | RTA_IFP | RTA_IFA)
-
-/* FreeBSD uses NET_RT_IFMALIST and RTM_NEWMADDR from <sys/socket.h> */
-/* We can use NET_RT_IFLIST2 and RTM_NEWMADDR2 on Darwin */
-//#define DARWIN_COMPAT
-
-//#ifdef DARWIN_COMPAT
-#define GIM_SYSCTL_MIB NET_RT_IFLIST2
-#define GIM_RTM_ADDR RTM_NEWMADDR2
-//#else
-//#define GIM_SYSCTL_MIB NET_RT_IFMALIST
-//#define GIM_RTM_ADDR RTM_NEWMADDR
-//#endif
-
-// Not in 10.6 includes so use our own
-struct _intl_ifmaddrs {
- struct _intl_ifmaddrs *ifma_next;
- struct sockaddr *ifma_name;
- struct sockaddr *ifma_addr;
- struct sockaddr *ifma_lladdr;
-};
-
-static inline int _intl_getifmaddrs(struct _intl_ifmaddrs **pif)
-{
- int icnt = 1;
- int dcnt = 0;
- int ntry = 0;
- size_t len;
- size_t needed;
- int mib[6];
- int i;
- char *buf;
- char *data;
- char *next;
- char *p;
- struct ifma_msghdr2 *ifmam;
- struct _intl_ifmaddrs *ifa, *ift;
- struct rt_msghdr *rtm;
- struct sockaddr *sa;
-
- mib[0] = CTL_NET;
- mib[1] = PF_ROUTE;
- mib[2] = 0; /* protocol */
- mib[3] = 0; /* wildcard address family */
- mib[4] = GIM_SYSCTL_MIB;
- mib[5] = 0; /* no flags */
- do {
- if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
- return (-1);
- if ((buf = (char *)malloc(needed)) == NULL)
- return (-1);
- if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
- if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
- free(buf);
- return (-1);
- }
- free(buf);
- buf = NULL;
- }
- } while (buf == NULL);
-
- for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
- rtm = (struct rt_msghdr *)(void *)next;
- if (rtm->rtm_version != RTM_VERSION)
- continue;
- switch (rtm->rtm_type) {
- case GIM_RTM_ADDR:
- ifmam = (struct ifma_msghdr2 *)(void *)rtm;
- if ((ifmam->ifmam_addrs & RTA_IFA) == 0)
- break;
- icnt++;
- p = (char *)(ifmam + 1);
- for (i = 0; i < RTAX_MAX; i++) {
- if ((RTA_MASKS & ifmam->ifmam_addrs &
- (1 << i)) == 0)
- continue;
- sa = (struct sockaddr *)(void *)p;
- len = SA_RLEN(sa);
- dcnt += len;
- p += len;
- }
- break;
- }
- }
-
- data = (char *)malloc(sizeof(struct _intl_ifmaddrs) * icnt + dcnt);
- if (data == NULL) {
- free(buf);
- return (-1);
- }
-
- ifa = (struct _intl_ifmaddrs *)(void *)data;
- data += sizeof(struct _intl_ifmaddrs) * icnt;
-
- memset(ifa, 0, sizeof(struct _intl_ifmaddrs) * icnt);
- ift = ifa;
-
- for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
- rtm = (struct rt_msghdr *)(void *)next;
- if (rtm->rtm_version != RTM_VERSION)
- continue;
-
- switch (rtm->rtm_type) {
- case GIM_RTM_ADDR:
- ifmam = (struct ifma_msghdr2 *)(void *)rtm;
- if ((ifmam->ifmam_addrs & RTA_IFA) == 0)
- break;
-
- p = (char *)(ifmam + 1);
- for (i = 0; i < RTAX_MAX; i++) {
- if ((RTA_MASKS & ifmam->ifmam_addrs &
- (1 << i)) == 0)
- continue;
- sa = (struct sockaddr *)(void *)p;
- len = SA_RLEN(sa);
- switch (i) {
- case RTAX_GATEWAY:
- ift->ifma_lladdr =
- (struct sockaddr *)(void *)data;
- memcpy(data, p, len);
- data += len;
- break;
-
- case RTAX_IFP:
- ift->ifma_name =
- (struct sockaddr *)(void *)data;
- memcpy(data, p, len);
- data += len;
- break;
-
- case RTAX_IFA:
- ift->ifma_addr =
- (struct sockaddr *)(void *)data;
- memcpy(data, p, len);
- data += len;
- break;
-
- default:
- data += len;
- break;
- }
- p += len;
- }
- ift->ifma_next = ift + 1;
- ift = ift->ifma_next;
- break;
- }
- }
-
- free(buf);
-
- if (ift > ifa) {
- ift--;
- ift->ifma_next = NULL;
- *pif = ifa;
- } else {
- *pif = NULL;
- free(ifa);
- }
- return (0);
-}
-
-static inline void _intl_freeifmaddrs(struct _intl_ifmaddrs *ifmp)
-{
- free(ifmp);
-}
-
-// --------------------------------------------------------------------------
-// --------------------------------------------------------------------------
-
-#include <string>
-#include <map>
-#include <set>
-#include <algorithm>
-
-#include "../Constants.hpp"
-#include "../Utils.hpp"
-#include "../Mutex.hpp"
-#include "OSXEthernetTap.hpp"
-
-// ff:ff:ff:ff:ff:ff with no ADI
-static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff),0);
-
-static inline bool _setIpv6Stuff(const char *ifname,bool performNUD,bool acceptRouterAdverts)
-{
- struct in6_ndireq nd;
- struct in6_ifreq ifr;
-
- int s = socket(AF_INET6,SOCK_DGRAM,0);
- if (s <= 0)
- return false;
-
- memset(&nd,0,sizeof(nd));
- strncpy(nd.ifname,ifname,sizeof(nd.ifname));
-
- if (ioctl(s,SIOCGIFINFO_IN6,&nd)) {
- close(s);
- return false;
- }
-
- unsigned long oldFlags = (unsigned long)nd.ndi.flags;
-
- if (performNUD)
- nd.ndi.flags |= ND6_IFF_PERFORMNUD;
- else nd.ndi.flags &= ~ND6_IFF_PERFORMNUD;
-
- if (oldFlags != (unsigned long)nd.ndi.flags) {
- if (ioctl(s,SIOCSIFINFO_FLAGS,&nd)) {
- close(s);
- return false;
- }
- }
-
- memset(&ifr,0,sizeof(ifr));
- strncpy(ifr.ifr_name,ifname,sizeof(ifr.ifr_name));
- if (ioctl(s,acceptRouterAdverts ? SIOCAUTOCONF_START : SIOCAUTOCONF_STOP,&ifr)) {
- close(s);
- return false;
- }
-
- close(s);
- return true;
-}
-
-namespace ZeroTier {
-
-// Only permit one tap to be opened concurrently across the entire process
-static Mutex __tapCreateLock;
-
-OSXEthernetTap::OSXEthernetTap(
- const RuntimeEnvironment *renv,
- const char *tryToGetDevice,
- const MAC &mac,
- unsigned int mtu,
- void (*handler)(void *,const MAC &,const MAC &,unsigned int,const Buffer<4096> &),
- void *arg)
- throw(std::runtime_error) :
- EthernetTap("OSXEthernetTap",mac,mtu,metric),
- _r(renv),
- _handler(handler),
- _arg(arg),
- _fd(0),
- _enabled(true)
-{
- 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");
- if (stat("/dev/zt0",&stattmp))
- throw std::runtime_error("/dev/zt# tap devices do not exist and unable to load kernel extension");
-
- // Try to reopen the last device we had, if we had one and it's still unused.
- bool recalledDevice = false;
- if ((tryToGetDevice)&&(tryToGetDevice[0])) {
- Utils::snprintf(devpath,sizeof(devpath),"/dev/%s",tryToGetDevice);
- if (stat(devpath,&stattmp) == 0) {
- _fd = ::open(devpath,O_RDWR);
- if (_fd > 0) {
- _dev = tryToGetDevice;
- recalledDevice = true;
- }
- }
- }
-
- // Open the first unused tap device if we didn't recall a previous one.
- if (!recalledDevice) {
- for(int i=0;i<256;++i) {
- Utils::snprintf(devpath,sizeof(devpath),"/dev/zt%d",i);
- if (stat(devpath,&stattmp))
- throw std::runtime_error("no more TAP devices available");
- _fd = ::open(devpath,O_RDWR);
- if (_fd > 0) {
- char foo[16];
- Utils::snprintf(foo,sizeof(foo),"zt%d",i);
- _dev = foo;
- break;
- }
- }
- }
-
- if (_fd <= 0)
- throw std::runtime_error("unable to open TAP device or no more devices available");
-
- if (fcntl(_fd,F_SETFL,fcntl(_fd,F_GETFL) & ~O_NONBLOCK) == -1) {
- ::close(_fd);
- throw std::runtime_error("unable to set flags on file descriptor for TAP device");
- }
-
- // 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);
- 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);
- if (exitcode) {
- ::close(_fd);
- throw std::runtime_error("ifconfig failure setting link-layer address and activating tap interface");
- }
- }
-
- _setIpv6Stuff(_dev.c_str(),true,false);
-
- // Set close-on-exec so that devices cannot persist if we fork/exec for update
- fcntl(_fd,F_SETFD,fcntl(_fd,F_GETFD) | FD_CLOEXEC);
-
- ::pipe(_shutdownSignalPipe);
-
- _thread = Thread::start(this);
-}
-
-OSXEthernetTap::~OSXEthernetTap()
-{
- ::write(_shutdownSignalPipe[1],"\0",1); // causes thread to exit
- Thread::join(_thread);
- ::close(_fd);
- ::close(_shutdownSignalPipe[0]);
- ::close(_shutdownSignalPipe[1]);
-}
-
-void OSXEthernetTap::setEnabled(bool en)
-{
- _enabled = en;
- // TODO: interface status change
-}
-
-bool OSXEthernetTap::enabled() const
-{
- return _enabled;
-}
-
-static bool ___removeIp(const std::string &_dev,const InetAddress &ip)
-{
- 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 (cpid > 0) {
- int exitcode = -1;
- waitpid(cpid,&exitcode,0);
- return (exitcode == 0);
- }
- return false; // never reached, make compiler shut up about return value
-}
-
-bool OSXEthernetTap::addIP(const InetAddress &ip)
-{
- if (!ip)
- return false;
-
- std::set<InetAddress> allIps(ips());
- if (allIps.count(ip) > 0)
- return true; // IP/netmask already assigned
-
- // Remove and reconfigure if address is the same but netmask is different
- for(std::set<InetAddress>::iterator i(allIps.begin());i!=allIps.end();++i) {
- if ((i->ipsEqual(ip))&&(i->netmaskBits() != ip.netmaskBits())) {
- if (___removeIp(_dev,*i)) {
- break;
- } else {
- LOG("WARNING: failed to remove old IP/netmask %s to replace with %s",i->toString().c_str(),ip.toString().c_str());
- }
- }
- }
-
- 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);
- return (exitcode == 0);
- }
- return false;
-}
-
-bool OSXEthernetTap::removeIP(const InetAddress &ip)
-{
- if (ips().count(ip) > 0) {
- if (___removeIp(_dev,ip))
- return true;
- }
- return false;
-}
-
-std::set<InetAddress> OSXEthernetTap::ips() const
-{
- struct ifaddrs *ifa = (struct ifaddrs *)0;
- if (getifaddrs(&ifa))
- return std::set<InetAddress>();
-
- std::set<InetAddress> r;
-
- struct ifaddrs *p = ifa;
- while (p) {
- if ((!strcmp(p->ifa_name,_dev.c_str()))&&(p->ifa_addr)&&(p->ifa_netmask)&&(p->ifa_addr->sa_family == p->ifa_netmask->sa_family)) {
- switch(p->ifa_addr->sa_family) {
- 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)));
- } 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])));
- } break;
- }
- }
- p = p->ifa_next;
- }
-
- if (ifa)
- freeifaddrs(ifa);
-
- return r;
-}
-
-void OSXEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
-{
- 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;
- ::write(_fd,putBuf,len);
- }
-}
-
-std::string OSXEthernetTap::deviceName() const
-{
- return _dev;
-}
-
-std::string OSXEthernetTap::persistentId() const
-{
- return std::string();
-}
-
-bool OSXEthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups)
-{
- std::set<MulticastGroup> newGroups;
- struct _intl_ifmaddrs *ifmap = (struct _intl_ifmaddrs *)0;
- if (!_intl_getifmaddrs(&ifmap)) {
- struct _intl_ifmaddrs *p = ifmap;
- while (p) {
- if (p->ifma_addr->sa_family == AF_LINK) {
- struct sockaddr_dl *in = (struct sockaddr_dl *)p->ifma_name;
- struct sockaddr_dl *la = (struct sockaddr_dl *)p->ifma_addr;
- if ((la->sdl_alen == 6)&&(in->sdl_nlen <= _dev.length())&&(!memcmp(_dev.data(),in->sdl_data,in->sdl_nlen)))
- newGroups.insert(MulticastGroup(MAC(la->sdl_data + la->sdl_nlen,6),0));
- }
- p = p->ifma_next;
- }
- _intl_freeifmaddrs(ifmap);
- }
-
- {
- std::set<InetAddress> allIps(ips());
- for(std::set<InetAddress>::const_iterator i(allIps.begin());i!=allIps.end();++i)
- newGroups.insert(MulticastGroup::deriveMulticastGroupForAddressResolution(*i));
- }
-
- bool changed = false;
-
- for(std::set<MulticastGroup>::iterator mg(newGroups.begin());mg!=newGroups.end();++mg) {
- if (!groups.count(*mg)) {
- groups.insert(*mg);
- changed = true;
- }
- }
- for(std::set<MulticastGroup>::iterator mg(groups.begin());mg!=groups.end();) {
- if ((!newGroups.count(*mg))&&(*mg != _blindWildcardMulticastGroup)) {
- groups.erase(mg++);
- changed = true;
- } else ++mg;
- }
-
- return changed;
-}
-
-void OSXEthernetTap::threadMain()
- throw()
-{
- fd_set readfds,nullfds;
- 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);
- FD_ZERO(&nullfds);
- nfds = (int)std::max(_shutdownSignalPipe[0],_fd) + 1;
-
- r = 0;
- for(;;) {
- FD_SET(_shutdownSignalPipe[0],&readfds);
- FD_SET(_fd,&readfds);
- select(nfds,&readfds,&nullfds,&nullfds,(struct timeval *)0);
-
- if (FD_ISSET(_shutdownSignalPipe[0],&readfds)) // writes to shutdown pipe terminate thread
- break;
-
- if (FD_ISSET(_fd,&readfds)) {
- n = (int)::read(_fd,getBuf + r,sizeof(getBuf) - r);
- if (n < 0) {
- 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
- // data until we have at least a frame.
- r += n;
- if (r > 14) {
- if (r > ((int)_mtu + 14)) // sanity check for weird TAP behavior on some platforms
- r = _mtu + 14;
-
- 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;
- }
- }
- }
- }
-}
-
-} // namespace ZeroTier
diff --git a/node/osdep/OSXEthernetTap.hpp b/node/osdep/OSXEthernetTap.hpp
deleted file mode 100644
index 7ca63730..00000000
--- a/node/osdep/OSXEthernetTap.hpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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_OSXETHERNETTAP_HPP
-#define ZT_OSXETHERNETTAP_HPP
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <stdexcept>
-
-#include "../EthernetTap.hpp"
-#include "../Mutex.hpp"
-#include "../Thread.hpp"
-
-namespace ZeroTier {
-
-/**
- * OSX Ethernet tap using ZeroTier kernel extension zt# devices
- *
- * This also installs a friendly-named network device in the system network
- * configuration, permitting network devices to be seen and configured in
- * the OSX system preferences app.
- */
-class OSXEthernetTap : public EthernetTap
-{
-public:
- OSXEthernetTap(
- 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 ~OSXEthernetTap();
-
- 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 std::string persistentId() const;
- virtual bool updateMulticastGroups(std::set<MulticastGroup> &groups);
-
- void threadMain()
- throw();
-
-private:
- void (*_handler)(void *,const MAC &,const MAC &,unsigned int,const Buffer<4096> &);
- void *_arg;
- Thread _thread;
- std::string _dev;
- int _fd;
- int _shutdownSignalPipe[2];
- volatile bool _enabled;
-};
-
-} // namespace ZeroTier
-
-#endif
diff --git a/node/osdep/OSXEthernetTapFactory.cpp b/node/osdep/OSXEthernetTapFactory.cpp
deleted file mode 100644
index 4d0f2069..00000000
--- a/node/osdep/OSXEthernetTapFactory.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 720e038a..00000000
--- a/node/osdep/OSXEthernetTapFactory.hpp
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 8541ce7c..00000000
--- a/node/osdep/WindowsEthernetTap.cpp
+++ /dev/null
@@ -1,837 +0,0 @@
-/*
- * 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 "../Constants.hpp"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <WinSock2.h>
-#include <Windows.h>
-#include <tchar.h>
-#include <winreg.h>
-#include <wchar.h>
-#include <ws2ipdef.h>
-#include <WS2tcpip.h>
-#include <IPHlpApi.h>
-#include <nldef.h>
-#include <netioapi.h>
-
-#include "../EthernetTap.hpp"
-#include "../Utils.hpp"
-#include "../Mutex.hpp"
-#include "WindowsEthernetTap.hpp"
-
-#include "..\windows\TapDriver\tap-windows.h"
-
-// ff:ff:ff:ff:ff:ff with no ADI
-static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff),0);
-
-namespace ZeroTier {
-
-// Helper function to get an adapter's LUID and index from its GUID. The LUID is
-// constant but the index can change, so go ahead and just look them both up by
-// the GUID which is constant. (The GUID is the instance ID in the registry.)
-static inline std::pair<NET_LUID,NET_IFINDEX> _findAdapterByGuid(const GUID &guid)
- throw(std::runtime_error)
-{
- MIB_IF_TABLE2 *ift = (MIB_IF_TABLE2 *)0;
-
- if (GetIfTable2Ex(MibIfTableRaw,&ift) != NO_ERROR)
- throw std::runtime_error("GetIfTable2Ex() failed");
-
- for(ULONG i=0;i<ift->NumEntries;++i) {
- if (ift->Table[i].InterfaceGuid == guid) {
- std::pair<NET_LUID,NET_IFINDEX> tmp(ift->Table[i].InterfaceLuid,ift->Table[i].InterfaceIndex);
- FreeMibTable(ift);
- return tmp;
- }
- }
-
- FreeMibTable(&ift);
-
- throw std::runtime_error("interface not found");
-}
-
-// Only create or delete devices one at a time
-static Mutex _systemTapInitLock;
-
-// Compute some basic environment stuff on startup
-class _WinSysEnv
-{
-public:
- _WinSysEnv()
- {
-#ifdef _WIN64
- is64Bit = TRUE;
- devcon = "\\devcon_x64.exe";
- tapDriver = "\\tap-windows\\x64\\zttap200.inf";
-#else
- is64Bit = FALSE;
- IsWow64Process(GetCurrentProcess(),&is64Bit);
- devcon = ((is64Bit == TRUE) ? "\\devcon_x64.exe" : "\\devcon_x86.exe");
- tapDriver = ((is64Bit == TRUE) ? "\\tap-windows\\x64\\zttap200.inf" : "\\tap-windows\\x86\\zttap200.inf");
-#endif
- }
- BOOL is64Bit;
- const char *devcon;
- const char *tapDriver;
-};
-static const _WinSysEnv _winEnv;
-
-static bool _disableTapDevice(const RuntimeEnvironment *_r,const std::string deviceInstanceId)
-{
- HANDLE devconLog = CreateFileA((_r->homePath + "\\devcon.log").c_str(),GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
- if (devconLog != INVALID_HANDLE_VALUE)
- SetFilePointer(devconLog,0,0,FILE_END);
-
- STARTUPINFOA startupInfo;
- startupInfo.cb = sizeof(startupInfo);
- if (devconLog != INVALID_HANDLE_VALUE) {
- startupInfo.hStdOutput = devconLog;
- startupInfo.hStdError = devconLog;
- }
- PROCESS_INFORMATION processInfo;
- memset(&startupInfo,0,sizeof(STARTUPINFOA));
- memset(&processInfo,0,sizeof(PROCESS_INFORMATION));
- if (!CreateProcessA(NULL,(LPSTR)(std::string("\"") + _r->homePath + _winEnv.devcon + "\" disable @" + deviceInstanceId).c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) {
- if (devconLog != INVALID_HANDLE_VALUE)
- CloseHandle(devconLog);
- return false;
- }
- WaitForSingleObject(processInfo.hProcess,INFINITE);
- CloseHandle(processInfo.hProcess);
- CloseHandle(processInfo.hThread);
-
- if (devconLog != INVALID_HANDLE_VALUE)
- CloseHandle(devconLog);
-
- return true;
-}
-static bool _enableTapDevice(const RuntimeEnvironment *_r,const std::string deviceInstanceId)
-{
- HANDLE devconLog = CreateFileA((_r->homePath + "\\devcon.log").c_str(),GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
- if (devconLog != INVALID_HANDLE_VALUE)
- SetFilePointer(devconLog,0,0,FILE_END);
-
- STARTUPINFOA startupInfo;
- startupInfo.cb = sizeof(startupInfo);
- if (devconLog != INVALID_HANDLE_VALUE) {
- startupInfo.hStdOutput = devconLog;
- startupInfo.hStdError = devconLog;
- }
- PROCESS_INFORMATION processInfo;
- memset(&startupInfo,0,sizeof(STARTUPINFOA));
- memset(&processInfo,0,sizeof(PROCESS_INFORMATION));
- if (!CreateProcessA(NULL,(LPSTR)(std::string("\"") + _r->homePath + _winEnv.devcon + "\" enable @" + deviceInstanceId).c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) {
- if (devconLog != INVALID_HANDLE_VALUE)
- CloseHandle(devconLog);
- return false;
- }
- WaitForSingleObject(processInfo.hProcess,INFINITE);
- CloseHandle(processInfo.hProcess);
- CloseHandle(processInfo.hThread);
-
- if (devconLog != INVALID_HANDLE_VALUE)
- CloseHandle(devconLog);
-
- return true;
-}
-
-static void _syncIpsWithRegistry(const std::set<InetAddress> &haveIps,const std::string netCfgInstanceId)
-{
- // Update registry to contain all non-link-local IPs for this interface
- std::string regMultiIps,regMultiNetmasks;
- for(std::set<InetAddress>::const_iterator i(haveIps.begin());i!=haveIps.end();++i) {
- if (!i->isLinkLocal()) {
- regMultiIps.append(i->toIpString());
- regMultiIps.push_back((char)0);
- regMultiNetmasks.append(i->netmask().toIpString());
- regMultiNetmasks.push_back((char)0);
- }
- }
- HKEY tcpIpInterfaces;
- if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces",0,KEY_READ|KEY_WRITE,&tcpIpInterfaces) == ERROR_SUCCESS) {
- if (regMultiIps.length()) {
- regMultiIps.push_back((char)0);
- regMultiNetmasks.push_back((char)0);
- RegSetKeyValueA(tcpIpInterfaces,netCfgInstanceId.c_str(),"IPAddress",REG_MULTI_SZ,regMultiIps.data(),(DWORD)regMultiIps.length());
- RegSetKeyValueA(tcpIpInterfaces,netCfgInstanceId.c_str(),"SubnetMask",REG_MULTI_SZ,regMultiNetmasks.data(),(DWORD)regMultiNetmasks.length());
- } else {
- RegDeleteKeyValueA(tcpIpInterfaces,netCfgInstanceId.c_str(),"IPAddress");
- RegDeleteKeyValueA(tcpIpInterfaces,netCfgInstanceId.c_str(),"SubnetMask");
- }
- }
- RegCloseKey(tcpIpInterfaces);
-}
-
-WindowsEthernetTap::WindowsEthernetTap(
- const RuntimeEnvironment *renv,
- const char *tag,
- const MAC &mac,
- unsigned int mtu,
- void (*handler)(void *,const MAC &,const MAC &,unsigned int,const Buffer<4096> &),
- void *arg)
- throw(std::runtime_error) :
- EthernetTap("WindowsEthernetTap",mac,mtu),
- _r(renv),
- _handler(handler),
- _arg(arg),
- _tap(INVALID_HANDLE_VALUE),
- _injectSemaphore(INVALID_HANDLE_VALUE),
- _run(true),
- _initialized(false),
- _enabled(true)
-{
- char subkeyName[4096];
- char subkeyClass[4096];
- char data[4096];
-
- if (mtu > ZT_IF_MTU)
- throw std::runtime_error("MTU too large for Windows tap");
-
- Mutex::Lock _l(_systemTapInitLock);
-
- HKEY nwAdapters;
- if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",0,KEY_READ|KEY_WRITE,&nwAdapters) != ERROR_SUCCESS)
- throw std::runtime_error("unable to open registry key for network adapter enumeration");
-
- std::set<std::string> existingDeviceInstances;
- std::string mySubkeyName;
-
- // Look for the tap instance that corresponds with our interface tag (network ID)
- for(DWORD subkeyIndex=0;;++subkeyIndex) {
- DWORD type;
- DWORD dataLen;
- DWORD subkeyNameLen = sizeof(subkeyName);
- DWORD subkeyClassLen = sizeof(subkeyClass);
- FILETIME lastWriteTime;
- if (RegEnumKeyExA(nwAdapters,subkeyIndex,subkeyName,&subkeyNameLen,(DWORD *)0,subkeyClass,&subkeyClassLen,&lastWriteTime) == ERROR_SUCCESS) {
- type = 0;
- dataLen = sizeof(data);
- if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
- data[dataLen] = '\0';
- if (!strnicmp(data,"zttap",5)) {
- std::string instanceId;
- type = 0;
- dataLen = sizeof(data);
- if (RegGetValueA(nwAdapters,subkeyName,"NetCfgInstanceId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
- instanceId.assign(data,dataLen);
- existingDeviceInstances.insert(instanceId);
- }
-
- std::string instanceIdPath;
- type = 0;
- dataLen = sizeof(data);
- if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS)
- instanceIdPath.assign(data,dataLen);
-
- if ((_netCfgInstanceId.length() == 0)&&(instanceId.length() != 0)&&(instanceIdPath.length() != 0)) {
- type = 0;
- dataLen = sizeof(data);
- if (RegGetValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
- data[dataLen] = '\0';
- if (!strcmp(data,tag)) {
- _netCfgInstanceId = instanceId;
- _deviceInstanceId = instanceIdPath;
- mySubkeyName = subkeyName;
- break; // found it!
- }
- }
- }
- }
- }
- } else break; // no more subkeys or error occurred enumerating them
- }
-
- // If there is no device, try to create one
- if (_netCfgInstanceId.length() == 0) {
- // Log devcon output to a file
- HANDLE devconLog = CreateFileA((_r->homePath + "\\devcon.log").c_str(),GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
- if (devconLog == INVALID_HANDLE_VALUE) {
- LOG("WARNING: unable to open devcon.log");
- } else {
- SetFilePointer(devconLog,0,0,FILE_END);
- }
-
- // Execute devcon to install an instance of the Microsoft Loopback Adapter
- STARTUPINFOA startupInfo;
- startupInfo.cb = sizeof(startupInfo);
- if (devconLog != INVALID_HANDLE_VALUE) {
- SetFilePointer(devconLog,0,0,FILE_END);
- startupInfo.hStdOutput = devconLog;
- startupInfo.hStdError = devconLog;
- }
- PROCESS_INFORMATION processInfo;
- memset(&startupInfo,0,sizeof(STARTUPINFOA));
- memset(&processInfo,0,sizeof(PROCESS_INFORMATION));
- if (!CreateProcessA(NULL,(LPSTR)(std::string("\"") + _r->homePath + _winEnv.devcon + "\" install \"" + _r->homePath + _winEnv.tapDriver + "\" zttap200").c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) {
- RegCloseKey(nwAdapters);
- if (devconLog != INVALID_HANDLE_VALUE)
- CloseHandle(devconLog);
- throw std::runtime_error(std::string("unable to find or execute devcon at ") + _winEnv.devcon);
- }
- WaitForSingleObject(processInfo.hProcess,INFINITE);
- CloseHandle(processInfo.hProcess);
- CloseHandle(processInfo.hThread);
-
- if (devconLog != INVALID_HANDLE_VALUE)
- CloseHandle(devconLog);
-
- // Scan for the new instance by simply looking for taps that weren't
- // there originally. The static mutex we lock ensures this can't step
- // on its own toes.
- for(DWORD subkeyIndex=0;;++subkeyIndex) {
- DWORD type;
- DWORD dataLen;
- DWORD subkeyNameLen = sizeof(subkeyName);
- DWORD subkeyClassLen = sizeof(subkeyClass);
- FILETIME lastWriteTime;
- if (RegEnumKeyExA(nwAdapters,subkeyIndex,subkeyName,&subkeyNameLen,(DWORD *)0,subkeyClass,&subkeyClassLen,&lastWriteTime) == ERROR_SUCCESS) {
- type = 0;
- dataLen = sizeof(data);
- if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
- data[dataLen] = '\0';
- if (!strnicmp(data,"zttap",5)) {
- type = 0;
- dataLen = sizeof(data);
- if (RegGetValueA(nwAdapters,subkeyName,"NetCfgInstanceId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
- if (existingDeviceInstances.count(std::string(data,dataLen)) == 0) {
- RegSetKeyValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",REG_SZ,tag,(DWORD)(strlen(tag)+1));
- _netCfgInstanceId.assign(data,dataLen);
- type = 0;
- dataLen = sizeof(data);
- if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS)
- _deviceInstanceId.assign(data,dataLen);
- mySubkeyName = subkeyName;
-
- // Disable DHCP by default on newly created devices
- HKEY tcpIpInterfaces;
- if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces",0,KEY_READ|KEY_WRITE,&tcpIpInterfaces) == ERROR_SUCCESS) {
- DWORD enable = 0;
- RegSetKeyValueA(tcpIpInterfaces,_netCfgInstanceId.c_str(),"EnableDHCP",REG_DWORD,&enable,sizeof(enable));
- RegCloseKey(tcpIpInterfaces);
- }
-
- break; // found it!
- }
- }
- }
- }
- } else break; // no more keys or error occurred
- }
- }
-
- if (_netCfgInstanceId.length() > 0) {
- char tmps[4096];
- unsigned int tmpsl = Utils::snprintf(tmps,sizeof(tmps),"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",(unsigned int)mac[0],(unsigned int)mac[1],(unsigned int)mac[2],(unsigned int)mac[3],(unsigned int)mac[4],(unsigned int)mac[5]) + 1;
- RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"NetworkAddress",REG_SZ,tmps,tmpsl);
- RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"MAC",REG_SZ,tmps,tmpsl);
- DWORD tmp = mtu;
- RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"MTU",REG_DWORD,(LPCVOID)&tmp,sizeof(tmp));
- tmp = 0;
- RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"EnableDHCP",REG_DWORD,(LPCVOID)&tmp,sizeof(tmp));
- RegCloseKey(nwAdapters);
- } else {
- RegCloseKey(nwAdapters);
- throw std::runtime_error("unable to find or create tap adapter");
- }
-
- // Convert device GUID junk... blech... is there an easier way to do this?
- {
- char nobraces[128];
- const char *nbtmp1 = _netCfgInstanceId.c_str();
- char *nbtmp2 = nobraces;
- while (*nbtmp1) {
- if ((*nbtmp1 != '{')&&(*nbtmp1 != '}'))
- *nbtmp2++ = *nbtmp1;
- ++nbtmp1;
- }
- *nbtmp2 = (char)0;
- if (UuidFromStringA((RPC_CSTR)nobraces,&_deviceGuid) != RPC_S_OK)
- throw std::runtime_error("unable to convert instance ID GUID to native GUID (invalid NetCfgInstanceId in registry?)");
- }
-
- // Start background thread that actually performs I/O
- _injectSemaphore = CreateSemaphore(NULL,0,1,NULL);
- _thread = Thread::start(this);
-
- // Certain functions can now work (e.g. ips())
- _initialized = true;
-}
-
-WindowsEthernetTap::~WindowsEthernetTap()
-{
- _run = false;
- ReleaseSemaphore(_injectSemaphore,1,NULL);
- Thread::join(_thread);
- CloseHandle(_injectSemaphore);
- _disableTapDevice(_r,_deviceInstanceId);
-}
-
-void WindowsEthernetTap::setEnabled(bool en)
-{
- _enabled = en;
-}
-
-bool WindowsEthernetTap::enabled() const
-{
- return _enabled;
-}
-
-void WindowsEthernetTap::setDisplayName(const char *dn)
-{
- if (!_initialized)
- return;
- HKEY ifp;
- if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,(std::string("SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\") + _netCfgInstanceId).c_str(),0,KEY_READ|KEY_WRITE,&ifp) == ERROR_SUCCESS) {
- RegSetKeyValueA(ifp,"Connection","Name",REG_SZ,(LPCVOID)dn,(DWORD)(strlen(dn)+1));
- RegCloseKey(ifp);
- }
-}
-
-bool WindowsEthernetTap::addIP(const InetAddress &ip)
-{
- if (!_initialized)
- return false;
- if (!ip.netmaskBits()) // sanity check... netmask of 0.0.0.0 is WUT?
- return false;
-
- std::set<InetAddress> haveIps(ips());
-
- try {
- // Add IP to interface at the netlink level if not already assigned.
- if (!haveIps.count(ip)) {
- std::pair<NET_LUID,NET_IFINDEX> ifidx = _findAdapterByGuid(_deviceGuid);
- MIB_UNICASTIPADDRESS_ROW ipr;
-
- InitializeUnicastIpAddressEntry(&ipr);
- if (ip.isV4()) {
- ipr.Address.Ipv4.sin_family = AF_INET;
- ipr.Address.Ipv4.sin_addr.S_un.S_addr = *((const uint32_t *)ip.rawIpData());
- ipr.OnLinkPrefixLength = ip.port();
- if (ipr.OnLinkPrefixLength >= 32)
- return false;
- } else if (ip.isV6()) {
- ipr.Address.Ipv6.sin6_family = AF_INET6;
- memcpy(ipr.Address.Ipv6.sin6_addr.u.Byte,ip.rawIpData(),16);
- ipr.OnLinkPrefixLength = ip.port();
- if (ipr.OnLinkPrefixLength >= 128)
- return false;
- } else return false;
-
- ipr.PrefixOrigin = IpPrefixOriginManual;
- ipr.SuffixOrigin = IpSuffixOriginManual;
- ipr.ValidLifetime = 0xffffffff;
- ipr.PreferredLifetime = 0xffffffff;
-
- ipr.InterfaceLuid = ifidx.first;
- ipr.InterfaceIndex = ifidx.second;
-
- if (CreateUnicastIpAddressEntry(&ipr) == NO_ERROR) {
- haveIps.insert(ip);
- } else {
- LOG("unable to add IP address %s to interface %s: %d",ip.toString().c_str(),deviceName().c_str(),(int)GetLastError());
- return false;
- }
- }
-
- _syncIpsWithRegistry(haveIps,_netCfgInstanceId);
- } catch (std::exception &exc) {
- LOG("unexpected exception adding IP address %s to %s: %s",ip.toString().c_str(),deviceName().c_str(),exc.what());
- return false;
- } catch ( ... ) {
- LOG("unexpected exception adding IP address %s to %s: unknown exception",ip.toString().c_str(),deviceName().c_str());
- return false;
- }
- return true;
-}
-
-bool WindowsEthernetTap::removeIP(const InetAddress &ip)
-{
- if (!_initialized)
- return false;
- try {
- MIB_UNICASTIPADDRESS_TABLE *ipt = (MIB_UNICASTIPADDRESS_TABLE *)0;
- std::pair<NET_LUID,NET_IFINDEX> ifidx = _findAdapterByGuid(_deviceGuid);
- if (GetUnicastIpAddressTable(AF_UNSPEC,&ipt) == NO_ERROR) {
- for(DWORD i=0;i<ipt->NumEntries;++i) {
- if ((ipt->Table[i].InterfaceLuid.Value == ifidx.first.Value)&&(ipt->Table[i].InterfaceIndex == ifidx.second)) {
- InetAddress addr;
- switch(ipt->Table[i].Address.si_family) {
- case AF_INET:
- addr.set(&(ipt->Table[i].Address.Ipv4.sin_addr.S_un.S_addr),4,ipt->Table[i].OnLinkPrefixLength);
- break;
- case AF_INET6:
- addr.set(ipt->Table[i].Address.Ipv6.sin6_addr.u.Byte,16,ipt->Table[i].OnLinkPrefixLength);
- if (addr.isLinkLocal())
- continue; // can't remove link-local IPv6 addresses
- break;
- }
- if (addr == ip) {
- DeleteUnicastIpAddressEntry(&(ipt->Table[i]));
- FreeMibTable(ipt);
- _syncIpsWithRegistry(ips(),_netCfgInstanceId);
- return true;
- }
- }
- }
- FreeMibTable((PVOID)ipt);
- }
- } catch (std::exception &exc) {
- LOG("unexpected exception removing IP address %s from %s: %s",ip.toString().c_str(),deviceName().c_str(),exc.what());
- } catch ( ... ) {
- LOG("unexpected exception removing IP address %s from %s: unknown exception",ip.toString().c_str(),deviceName().c_str());
- }
- return false;
-}
-
-std::set<InetAddress> WindowsEthernetTap::ips() const
-{
- static const InetAddress linkLocalLoopback("fe80::1",64); // what is this and why does Windows assign it?
- std::set<InetAddress> addrs;
-
- if (!_initialized)
- return addrs;
-
- try {
- MIB_UNICASTIPADDRESS_TABLE *ipt = (MIB_UNICASTIPADDRESS_TABLE *)0;
- std::pair<NET_LUID,NET_IFINDEX> ifidx = _findAdapterByGuid(_deviceGuid);
-
- if (GetUnicastIpAddressTable(AF_UNSPEC,&ipt) == NO_ERROR) {
- for(DWORD i=0;i<ipt->NumEntries;++i) {
- if ((ipt->Table[i].InterfaceLuid.Value == ifidx.first.Value)&&(ipt->Table[i].InterfaceIndex == ifidx.second)) {
- switch(ipt->Table[i].Address.si_family) {
- case AF_INET: {
- InetAddress ip(&(ipt->Table[i].Address.Ipv4.sin_addr.S_un.S_addr),4,ipt->Table[i].OnLinkPrefixLength);
- if (ip != InetAddress::LO4)
- addrs.insert(ip);
- } break;
- case AF_INET6: {
- InetAddress ip(ipt->Table[i].Address.Ipv6.sin6_addr.u.Byte,16,ipt->Table[i].OnLinkPrefixLength);
- if ((ip != linkLocalLoopback)&&(ip != InetAddress::LO6))
- addrs.insert(ip);
- } break;
- }
- }
- }
- FreeMibTable(ipt);
- }
- } catch ( ... ) {} // sanity check, shouldn't happen unless out of memory
-
- return addrs;
-}
-
-void WindowsEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
-{
- if ((!_initialized)||(!_enabled)||(_tap == INVALID_HANDLE_VALUE)||(len > (ZT_IF_MTU)))
- return;
- {
- Mutex::Lock _l(_injectPending_m);
- _injectPending.push( std::pair<Array<char,ZT_IF_MTU + 32>,unsigned int>(Array<char,ZT_IF_MTU + 32>(),len + 14) );
- char *d = _injectPending.back().first.data;
- to.copyTo(d,6);
- from.copyTo(d + 6,6);
- d[12] = (char)((etherType >> 8) & 0xff);
- d[13] = (char)(etherType & 0xff);
- memcpy(d + 14,data,len);
- }
- ReleaseSemaphore(_injectSemaphore,1,NULL);
-}
-
-std::string WindowsEthernetTap::deviceName() const
-{
- return _netCfgInstanceId;
-}
-
-std::string WindowsEthernetTap::persistentId() const
-{
- return _deviceInstanceId;
-}
-
-bool WindowsEthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups)
-{
- if (!_initialized)
- return false;
- HANDLE t = _tap;
- if (t == INVALID_HANDLE_VALUE)
- return false;
-
- std::set<MulticastGroup> newGroups;
-
- // Ensure that groups are added for each IP... this handles the MAC:ADI
- // groups that are created from IPv4 addresses. Some of these may end
- // up being duplicates of what the IOCTL returns but that's okay since
- // the set<> will filter that.
- std::set<InetAddress> ipaddrs(ips());
- for(std::set<InetAddress>::const_iterator i(ipaddrs.begin());i!=ipaddrs.end();++i)
- newGroups.insert(MulticastGroup::deriveMulticastGroupForAddressResolution(*i));
-
- // The ZT1 tap driver supports an IOCTL to get multicast memberships at the L2
- // level... something Windows does not seem to expose ordinarily. This lets
- // pretty much anything work... IPv4, IPv6, IPX, oldskool Netbios, who knows...
- unsigned char mcastbuf[TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS_OUTPUT_BUF_SIZE];
- DWORD bytesReturned = 0;
- if (DeviceIoControl(t,TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS,(LPVOID)0,0,(LPVOID)mcastbuf,sizeof(mcastbuf),&bytesReturned,NULL)) {
- MAC mac;
- DWORD i = 0;
- while ((i + 6) <= bytesReturned) {
- mac.setTo(mcastbuf + i,6);
- i += 6;
- if ((mac.isMulticast())&&(!mac.isBroadcast())) {
- // exclude the nulls that may be returned or any other junk Windows puts in there
- newGroups.insert(MulticastGroup(mac,0));
- }
- }
- }
-
- bool changed = false;
-
- for(std::set<MulticastGroup>::iterator mg(newGroups.begin());mg!=newGroups.end();++mg) {
- if (!groups.count(*mg)) {
- groups.insert(*mg);
- changed = true;
- }
- }
- for(std::set<MulticastGroup>::iterator mg(groups.begin());mg!=groups.end();) {
- if ((!newGroups.count(*mg))&&(*mg != _blindWildcardMulticastGroup)) {
- groups.erase(mg++);
- changed = true;
- } else ++mg;
- }
-
- return changed;
-}
-
-void WindowsEthernetTap::threadMain()
- throw()
-{
- char tapPath[256];
- OVERLAPPED tapOvlRead,tapOvlWrite;
- HANDLE wait4[3];
- char *tapReadBuf = (char *)0;
-
- // Shouldn't be needed, but Windows does not overcommit. This Windows
- // tap code is defensive to schizoid paranoia degrees.
- while (!tapReadBuf) {
- tapReadBuf = (char *)::malloc(ZT_IF_MTU + 32);
- if (!tapReadBuf)
- Sleep(1000);
- }
-
- // Tap is in this weird Windows global pseudo file space
- Utils::snprintf(tapPath,sizeof(tapPath),"\\\\.\\Global\\%s.tap",_netCfgInstanceId.c_str());
-
- // More insanity: repetatively try to enable/disable tap device. The first
- // time we succeed, close it and do it again. This is to fix a driver init
- // bug that seems to be extremely non-deterministic and to only occur after
- // headless MSI upgrade. It cannot be reproduced in any other circumstance.
- bool throwOneAway = true;
- while (_run) {
- _disableTapDevice(_r,_deviceInstanceId);
- Sleep(250);
- if (!_enableTapDevice(_r,_deviceInstanceId)) {
- ::free(tapReadBuf);
- _enabled = false;
- return; // only happens if devcon is missing or totally fails
- }
- Sleep(250);
-
- _tap = CreateFileA(tapPath,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED,NULL);
- if (_tap == INVALID_HANDLE_VALUE) {
- Sleep(500);
- continue;
- }
-
- uint32_t tmpi = 1;
- DWORD bytesReturned = 0;
- DeviceIoControl(_tap,TAP_WIN_IOCTL_SET_MEDIA_STATUS,&tmpi,sizeof(tmpi),&tmpi,sizeof(tmpi),&bytesReturned,NULL);
-
- if (throwOneAway) {
- throwOneAway = false;
- CloseHandle(_tap);
- _tap = INVALID_HANDLE_VALUE;
- Sleep(250);
- continue;
- } else break;
- }
-
- memset(&tapOvlRead,0,sizeof(tapOvlRead));
- tapOvlRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
- memset(&tapOvlWrite,0,sizeof(tapOvlWrite));
- tapOvlWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
-
- wait4[0] = _injectSemaphore;
- wait4[1] = tapOvlRead.hEvent;
- wait4[2] = tapOvlWrite.hEvent; // only included if writeInProgress is true
-
- // Start overlapped read, which is always active
- ReadFile(_tap,tapReadBuf,sizeof(tapReadBuf),NULL,&tapOvlRead);
- bool writeInProgress = false;
-
- for(;;) {
- if (!_run) break;
- DWORD r = WaitForMultipleObjectsEx(writeInProgress ? 3 : 2,wait4,FALSE,5000,TRUE);
- if (!_run) break;
-
- if ((r == WAIT_TIMEOUT)||(r == WAIT_FAILED))
- continue;
-
- if (HasOverlappedIoCompleted(&tapOvlRead)) {
- DWORD bytesRead = 0;
- if (GetOverlappedResult(_tap,&tapOvlRead,&bytesRead,FALSE)) {
- if ((bytesRead > 14)&&(_enabled)) {
- MAC to(tapReadBuf,6);
- MAC from(tapReadBuf + 6,6);
- unsigned int etherType = ((((unsigned int)tapReadBuf[12]) & 0xff) << 8) | (((unsigned int)tapReadBuf[13]) & 0xff);
- try {
- Buffer<4096> tmp(tapReadBuf + 14,bytesRead - 14);
- _handler(_arg,from,to,etherType,tmp);
- } catch ( ... ) {} // handlers should not throw
- }
- }
- ReadFile(_tap,tapReadBuf,ZT_IF_MTU + 32,NULL,&tapOvlRead);
- }
-
- if (writeInProgress) {
- if (HasOverlappedIoCompleted(&tapOvlWrite)) {
- writeInProgress = false;
- _injectPending_m.lock();
- _injectPending.pop();
- } else continue; // still writing, so skip code below and wait
- } else _injectPending_m.lock();
-
- if (!_injectPending.empty()) {
- WriteFile(_tap,_injectPending.front().first.data,_injectPending.front().second,NULL,&tapOvlWrite);
- writeInProgress = true;
- }
-
- _injectPending_m.unlock();
- }
-
- CancelIo(_tap);
-
- CloseHandle(tapOvlRead.hEvent);
- CloseHandle(tapOvlWrite.hEvent);
- CloseHandle(_tap);
- _tap = INVALID_HANDLE_VALUE;
-
- ::free(tapReadBuf);
-}
-
-bool WindowsEthernetTap::deletePersistentTapDevice(const RuntimeEnvironment *_r,const char *pid)
-{
- Mutex::Lock _l(_systemTapInitLock); // only one thread may mess with taps at a time, process-wide
-
- HANDLE devconLog = CreateFileA((_r->homePath + "\\devcon.log").c_str(),GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
- STARTUPINFOA startupInfo;
- startupInfo.cb = sizeof(startupInfo);
- if (devconLog != INVALID_HANDLE_VALUE) {
- SetFilePointer(devconLog,0,0,FILE_END);
- startupInfo.hStdOutput = devconLog;
- startupInfo.hStdError = devconLog;
- }
- PROCESS_INFORMATION processInfo;
- memset(&startupInfo,0,sizeof(STARTUPINFOA));
- memset(&processInfo,0,sizeof(PROCESS_INFORMATION));
- if (CreateProcessA(NULL,(LPSTR)(std::string("\"") + _r->homePath + _winEnv.devcon + "\" remove @" + pid).c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) {
- WaitForSingleObject(processInfo.hProcess,INFINITE);
- CloseHandle(processInfo.hProcess);
- CloseHandle(processInfo.hThread);
- if (devconLog != INVALID_HANDLE_VALUE)
- CloseHandle(devconLog);
- return true;
- }
- if (devconLog != INVALID_HANDLE_VALUE)
- CloseHandle(devconLog);
-
- return false;
-}
-
-int WindowsEthernetTap::cleanPersistentTapDevices(const RuntimeEnvironment *_r,const std::set<std::string> &exceptThese,bool alsoRemoveUnassociatedDevices)
-{
- char subkeyName[4096];
- char subkeyClass[4096];
- char data[4096];
-
- std::set<std::string> instanceIdPathsToRemove;
- {
- Mutex::Lock _l(_systemTapInitLock); // only one thread may mess with taps at a time, process-wide
-
- HKEY nwAdapters;
- if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",0,KEY_READ|KEY_WRITE,&nwAdapters) != ERROR_SUCCESS)
- return -1;
-
- for(DWORD subkeyIndex=0;;++subkeyIndex) {
- DWORD type;
- DWORD dataLen;
- DWORD subkeyNameLen = sizeof(subkeyName);
- DWORD subkeyClassLen = sizeof(subkeyClass);
- FILETIME lastWriteTime;
- if (RegEnumKeyExA(nwAdapters,subkeyIndex,subkeyName,&subkeyNameLen,(DWORD *)0,subkeyClass,&subkeyClassLen,&lastWriteTime) == ERROR_SUCCESS) {
- type = 0;
- dataLen = sizeof(data);
- if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
- data[dataLen] = '\0';
- if (!strnicmp(data,"zttap",5)) {
- std::string instanceIdPath;
- type = 0;
- dataLen = sizeof(data);
- if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS)
- instanceIdPath.assign(data,dataLen);
- if (instanceIdPath.length() != 0) {
- type = 0;
- dataLen = sizeof(data);
- if (RegGetValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
- if (dataLen <= 0) {
- if (alsoRemoveUnassociatedDevices)
- instanceIdPathsToRemove.insert(instanceIdPath);
- } else {
- if (!exceptThese.count(std::string(data,dataLen)))
- instanceIdPathsToRemove.insert(instanceIdPath);
- }
- } else if (alsoRemoveUnassociatedDevices)
- instanceIdPathsToRemove.insert(instanceIdPath);
- }
- }
- }
- } else break; // end of list or failure
- }
-
- RegCloseKey(nwAdapters);
- }
-
- int removed = 0;
- for(std::set<std::string>::iterator iidp(instanceIdPathsToRemove.begin());iidp!=instanceIdPathsToRemove.end();++iidp) {
- if (deletePersistentTapDevice(_r,iidp->c_str()))
- ++removed;
- }
- return removed;
-}
-
-} // namespace ZeroTier
diff --git a/node/osdep/WindowsEthernetTap.hpp b/node/osdep/WindowsEthernetTap.hpp
deleted file mode 100644
index 74c56621..00000000
--- a/node/osdep/WindowsEthernetTap.hpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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_WINDOWSETHERNETTAP_HPP
-#define ZT_WINDOWSETHERNETTAP_HPP
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <string>
-#include <queue>
-#include <stdexcept>
-
-#include "../Constants.hpp"
-#include "../EthernetTap.hpp"
-#include "../Mutex.hpp"
-#include "../Thread.hpp"
-#include "../Array.hpp"
-
-namespace ZeroTier {
-
-/**
- * Windows Ethernet tap device using bundled ztTap driver
- */
-class WindowsEthernetTap : public EthernetTap
-{
-public:
- /**
- * Open tap device, installing and creating one if it does not exist
- *
- * @param renv Runtime environment
- * @param tag A tag (presently the hex network ID) used to identify persistent tap devices in the registry
- * @param mac MAC address of device
- * @param mtu MTU of device
- * @param desc If non-NULL, a description (not used on all OSes)
- * @param handler Handler function to be called when data is received from the tap
- * @param arg First argument to handler function
- * @throws std::runtime_error Unable to allocate device
- */
- WindowsEthernetTap(
- const RuntimeEnvironment *renv,
- const char *tag,
- const MAC &mac,
- unsigned int mtu,
- void (*handler)(void *,const MAC &,const MAC &,unsigned int,const Buffer<4096> &),
- void *arg)
- throw(std::runtime_error);
-
- virtual ~WindowsEthernetTap();
-
- virtual void setEnabled(bool en);
- virtual bool enabled() const;
- virtual void setDisplayName(const char *dn);
- 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 std::string persistentId() const;
- virtual bool updateMulticastGroups(std::set<MulticastGroup> &groups);
-
- /**
- * Thread main method; do not call elsewhere
- */
- void threadMain()
- throw();
-
- /**
- * Remove persistent tap device by device name
- *
- * @param _r Runtime environment
- * @param pdev Device name as returned by persistentId() while tap is running
- * @return True if a device was deleted
- */
- static bool deletePersistentTapDevice(const RuntimeEnvironment *_r,const char *pid);
-
- /**
- * Clean persistent tap devices that are not in the supplied set
- *
- * @param _r Runtime environment
- * @param exceptThese Devices to leave in place
- * @param alsoRemoveUnassociatedDevices If true, remove devices not associated with any network as well
- * @return Number of devices deleted or -1 if an error prevented the operation from being performed
- */
- static int cleanPersistentTapDevices(const RuntimeEnvironment *_r,const std::set<std::string> &exceptThese,bool alsoRemoveUnassociatedDevices);
-
-private:
- void (*_handler)(void *,const MAC &,const MAC &,unsigned int,const Buffer<4096> &);
- void *_arg;
- Thread _thread;
-
- volatile HANDLE _tap;
- HANDLE _injectSemaphore;
- GUID _deviceGuid;
- std::string _netCfgInstanceId; // NetCfgInstanceId, a GUID
- std::string _deviceInstanceId; // DeviceInstanceID, another kind of "instance ID"
- std::queue< std::pair< Array<char,ZT_IF_MTU + 32>,unsigned int > > _injectPending;
- Mutex _injectPending_m;
- volatile bool _run;
- volatile bool _initialized;
- volatile bool _enabled;
-};
-
-} // namespace ZeroTier
-
-#endif
diff --git a/node/osdep/WindowsEthernetTapFactory.cpp b/node/osdep/WindowsEthernetTapFactory.cpp
deleted file mode 100644
index e69de29b..00000000
--- a/node/osdep/WindowsEthernetTapFactory.cpp
+++ /dev/null
diff --git a/node/osdep/WindowsEthernetTapFactory.hpp b/node/osdep/WindowsEthernetTapFactory.hpp
deleted file mode 100644
index e69de29b..00000000
--- a/node/osdep/WindowsEthernetTapFactory.hpp
+++ /dev/null
diff --git a/node/osdep/WindowsRoutingTable.cpp b/node/osdep/WindowsRoutingTable.cpp
deleted file mode 100644
index e69de29b..00000000
--- a/node/osdep/WindowsRoutingTable.cpp
+++ /dev/null
diff --git a/node/osdep/WindowsRoutingTable.hpp b/node/osdep/WindowsRoutingTable.hpp
deleted file mode 100644
index e69de29b..00000000
--- a/node/osdep/WindowsRoutingTable.hpp
+++ /dev/null