mirror of
https://github.com/ZeroTier/ZeroTierOne
synced 2025-07-05 12:36:14 -07:00
clang-format
This commit is contained in:
parent
d45f280cb7
commit
ba2a4a605c
140 changed files with 19214 additions and 17403 deletions
|
@ -11,29 +11,28 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "Arp.hpp"
|
||||
|
||||
#include "OSUtils.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
static const uint8_t ARP_REQUEST_HEADER[8] = { 0x00,0x01,0x08,0x00,0x06,0x04,0x00,0x01 };
|
||||
static const uint8_t ARP_RESPONSE_HEADER[8] = { 0x00,0x01,0x08,0x00,0x06,0x04,0x00,0x02 };
|
||||
static const uint8_t ARP_REQUEST_HEADER[8] = { 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01 };
|
||||
static const uint8_t ARP_RESPONSE_HEADER[8] = { 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02 };
|
||||
|
||||
Arp::Arp() :
|
||||
_cache(256),
|
||||
_lastCleaned(OSUtils::now())
|
||||
Arp::Arp() : _cache(256), _lastCleaned(OSUtils::now())
|
||||
{
|
||||
}
|
||||
|
||||
void Arp::addLocal(uint32_t ip,const MAC &mac)
|
||||
void Arp::addLocal(uint32_t ip, const MAC& mac)
|
||||
{
|
||||
_ArpEntry &e = _cache[ip];
|
||||
e.lastQuerySent = 0; // local IP
|
||||
e.lastResponseReceived = 0; // local IP
|
||||
_ArpEntry& e = _cache[ip];
|
||||
e.lastQuerySent = 0; // local IP
|
||||
e.lastResponseReceived = 0; // local IP
|
||||
e.mac = mac;
|
||||
e.local = true;
|
||||
}
|
||||
|
@ -43,7 +42,7 @@ void Arp::remove(uint32_t ip)
|
|||
_cache.erase(ip);
|
||||
}
|
||||
|
||||
uint32_t Arp::processIncomingArp(const void *arp,unsigned int len,void *response,unsigned int &responseLen,MAC &responseDest)
|
||||
uint32_t Arp::processIncomingArp(const void* arp, unsigned int len, void* response, unsigned int& responseLen, MAC& responseDest)
|
||||
{
|
||||
const uint64_t now = OSUtils::now();
|
||||
uint32_t ip = 0;
|
||||
|
@ -52,25 +51,26 @@ uint32_t Arp::processIncomingArp(const void *arp,unsigned int len,void *response
|
|||
responseDest.zero();
|
||||
|
||||
if (len >= 28) {
|
||||
if (!memcmp(arp,ARP_REQUEST_HEADER,8)) {
|
||||
if (! memcmp(arp, ARP_REQUEST_HEADER, 8)) {
|
||||
// Respond to ARP requests for locally-known IPs
|
||||
_ArpEntry *targetEntry = _cache.get(reinterpret_cast<const uint32_t *>(arp)[6]);
|
||||
if ((targetEntry)&&(targetEntry->local)) {
|
||||
memcpy(response,ARP_RESPONSE_HEADER,8);
|
||||
targetEntry->mac.copyTo(reinterpret_cast<uint8_t *>(response) + 8,6);
|
||||
memcpy(reinterpret_cast<uint8_t *>(response) + 14,reinterpret_cast<const uint8_t *>(arp) + 24,4);
|
||||
memcpy(reinterpret_cast<uint8_t *>(response) + 18,reinterpret_cast<const uint8_t *>(arp) + 8,10);
|
||||
_ArpEntry* targetEntry = _cache.get(reinterpret_cast<const uint32_t*>(arp)[6]);
|
||||
if ((targetEntry) && (targetEntry->local)) {
|
||||
memcpy(response, ARP_RESPONSE_HEADER, 8);
|
||||
targetEntry->mac.copyTo(reinterpret_cast<uint8_t*>(response) + 8, 6);
|
||||
memcpy(reinterpret_cast<uint8_t*>(response) + 14, reinterpret_cast<const uint8_t*>(arp) + 24, 4);
|
||||
memcpy(reinterpret_cast<uint8_t*>(response) + 18, reinterpret_cast<const uint8_t*>(arp) + 8, 10);
|
||||
responseLen = 28;
|
||||
responseDest.setTo(reinterpret_cast<const uint8_t *>(arp) + 8,6);
|
||||
responseDest.setTo(reinterpret_cast<const uint8_t*>(arp) + 8, 6);
|
||||
}
|
||||
} else if (!memcmp(arp,ARP_RESPONSE_HEADER,8)) {
|
||||
}
|
||||
else if (! memcmp(arp, ARP_RESPONSE_HEADER, 8)) {
|
||||
// Learn cache entries for remote IPs from relevant ARP replies
|
||||
uint32_t responseIp = 0;
|
||||
memcpy(&responseIp,reinterpret_cast<const uint8_t *>(arp) + 14,4);
|
||||
_ArpEntry *queryEntry = _cache.get(responseIp);
|
||||
if ((queryEntry)&&(!queryEntry->local)&&((now - queryEntry->lastQuerySent) <= ZT_ARP_QUERY_MAX_TTL)) {
|
||||
memcpy(&responseIp, reinterpret_cast<const uint8_t*>(arp) + 14, 4);
|
||||
_ArpEntry* queryEntry = _cache.get(responseIp);
|
||||
if ((queryEntry) && (! queryEntry->local) && ((now - queryEntry->lastQuerySent) <= ZT_ARP_QUERY_MAX_TTL)) {
|
||||
queryEntry->lastResponseReceived = now;
|
||||
queryEntry->mac.setTo(reinterpret_cast<const uint8_t *>(arp) + 8,6);
|
||||
queryEntry->mac.setTo(reinterpret_cast<const uint8_t*>(arp) + 8, 6);
|
||||
ip = responseIp;
|
||||
}
|
||||
}
|
||||
|
@ -78,11 +78,11 @@ uint32_t Arp::processIncomingArp(const void *arp,unsigned int len,void *response
|
|||
|
||||
if ((now - _lastCleaned) >= ZT_ARP_EXPIRE) {
|
||||
_lastCleaned = now;
|
||||
Hashtable< uint32_t,_ArpEntry >::Iterator i(_cache);
|
||||
uint32_t *k = (uint32_t *)0;
|
||||
_ArpEntry *v = (_ArpEntry *)0;
|
||||
while (i.next(k,v)) {
|
||||
if ((!v->local)&&((now - v->lastResponseReceived) >= ZT_ARP_EXPIRE))
|
||||
Hashtable<uint32_t, _ArpEntry>::Iterator i(_cache);
|
||||
uint32_t* k = (uint32_t*)0;
|
||||
_ArpEntry* v = (_ArpEntry*)0;
|
||||
while (i.next(k, v)) {
|
||||
if ((! v->local) && ((now - v->lastResponseReceived) >= ZT_ARP_EXPIRE))
|
||||
_cache.erase(*k);
|
||||
}
|
||||
}
|
||||
|
@ -90,27 +90,32 @@ uint32_t Arp::processIncomingArp(const void *arp,unsigned int len,void *response
|
|||
return ip;
|
||||
}
|
||||
|
||||
MAC Arp::query(const MAC &localMac,uint32_t localIp,uint32_t targetIp,void *query,unsigned int &queryLen,MAC &queryDest)
|
||||
MAC Arp::query(const MAC& localMac, uint32_t localIp, uint32_t targetIp, void* query, unsigned int& queryLen, MAC& queryDest)
|
||||
{
|
||||
const uint64_t now = OSUtils::now();
|
||||
|
||||
_ArpEntry &e = _cache[targetIp];
|
||||
_ArpEntry& e = _cache[targetIp];
|
||||
|
||||
if ( ((e.mac)&&((now - e.lastResponseReceived) >= (ZT_ARP_EXPIRE / 3))) ||
|
||||
((!e.mac)&&((now - e.lastQuerySent) >= ZT_ARP_QUERY_INTERVAL)) ) {
|
||||
if (((e.mac) && ((now - e.lastResponseReceived) >= (ZT_ARP_EXPIRE / 3))) || ((! e.mac) && ((now - e.lastQuerySent) >= ZT_ARP_QUERY_INTERVAL))) {
|
||||
e.lastQuerySent = now;
|
||||
|
||||
uint8_t *q = reinterpret_cast<uint8_t *>(query);
|
||||
memcpy(q,ARP_REQUEST_HEADER,8); q += 8; // ARP request header information, always the same
|
||||
localMac.copyTo(q,6); q += 6; // sending host MAC address
|
||||
memcpy(q,&localIp,4); q += 4; // sending host IP (IP already in big-endian byte order)
|
||||
memset(q,0,6); q += 6; // sending zeros for target MAC address as thats what we want to find
|
||||
memcpy(q,&targetIp,4); // target IP address for resolution (IP already in big-endian byte order)
|
||||
uint8_t* q = reinterpret_cast<uint8_t*>(query);
|
||||
memcpy(q, ARP_REQUEST_HEADER, 8);
|
||||
q += 8; // ARP request header information, always the same
|
||||
localMac.copyTo(q, 6);
|
||||
q += 6; // sending host MAC address
|
||||
memcpy(q, &localIp, 4);
|
||||
q += 4; // sending host IP (IP already in big-endian byte order)
|
||||
memset(q, 0, 6);
|
||||
q += 6; // sending zeros for target MAC address as thats what we want to find
|
||||
memcpy(q, &targetIp, 4); // target IP address for resolution (IP already in big-endian byte order)
|
||||
queryLen = 28;
|
||||
if (e.mac)
|
||||
queryDest = e.mac; // confirmation query, send directly to address holder
|
||||
else queryDest = (uint64_t)0xffffffffffffULL; // broadcast query
|
||||
} else {
|
||||
queryDest = e.mac; // confirmation query, send directly to address holder
|
||||
else
|
||||
queryDest = (uint64_t)0xffffffffffffULL; // broadcast query
|
||||
}
|
||||
else {
|
||||
queryLen = 0;
|
||||
queryDest.zero();
|
||||
}
|
||||
|
@ -118,4 +123,4 @@ MAC Arp::query(const MAC &localMac,uint32_t localIp,uint32_t targetIp,void *quer
|
|||
return e.mac;
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -14,14 +14,13 @@
|
|||
#ifndef ZT_ARP_HPP
|
||||
#define ZT_ARP_HPP
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/Hashtable.hpp"
|
||||
#include "../node/MAC.hpp"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <utility>
|
||||
|
||||
/**
|
||||
* Maximum possible ARP length
|
||||
*
|
||||
|
@ -67,9 +66,8 @@ namespace ZeroTier {
|
|||
* This class is not thread-safe and must be guarded if used in multi-threaded
|
||||
* code.
|
||||
*/
|
||||
class Arp
|
||||
{
|
||||
public:
|
||||
class Arp {
|
||||
public:
|
||||
Arp();
|
||||
|
||||
/**
|
||||
|
@ -78,7 +76,7 @@ public:
|
|||
* @param mac Our local MAC address
|
||||
* @param ip IP in big-endian byte order (sin_addr.s_addr)
|
||||
*/
|
||||
void addLocal(uint32_t ip,const MAC &mac);
|
||||
void addLocal(uint32_t ip, const MAC& mac);
|
||||
|
||||
/**
|
||||
* Delete a local IP entry or a cached ARP entry
|
||||
|
@ -103,7 +101,7 @@ public:
|
|||
* @param responseDest Destination of response, or set to null if no response
|
||||
* @return IP address learned or 0 if no new IPs in cache
|
||||
*/
|
||||
uint32_t processIncomingArp(const void *arp,unsigned int len,void *response,unsigned int &responseLen,MAC &responseDest);
|
||||
uint32_t processIncomingArp(const void* arp, unsigned int len, void* response, unsigned int& responseLen, MAC& responseDest);
|
||||
|
||||
/**
|
||||
* Get the MAC corresponding to an IP, generating a query if needed
|
||||
|
@ -115,29 +113,30 @@ public:
|
|||
* MAC returned is non-null.
|
||||
*
|
||||
* @param localMac Local MAC address of host interface
|
||||
* @param localIp Local IP address of host interface
|
||||
* @param localIp Local IP address of host interface
|
||||
* @param targetIp IP to look up
|
||||
* @param query Buffer for generated query -- MUST be a minimum of ZT_ARP_BUF_LENGTH in size
|
||||
* @param queryLen Length of generated query, or set to 0 if no query generated
|
||||
* @param queryDest Destination of query, or set to null if no query generated
|
||||
* @return MAC or 0 if no cached entry for this IP
|
||||
*/
|
||||
MAC query(const MAC &localMac,uint32_t localIp,uint32_t targetIp,void *query,unsigned int &queryLen,MAC &queryDest);
|
||||
MAC query(const MAC& localMac, uint32_t localIp, uint32_t targetIp, void* query, unsigned int& queryLen, MAC& queryDest);
|
||||
|
||||
private:
|
||||
struct _ArpEntry
|
||||
{
|
||||
_ArpEntry() : lastQuerySent(0),lastResponseReceived(0),mac(),local(false) {}
|
||||
uint64_t lastQuerySent; // Time last query was sent or 0 for local IP
|
||||
uint64_t lastResponseReceived; // Time of last ARP response or 0 for local IP
|
||||
MAC mac; // MAC address of device responsible for IP or null if not known yet
|
||||
bool local; // True if this is a local ARP entry
|
||||
private:
|
||||
struct _ArpEntry {
|
||||
_ArpEntry() : lastQuerySent(0), lastResponseReceived(0), mac(), local(false)
|
||||
{
|
||||
}
|
||||
uint64_t lastQuerySent; // Time last query was sent or 0 for local IP
|
||||
uint64_t lastResponseReceived; // Time of last ARP response or 0 for local IP
|
||||
MAC mac; // MAC address of device responsible for IP or null if not known yet
|
||||
bool local; // True if this is a local ARP entry
|
||||
};
|
||||
|
||||
Hashtable< uint32_t,_ArpEntry > _cache;
|
||||
Hashtable<uint32_t, _ArpEntry> _cache;
|
||||
uint64_t _lastCleaned;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,81 +11,78 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "BSDEthernetTap.hpp"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/Mutex.hpp"
|
||||
#include "../node/Utils.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
|
||||
#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/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <algorithm>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <map>
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <pthread_np.h>
|
||||
|
||||
#include <sched.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <utility>
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/Utils.hpp"
|
||||
#include "../node/Mutex.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
#include "BSDEthernetTap.hpp"
|
||||
|
||||
#define ZT_BASE32_CHARS "0123456789abcdefghijklmnopqrstuv"
|
||||
#define ZT_TAP_BUF_SIZE (1024 * 16)
|
||||
|
||||
// ff:ff:ff:ff:ff:ff with no ADI
|
||||
static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff),0);
|
||||
static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff), 0);
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
BSDEthernetTap::BSDEthernetTap(
|
||||
const char *homePath,
|
||||
const char* homePath,
|
||||
unsigned int concurrency,
|
||||
bool pinning,
|
||||
const MAC &mac,
|
||||
const MAC& mac,
|
||||
unsigned int mtu,
|
||||
unsigned int metric,
|
||||
uint64_t nwid,
|
||||
const char *friendlyName,
|
||||
void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
|
||||
void *arg) :
|
||||
_handler(handler),
|
||||
_concurrency(concurrency),
|
||||
_pinning(pinning),
|
||||
_arg(arg),
|
||||
_nwid(nwid),
|
||||
_mtu(mtu),
|
||||
_metric(metric),
|
||||
_fd(0),
|
||||
_enabled(true),
|
||||
_lastIfAddrsUpdate(0)
|
||||
const char* friendlyName,
|
||||
void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
|
||||
void* arg)
|
||||
: _handler(handler)
|
||||
, _concurrency(concurrency)
|
||||
, _pinning(pinning)
|
||||
, _arg(arg)
|
||||
, _nwid(nwid)
|
||||
, _mtu(mtu)
|
||||
, _metric(metric)
|
||||
, _fd(0)
|
||||
, _enabled(true)
|
||||
, _lastIfAddrsUpdate(0)
|
||||
{
|
||||
static Mutex globalTapCreateLock;
|
||||
char devpath[64],ethaddr[64],mtustr[32],metstr[32],tmpdevname[32];
|
||||
char devpath[64], ethaddr[64], mtustr[32], metstr[32], tmpdevname[32];
|
||||
|
||||
Mutex::Lock _gl(globalTapCreateLock);
|
||||
|
||||
|
@ -108,43 +105,51 @@ BSDEthernetTap::BSDEthernetTap(
|
|||
_dev.push_back(ZT_BASE32_CHARS[(unsigned long)(nwid & 0x1f)]);
|
||||
|
||||
std::vector<std::string> devFiles(OSUtils::listDirectory("/dev"));
|
||||
for(int i=9993;i<(9993+128);++i) {
|
||||
OSUtils::ztsnprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i);
|
||||
OSUtils::ztsnprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname);
|
||||
if (std::find(devFiles.begin(),devFiles.end(),std::string(tmpdevname)) == devFiles.end()) {
|
||||
for (int i = 9993; i < (9993 + 128); ++i) {
|
||||
OSUtils::ztsnprintf(tmpdevname, sizeof(tmpdevname), "tap%d", i);
|
||||
OSUtils::ztsnprintf(devpath, sizeof(devpath), "/dev/%s", tmpdevname);
|
||||
if (std::find(devFiles.begin(), devFiles.end(), std::string(tmpdevname)) == devFiles.end()) {
|
||||
long cpid = (long)vfork();
|
||||
if (cpid == 0) {
|
||||
#ifdef ZT_TRACE
|
||||
fprintf(stderr, "DEBUG: ifconfig %s create" ZT_EOL_S, tmpdevname);
|
||||
#endif
|
||||
::execl("/sbin/ifconfig","/sbin/ifconfig",tmpdevname,"create",(const char *)0);
|
||||
::execl("/sbin/ifconfig", "/sbin/ifconfig", tmpdevname, "create", (const char*)0);
|
||||
::_exit(-1);
|
||||
} else if (cpid > 0) {
|
||||
}
|
||||
else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
::waitpid(cpid,&exitcode,0);
|
||||
} else throw std::runtime_error("fork() failed");
|
||||
::waitpid(cpid, &exitcode, 0);
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("fork() failed");
|
||||
|
||||
struct stat stattmp;
|
||||
if (!stat(devpath,&stattmp)) {
|
||||
if (! stat(devpath, &stattmp)) {
|
||||
cpid = (long)vfork();
|
||||
if (cpid == 0) {
|
||||
#ifdef ZT_TRACE
|
||||
fprintf(stderr, "DEBUG: ifconfig %s name %s" ZT_EOL_S, tmpdevname, _dev.c_str());
|
||||
#endif
|
||||
::execl("/sbin/ifconfig","/sbin/ifconfig",tmpdevname,"name",_dev.c_str(),(const char *)0);
|
||||
::execl("/sbin/ifconfig", "/sbin/ifconfig", tmpdevname, "name", _dev.c_str(), (const char*)0);
|
||||
::_exit(-1);
|
||||
} else if (cpid > 0) {
|
||||
}
|
||||
else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
::waitpid(cpid,&exitcode,0);
|
||||
::waitpid(cpid, &exitcode, 0);
|
||||
if (exitcode)
|
||||
throw std::runtime_error("ifconfig rename operation failed");
|
||||
} else throw std::runtime_error("fork() failed");
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("fork() failed");
|
||||
|
||||
_fd = ::open(devpath,O_RDWR);
|
||||
_fd = ::open(devpath, O_RDWR);
|
||||
if (_fd > 0)
|
||||
break;
|
||||
else throw std::runtime_error("unable to open created tap device");
|
||||
} else {
|
||||
else
|
||||
throw std::runtime_error("unable to open created tap device");
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error("cannot find /dev node for newly created tap device");
|
||||
}
|
||||
}
|
||||
|
@ -152,10 +157,10 @@ BSDEthernetTap::BSDEthernetTap(
|
|||
#else
|
||||
/* Other BSDs like OpenBSD only have a limited number of tap devices that cannot be renamed */
|
||||
|
||||
for(int i=0;i<64;++i) {
|
||||
OSUtils::ztsnprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i);
|
||||
OSUtils::ztsnprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname);
|
||||
_fd = ::open(devpath,O_RDWR);
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
OSUtils::ztsnprintf(tmpdevname, sizeof(tmpdevname), "tap%d", i);
|
||||
OSUtils::ztsnprintf(devpath, sizeof(devpath), "/dev/%s", tmpdevname);
|
||||
_fd = ::open(devpath, O_RDWR);
|
||||
if (_fd > 0) {
|
||||
_dev = tmpdevname;
|
||||
break;
|
||||
|
@ -166,25 +171,26 @@ BSDEthernetTap::BSDEthernetTap(
|
|||
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) {
|
||||
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
|
||||
OSUtils::ztsnprintf(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]);
|
||||
OSUtils::ztsnprintf(mtustr,sizeof(mtustr),"%u",_mtu);
|
||||
OSUtils::ztsnprintf(metstr,sizeof(metstr),"%u",_metric);
|
||||
OSUtils::ztsnprintf(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]);
|
||||
OSUtils::ztsnprintf(mtustr, sizeof(mtustr), "%u", _mtu);
|
||||
OSUtils::ztsnprintf(metstr, sizeof(metstr), "%u", _metric);
|
||||
long cpid = (long)vfork();
|
||||
if (cpid == 0) {
|
||||
#ifdef ZT_TRACE
|
||||
fprintf(stderr, "DEBUG: ifconfig %s lladdr %s mtu %s metric %s up" ZT_EOL_S, _dev.c_str(), ethaddr, mtustr, metstr);
|
||||
#endif
|
||||
::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"lladdr",ethaddr,"mtu",mtustr,"metric",metstr,"up",(const char *)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) {
|
||||
}
|
||||
else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
::waitpid(cpid,&exitcode,0);
|
||||
::waitpid(cpid, &exitcode, 0);
|
||||
if (exitcode) {
|
||||
::close(_fd);
|
||||
throw std::runtime_error("ifconfig failure setting link-layer address and activating tap interface");
|
||||
|
@ -192,7 +198,7 @@ BSDEthernetTap::BSDEthernetTap(
|
|||
}
|
||||
|
||||
// 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);
|
||||
fcntl(_fd, F_SETFD, fcntl(_fd, F_GETFD) | FD_CLOEXEC);
|
||||
|
||||
::pipe(_shutdownSignalPipe);
|
||||
|
||||
|
@ -201,23 +207,24 @@ BSDEthernetTap::BSDEthernetTap(
|
|||
|
||||
BSDEthernetTap::~BSDEthernetTap()
|
||||
{
|
||||
::write(_shutdownSignalPipe[1],"\0",1); // causes thread to exit
|
||||
::write(_shutdownSignalPipe[1], "\0", 1); // causes thread to exit
|
||||
::close(_fd);
|
||||
::close(_shutdownSignalPipe[0]);
|
||||
::close(_shutdownSignalPipe[1]);
|
||||
long cpid = (long)vfork();
|
||||
if (cpid == 0) {
|
||||
#ifdef ZT_TRACE
|
||||
fprintf(stderr, "DEBUG: ifconfig %s destroy" ZT_EOL_S, _dev.c_str());
|
||||
fprintf(stderr, "DEBUG: ifconfig %s destroy" ZT_EOL_S, _dev.c_str());
|
||||
#endif
|
||||
::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"destroy",(const char *)0);
|
||||
::execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "destroy", (const char*)0);
|
||||
::_exit(-1);
|
||||
} else if (cpid > 0) {
|
||||
}
|
||||
else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
::waitpid(cpid,&exitcode,0);
|
||||
::waitpid(cpid, &exitcode, 0);
|
||||
}
|
||||
Thread::join(_thread);
|
||||
for (std::thread &t : _rxThreads) {
|
||||
for (std::thread& t : _rxThreads) {
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
|
@ -232,7 +239,7 @@ bool BSDEthernetTap::enabled() const
|
|||
return _enabled;
|
||||
}
|
||||
|
||||
static bool ___removeIp(const std::string &_dev,const InetAddress &ip)
|
||||
static bool ___removeIp(const std::string& _dev, const InetAddress& ip)
|
||||
{
|
||||
long cpid = (long)vfork();
|
||||
if (cpid == 0) {
|
||||
|
@ -240,29 +247,30 @@ static bool ___removeIp(const std::string &_dev,const InetAddress &ip)
|
|||
#ifdef ZT_TRACE
|
||||
fprintf(stderr, "DEBUG: ifconfig %s inet %s -alias" ZT_EOL_S, _dev.c_str(), ip.toIpString(ipbuf));
|
||||
#endif
|
||||
execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"inet",ip.toIpString(ipbuf),"-alias",(const char *)0);
|
||||
execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "inet", ip.toIpString(ipbuf), "-alias", (const char*)0);
|
||||
_exit(-1);
|
||||
} else if (cpid > 0) {
|
||||
}
|
||||
else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
waitpid(cpid,&exitcode,0);
|
||||
waitpid(cpid, &exitcode, 0);
|
||||
return (exitcode == 0);
|
||||
}
|
||||
return false; // never reached, make compiler shut up about return value
|
||||
return false; // never reached, make compiler shut up about return value
|
||||
}
|
||||
|
||||
bool BSDEthernetTap::addIp(const InetAddress &ip)
|
||||
bool BSDEthernetTap::addIp(const InetAddress& ip)
|
||||
{
|
||||
if (!ip)
|
||||
if (! ip)
|
||||
return false;
|
||||
|
||||
std::vector<InetAddress> allIps(ips());
|
||||
if (std::find(allIps.begin(),allIps.end(),ip) != allIps.end())
|
||||
return true; // IP/netmask already assigned
|
||||
if (std::find(allIps.begin(), allIps.end(), ip) != allIps.end())
|
||||
return true; // IP/netmask already assigned
|
||||
|
||||
// Remove and reconfigure if address is the same but netmask is different
|
||||
for(std::vector<InetAddress>::iterator i(allIps.begin());i!=allIps.end();++i) {
|
||||
if ((i->ipsEqual(ip))&&(i->netmaskBits() != ip.netmaskBits())) {
|
||||
if (___removeIp(_dev,*i))
|
||||
for (std::vector<InetAddress>::iterator i(allIps.begin()); i != allIps.end(); ++i) {
|
||||
if ((i->ipsEqual(ip)) && (i->netmaskBits() != ip.netmaskBits())) {
|
||||
if (___removeIp(_dev, *i))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -273,23 +281,24 @@ bool BSDEthernetTap::addIp(const InetAddress &ip)
|
|||
#ifdef ZT_TRACE
|
||||
fprintf(stderr, "DEBUG: ifconfig %s %s %s alias" ZT_EOL_S, _dev.c_str(), ip.isV4() ? "inet" : "inet6", ip.toString(tmp));
|
||||
#endif
|
||||
::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),ip.isV4() ? "inet" : "inet6",ip.toString(tmp),"alias",(const char *)0);
|
||||
::execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), ip.isV4() ? "inet" : "inet6", ip.toString(tmp), "alias", (const char*)0);
|
||||
::_exit(-1);
|
||||
} else if (cpid > 0) {
|
||||
}
|
||||
else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
::waitpid(cpid,&exitcode,0);
|
||||
::waitpid(cpid, &exitcode, 0);
|
||||
return (exitcode == 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BSDEthernetTap::removeIp(const InetAddress &ip)
|
||||
bool BSDEthernetTap::removeIp(const InetAddress& ip)
|
||||
{
|
||||
if (!ip)
|
||||
if (! ip)
|
||||
return false;
|
||||
std::vector<InetAddress> allIps(ips());
|
||||
if (std::find(allIps.begin(),allIps.end(),ip) != allIps.end()) {
|
||||
if (___removeIp(_dev,ip))
|
||||
if (std::find(allIps.begin(), allIps.end(), ip) != allIps.end()) {
|
||||
if (___removeIp(_dev, ip))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -304,28 +313,28 @@ std::vector<InetAddress> BSDEthernetTap::ips() const
|
|||
}
|
||||
_lastIfAddrsUpdate = now;
|
||||
|
||||
struct ifaddrs *ifa = (struct ifaddrs *)0;
|
||||
struct ifaddrs* ifa = (struct ifaddrs*)0;
|
||||
if (getifaddrs(&ifa))
|
||||
return std::vector<InetAddress>();
|
||||
|
||||
std::vector<InetAddress> r;
|
||||
|
||||
struct ifaddrs *p = ifa;
|
||||
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) {
|
||||
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.push_back(InetAddress(&(sin->sin_addr.s_addr),4,Utils::countBits((uint32_t)nm->sin_addr.s_addr)));
|
||||
} break;
|
||||
struct sockaddr_in* sin = (struct sockaddr_in*)p->ifa_addr;
|
||||
struct sockaddr_in* nm = (struct sockaddr_in*)p->ifa_netmask;
|
||||
r.push_back(InetAddress(&(sin->sin_addr.s_addr), 4, Utils::countBits((uint32_t)nm->sin_addr.s_addr)));
|
||||
} break;
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *sin = (struct sockaddr_in6 *)p->ifa_addr;
|
||||
struct sockaddr_in6 *nm = (struct sockaddr_in6 *)p->ifa_netmask;
|
||||
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.push_back(InetAddress(sin->sin6_addr.s6_addr,16,Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3])));
|
||||
} break;
|
||||
memcpy(b, nm->sin6_addr.s6_addr, sizeof(b));
|
||||
r.push_back(InetAddress(sin->sin6_addr.s6_addr, 16, Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3])));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
p = p->ifa_next;
|
||||
|
@ -334,24 +343,24 @@ std::vector<InetAddress> BSDEthernetTap::ips() const
|
|||
if (ifa)
|
||||
freeifaddrs(ifa);
|
||||
|
||||
std::sort(r.begin(),r.end());
|
||||
std::unique(r.begin(),r.end());
|
||||
std::sort(r.begin(), r.end());
|
||||
std::unique(r.begin(), r.end());
|
||||
|
||||
_ifaddrs = r;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void BSDEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
|
||||
void BSDEthernetTap::put(const MAC& from, const MAC& to, unsigned int etherType, const void* data, unsigned int len)
|
||||
{
|
||||
char putBuf[ZT_MAX_MTU + 64];
|
||||
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);
|
||||
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);
|
||||
::write(_fd, putBuf, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -360,44 +369,44 @@ std::string BSDEthernetTap::deviceName() const
|
|||
return _dev;
|
||||
}
|
||||
|
||||
void BSDEthernetTap::setFriendlyName(const char *friendlyName)
|
||||
void BSDEthernetTap::setFriendlyName(const char* friendlyName)
|
||||
{
|
||||
}
|
||||
|
||||
void BSDEthernetTap::scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed)
|
||||
void BSDEthernetTap::scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed)
|
||||
{
|
||||
std::vector<MulticastGroup> newGroups;
|
||||
|
||||
#ifndef __OpenBSD__
|
||||
struct ifmaddrs *ifmap = (struct ifmaddrs *)0;
|
||||
if (!getifmaddrs(&ifmap)) {
|
||||
struct ifmaddrs *p = ifmap;
|
||||
struct ifmaddrs* ifmap = (struct ifmaddrs*)0;
|
||||
if (! getifmaddrs(&ifmap)) {
|
||||
struct 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.push_back(MulticastGroup(MAC(la->sdl_data + la->sdl_nlen,6),0));
|
||||
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.push_back(MulticastGroup(MAC(la->sdl_data + la->sdl_nlen, 6), 0));
|
||||
}
|
||||
p = p->ifma_next;
|
||||
}
|
||||
freeifmaddrs(ifmap);
|
||||
}
|
||||
#endif // __OpenBSD__
|
||||
#endif // __OpenBSD__
|
||||
|
||||
std::vector<InetAddress> allIps(ips());
|
||||
for(std::vector<InetAddress>::iterator ip(allIps.begin());ip!=allIps.end();++ip)
|
||||
for (std::vector<InetAddress>::iterator ip(allIps.begin()); ip != allIps.end(); ++ip)
|
||||
newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip));
|
||||
|
||||
std::sort(newGroups.begin(),newGroups.end());
|
||||
std::unique(newGroups.begin(),newGroups.end());
|
||||
std::sort(newGroups.begin(), newGroups.end());
|
||||
std::unique(newGroups.begin(), newGroups.end());
|
||||
|
||||
for(std::vector<MulticastGroup>::iterator m(newGroups.begin());m!=newGroups.end();++m) {
|
||||
if (!std::binary_search(_multicastGroups.begin(),_multicastGroups.end(),*m))
|
||||
for (std::vector<MulticastGroup>::iterator m(newGroups.begin()); m != newGroups.end(); ++m) {
|
||||
if (! std::binary_search(_multicastGroups.begin(), _multicastGroups.end(), *m))
|
||||
added.push_back(*m);
|
||||
}
|
||||
for(std::vector<MulticastGroup>::iterator m(_multicastGroups.begin());m!=_multicastGroups.end();++m) {
|
||||
if (!std::binary_search(newGroups.begin(),newGroups.end(),*m))
|
||||
for (std::vector<MulticastGroup>::iterator m(_multicastGroups.begin()); m != _multicastGroups.end(); ++m) {
|
||||
if (! std::binary_search(newGroups.begin(), newGroups.end(), *m))
|
||||
removed.push_back(*m);
|
||||
}
|
||||
|
||||
|
@ -411,21 +420,21 @@ void BSDEthernetTap::setMtu(unsigned int mtu)
|
|||
long cpid = (long)vfork();
|
||||
if (cpid == 0) {
|
||||
char tmp[64];
|
||||
OSUtils::ztsnprintf(tmp,sizeof(tmp),"%u",mtu);
|
||||
OSUtils::ztsnprintf(tmp, sizeof(tmp), "%u", mtu);
|
||||
#ifdef ZT_TRACE
|
||||
fprintf(stderr, "DEBUG: ifconfig %s mtu %s" ZT_EOL_S, _dev.c_str(), tmp);
|
||||
#endif
|
||||
execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"mtu",tmp,(const char *)0);
|
||||
execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "mtu", tmp, (const char*)0);
|
||||
_exit(-1);
|
||||
} else if (cpid > 0) {
|
||||
}
|
||||
else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
waitpid(cpid,&exitcode,0);
|
||||
waitpid(cpid, &exitcode, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BSDEthernetTap::threadMain()
|
||||
throw()
|
||||
void BSDEthernetTap::threadMain() throw()
|
||||
{
|
||||
// Wait for a moment after startup -- wait for Network to finish
|
||||
// constructing itself.
|
||||
|
@ -436,7 +445,6 @@ void BSDEthernetTap::threadMain()
|
|||
|
||||
for (unsigned int i = 0; i < _concurrency; ++i) {
|
||||
_rxThreads.push_back(std::thread([this, i, pinning] {
|
||||
|
||||
if (pinning) {
|
||||
int pinCore = i % _concurrency;
|
||||
fprintf(stderr, "Pinning thread %d to core %d\n", i, pinCore);
|
||||
|
@ -444,15 +452,14 @@ void BSDEthernetTap::threadMain()
|
|||
cpu_set_t cpuset;
|
||||
CPU_ZERO(&cpuset);
|
||||
CPU_SET(pinCore, &cpuset);
|
||||
//int rc = sched_setaffinity(self, sizeof(cpu_set_t), &cpuset);
|
||||
// int rc = sched_setaffinity(self, sizeof(cpu_set_t), &cpuset);
|
||||
int rc = pthread_setaffinity_np(self, sizeof(cpu_set_t), &cpuset);
|
||||
if (rc != 0)
|
||||
{
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "Failed to pin thread %d to core %d: %s\n", i, pinCore, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif // __OpenBSD__
|
||||
#endif // __OpenBSD__
|
||||
|
||||
uint8_t b[ZT_TAP_BUF_SIZE];
|
||||
MAC to, from;
|
||||
|
@ -461,37 +468,38 @@ void BSDEthernetTap::threadMain()
|
|||
|
||||
FD_ZERO(&readfds);
|
||||
FD_ZERO(&nullfds);
|
||||
nfds = (int)std::max(_shutdownSignalPipe[0],_fd) + 1;
|
||||
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);
|
||||
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
|
||||
if (FD_ISSET(_shutdownSignalPipe[0], &readfds)) // writes to shutdown pipe terminate thread
|
||||
break;
|
||||
|
||||
if (FD_ISSET(_fd,&readfds)) {
|
||||
n = (int)::read(_fd,b + r,sizeof(b) - r);
|
||||
if (FD_ISSET(_fd, &readfds)) {
|
||||
n = (int)::read(_fd, b + r, sizeof(b) - r);
|
||||
if (n < 0) {
|
||||
if ((errno != EINTR)&&(errno != ETIMEDOUT))
|
||||
if ((errno != EINTR) && (errno != ETIMEDOUT))
|
||||
break;
|
||||
} else {
|
||||
}
|
||||
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
|
||||
if (r > ((int)_mtu + 14)) // sanity check for weird TAP behavior on some platforms
|
||||
r = _mtu + 14;
|
||||
|
||||
if (_enabled) {
|
||||
to.setTo(b,6);
|
||||
from.setTo(b + 6,6);
|
||||
unsigned int etherType = ntohs(((const uint16_t *)b)[6]);
|
||||
_handler(_arg,(void *)0,_nwid,from,to,etherType,0,(const void *)(b + 14),r - 14);
|
||||
to.setTo(b, 6);
|
||||
from.setTo(b + 6, 6);
|
||||
unsigned int etherType = ntohs(((const uint16_t*)b)[6]);
|
||||
_handler(_arg, (void*)0, _nwid, from, to, etherType, 0, (const void*)(b + 14), r - 14);
|
||||
}
|
||||
|
||||
r = 0;
|
||||
|
@ -502,7 +510,7 @@ void BSDEthernetTap::threadMain()
|
|||
#ifndef __OpenBSD__
|
||||
}));
|
||||
}
|
||||
#endif // __OpenBSD__
|
||||
#endif // __OpenBSD__
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -14,57 +14,56 @@
|
|||
#ifndef ZT_BSDETHERNETTAP_HPP
|
||||
#define ZT_BSDETHERNETTAP_HPP
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/MAC.hpp"
|
||||
#include "../node/MulticastGroup.hpp"
|
||||
#include "EthernetTap.hpp"
|
||||
#include "Thread.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/MulticastGroup.hpp"
|
||||
#include "../node/MAC.hpp"
|
||||
#include "Thread.hpp"
|
||||
#include "EthernetTap.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class BSDEthernetTap : public EthernetTap
|
||||
{
|
||||
public:
|
||||
class BSDEthernetTap : public EthernetTap {
|
||||
public:
|
||||
BSDEthernetTap(
|
||||
const char *homePath,
|
||||
const char* homePath,
|
||||
unsigned int concurrency,
|
||||
bool pinning,
|
||||
const MAC &mac,
|
||||
const MAC& mac,
|
||||
unsigned int mtu,
|
||||
unsigned int metric,
|
||||
uint64_t nwid,
|
||||
const char *friendlyName,
|
||||
void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
|
||||
void *arg);
|
||||
const char* friendlyName,
|
||||
void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
|
||||
void* arg);
|
||||
|
||||
virtual ~BSDEthernetTap();
|
||||
|
||||
virtual void setEnabled(bool en);
|
||||
virtual bool enabled() const;
|
||||
virtual bool addIp(const InetAddress &ip);
|
||||
virtual bool removeIp(const InetAddress &ip);
|
||||
virtual bool addIp(const InetAddress& ip);
|
||||
virtual bool removeIp(const InetAddress& ip);
|
||||
virtual std::vector<InetAddress> ips() const;
|
||||
virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len);
|
||||
virtual void put(const MAC& from, const MAC& to, unsigned int etherType, const void* data, unsigned int len);
|
||||
virtual std::string deviceName() const;
|
||||
virtual void setFriendlyName(const char *friendlyName);
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
|
||||
virtual void setFriendlyName(const char* friendlyName);
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed);
|
||||
virtual void setMtu(unsigned int mtu);
|
||||
virtual void setDns(const char *domain, const std::vector<InetAddress> &servers) {}
|
||||
virtual void setDns(const char* domain, const std::vector<InetAddress>& servers)
|
||||
{
|
||||
}
|
||||
|
||||
void threadMain()
|
||||
throw();
|
||||
void threadMain() throw();
|
||||
|
||||
private:
|
||||
void (*_handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
|
||||
void *_arg;
|
||||
private:
|
||||
void (*_handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int);
|
||||
void* _arg;
|
||||
unsigned int _concurrency;
|
||||
bool _pinning;
|
||||
uint64_t _nwid;
|
||||
|
@ -81,6 +80,6 @@ private:
|
|||
std::vector<std::thread> _rxThreads;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,11 +22,11 @@
|
|||
#include <string.h>
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#include <shlobj.h>
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <netioapi.h>
|
||||
#include <shlobj.h>
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <ifaddrs.h>
|
||||
#include <sys/socket.h>
|
||||
|
@ -34,13 +34,13 @@
|
|||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#ifdef __LINUX__
|
||||
#include <linux/if_addr.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/if_addr.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(__unix__) || defined(__APPLE__)) && !defined(__LINUX__) && !defined(ZT_SDK)
|
||||
#if (defined(__unix__) || defined(__APPLE__)) && ! defined(__LINUX__) && ! defined(ZT_SDK)
|
||||
#include <net/if.h>
|
||||
#if TARGET_OS_OSX
|
||||
#include <netinet6/in6_var.h>
|
||||
|
@ -131,7 +131,7 @@ class Binder {
|
|||
template <typename PHY_HANDLER_TYPE, typename INTERFACE_CHECKER> void refresh(Phy<PHY_HANDLER_TYPE>& phy, unsigned int* ports, unsigned int portCount, const std::vector<InetAddress> explicitBind, INTERFACE_CHECKER& ifChecker)
|
||||
{
|
||||
std::map<InetAddress, std::string> localIfAddrs;
|
||||
PhySocket *udps;
|
||||
PhySocket* udps;
|
||||
Mutex::Lock _l(_lock);
|
||||
bool interfacesEnumerated = true;
|
||||
|
||||
|
@ -232,7 +232,7 @@ class Binder {
|
|||
}
|
||||
}
|
||||
|
||||
if ( (flags & IFA_F_TEMPORARY) != 0) {
|
||||
if ((flags & IFA_F_TEMPORARY) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (devname) {
|
||||
|
@ -318,11 +318,11 @@ class Binder {
|
|||
//
|
||||
(void)gotViaProc;
|
||||
|
||||
#if ! defined(__ANDROID__) // getifaddrs() freeifaddrs() not available on Android
|
||||
#if ! defined(__ANDROID__) // getifaddrs() freeifaddrs() not available on Android
|
||||
if (! gotViaProc) {
|
||||
struct ifaddrs* ifatbl = (struct ifaddrs*)0;
|
||||
struct ifaddrs* ifa;
|
||||
#if (defined(__unix__) || defined(__APPLE__)) && !defined(__LINUX__) && !defined(ZT_SDK)
|
||||
#if (defined(__unix__) || defined(__APPLE__)) && ! defined(__LINUX__) && ! defined(ZT_SDK)
|
||||
// set up an IPv6 socket so we can check the state of interfaces via SIOCGIFAFLAG_IN6
|
||||
int infoSock = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||
#endif
|
||||
|
@ -331,7 +331,7 @@ class Binder {
|
|||
while (ifa) {
|
||||
if ((ifa->ifa_name) && (ifa->ifa_addr)) {
|
||||
InetAddress ip = *(ifa->ifa_addr);
|
||||
#if (defined(__unix__) || defined(__APPLE__)) && !defined(__LINUX__) && !defined(ZT_SDK) && TARGET_OS_OSX
|
||||
#if (defined(__unix__) || defined(__APPLE__)) && ! defined(__LINUX__) && ! defined(ZT_SDK) && TARGET_OS_OSX
|
||||
// Check if the address is an IPv6 Temporary Address, macOS/BSD version
|
||||
if (ifa->ifa_addr->sa_family == AF_INET6) {
|
||||
struct sockaddr_in6* sa6 = (struct sockaddr_in6*)ifa->ifa_addr;
|
||||
|
@ -379,7 +379,7 @@ class Binder {
|
|||
else {
|
||||
interfacesEnumerated = false;
|
||||
}
|
||||
#if (defined(__unix__) || defined(__APPLE__)) && !defined(__LINUX__) && !defined(ZT_SDK)
|
||||
#if (defined(__unix__) || defined(__APPLE__)) && ! defined(__LINUX__) && ! defined(ZT_SDK)
|
||||
close(infoSock);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
#ifndef ZT_BLOCKINGQUEUE_HPP
|
||||
#define ZT_BLOCKINGQUEUE_HPP
|
||||
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <chrono>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
@ -28,11 +28,11 @@ namespace ZeroTier {
|
|||
*
|
||||
* Do not use in node/ since we have not gone C++11 there yet.
|
||||
*/
|
||||
template <class T>
|
||||
class BlockingQueue
|
||||
{
|
||||
public:
|
||||
BlockingQueue(void) : r(true) {}
|
||||
template <class T> class BlockingQueue {
|
||||
public:
|
||||
BlockingQueue(void) : r(true)
|
||||
{
|
||||
}
|
||||
|
||||
inline void post(T t)
|
||||
{
|
||||
|
@ -41,16 +41,16 @@ public:
|
|||
c.notify_one();
|
||||
}
|
||||
|
||||
inline void postLimit(T t,const unsigned long limit)
|
||||
inline void postLimit(T t, const unsigned long limit)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m);
|
||||
for(;;) {
|
||||
for (;;) {
|
||||
if (q.size() < limit) {
|
||||
q.push(t);
|
||||
c.notify_one();
|
||||
break;
|
||||
}
|
||||
if (!r)
|
||||
if (! r)
|
||||
break;
|
||||
gc.wait(lock);
|
||||
}
|
||||
|
@ -64,14 +64,14 @@ public:
|
|||
gc.notify_all();
|
||||
}
|
||||
|
||||
inline bool get(T &value)
|
||||
inline bool get(T& value)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m);
|
||||
if (!r)
|
||||
if (! r)
|
||||
return false;
|
||||
while (q.empty()) {
|
||||
c.wait(lock);
|
||||
if (!r) {
|
||||
if (! r) {
|
||||
gc.notify_all();
|
||||
return false;
|
||||
}
|
||||
|
@ -85,30 +85,25 @@ public:
|
|||
inline std::vector<T> drain()
|
||||
{
|
||||
std::vector<T> v;
|
||||
while (!q.empty()) {
|
||||
while (! q.empty()) {
|
||||
v.push_back(q.front());
|
||||
q.pop();
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
enum TimedWaitResult
|
||||
{
|
||||
OK,
|
||||
TIMED_OUT,
|
||||
STOP
|
||||
};
|
||||
enum TimedWaitResult { OK, TIMED_OUT, STOP };
|
||||
|
||||
inline TimedWaitResult get(T &value,const unsigned long ms)
|
||||
inline TimedWaitResult get(T& value, const unsigned long ms)
|
||||
{
|
||||
const std::chrono::milliseconds ms2{ms};
|
||||
const std::chrono::milliseconds ms2 { ms };
|
||||
std::unique_lock<std::mutex> lock(m);
|
||||
if (!r)
|
||||
if (! r)
|
||||
return STOP;
|
||||
while (q.empty()) {
|
||||
if (c.wait_for(lock,ms2) == std::cv_status::timeout)
|
||||
if (c.wait_for(lock, ms2) == std::cv_status::timeout)
|
||||
return ((r) ? TIMED_OUT : STOP);
|
||||
else if (!r)
|
||||
else if (! r)
|
||||
return STOP;
|
||||
}
|
||||
value = q.front();
|
||||
|
@ -116,17 +111,18 @@ public:
|
|||
return OK;
|
||||
}
|
||||
|
||||
inline size_t size() const {
|
||||
inline size_t size() const
|
||||
{
|
||||
return q.size();
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
std::queue<T> q;
|
||||
mutable std::mutex m;
|
||||
mutable std::condition_variable c,gc;
|
||||
mutable std::condition_variable c, gc;
|
||||
std::atomic_bool r;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
/****/
|
||||
|
||||
#include "EthernetTap.hpp"
|
||||
|
||||
#include "OSUtils.hpp"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
@ -20,82 +21,83 @@
|
|||
#ifdef ZT_SDK
|
||||
|
||||
#include "../controller/EmbeddedNetworkController.hpp"
|
||||
#include "../node/Node.hpp"
|
||||
#include "../include/VirtualTap.hpp"
|
||||
#include "../node/Node.hpp"
|
||||
|
||||
#else
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <sys/sysctl.h>
|
||||
#include "MacEthernetTap.hpp"
|
||||
#include "MacKextEthernetTap.hpp"
|
||||
#endif // __APPLE__
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
#endif // __APPLE__
|
||||
|
||||
#ifdef __LINUX__
|
||||
#include "LinuxEthernetTap.hpp"
|
||||
#endif // __LINUX__
|
||||
#endif // __LINUX__
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#include "WindowsEthernetTap.hpp"
|
||||
#endif // __WINDOWS__
|
||||
#endif // __WINDOWS__
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include "BSDEthernetTap.hpp"
|
||||
#endif // __FreeBSD__
|
||||
#endif // __FreeBSD__
|
||||
|
||||
#ifdef __NetBSD__
|
||||
#include "NetBSDEthernetTap.hpp"
|
||||
#endif // __NetBSD__
|
||||
#endif // __NetBSD__
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
#include "BSDEthernetTap.hpp"
|
||||
#endif // __OpenBSD__
|
||||
#endif // __OpenBSD__
|
||||
|
||||
#endif
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
std::shared_ptr<EthernetTap> EthernetTap::newInstance(
|
||||
const char *tapDeviceType, // OS-specific, NULL for default
|
||||
const char* tapDeviceType, // OS-specific, NULL for default
|
||||
unsigned int concurrency,
|
||||
bool pinning,
|
||||
const char *homePath,
|
||||
const MAC &mac,
|
||||
const char* homePath,
|
||||
const MAC& mac,
|
||||
unsigned int mtu,
|
||||
unsigned int metric,
|
||||
uint64_t nwid,
|
||||
const char *friendlyName,
|
||||
void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
|
||||
void *arg)
|
||||
const char* friendlyName,
|
||||
void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
|
||||
void* arg)
|
||||
{
|
||||
|
||||
#ifdef ZT_SDK
|
||||
|
||||
return std::shared_ptr<EthernetTap>(new VirtualTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg));
|
||||
return std::shared_ptr<EthernetTap>(new VirtualTap(homePath, mac, mtu, metric, nwid, friendlyName, handler, arg));
|
||||
|
||||
#else // not ZT_SDK
|
||||
#else // not ZT_SDK
|
||||
|
||||
#ifdef __APPLE__
|
||||
char osrelease[256];
|
||||
size_t size = sizeof(osrelease);
|
||||
if (sysctlbyname("kern.osrelease",osrelease,&size,nullptr,0) == 0) {
|
||||
char *dotAt = strchr(osrelease,'.');
|
||||
if (sysctlbyname("kern.osrelease", osrelease, &size, nullptr, 0) == 0) {
|
||||
char* dotAt = strchr(osrelease, '.');
|
||||
if (dotAt) {
|
||||
*dotAt = (char)0;
|
||||
// The "feth" virtual Ethernet device type appeared in Darwin 17.x.x. Older versions
|
||||
// (Sierra and earlier) must use the a kernel extension.
|
||||
if (strtol(osrelease,(char **)0,10) < 17) {
|
||||
return std::shared_ptr<EthernetTap>(new MacKextEthernetTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg));
|
||||
} else {
|
||||
return std::shared_ptr<EthernetTap>(new MacEthernetTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg));
|
||||
if (strtol(osrelease, (char**)0, 10) < 17) {
|
||||
return std::shared_ptr<EthernetTap>(new MacKextEthernetTap(homePath, mac, mtu, metric, nwid, friendlyName, handler, arg));
|
||||
}
|
||||
else {
|
||||
return std::shared_ptr<EthernetTap>(new MacEthernetTap(homePath, mac, mtu, metric, nwid, friendlyName, handler, arg));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // __APPLE__
|
||||
#endif // __APPLE__
|
||||
|
||||
#ifdef __LINUX__
|
||||
return std::shared_ptr<EthernetTap>(new LinuxEthernetTap(homePath,concurrency,pinning,mac,mtu,metric,nwid,friendlyName,handler,arg));
|
||||
#endif // __LINUX__
|
||||
return std::shared_ptr<EthernetTap>(new LinuxEthernetTap(homePath, concurrency, pinning, mac, mtu, metric, nwid, friendlyName, handler, arg));
|
||||
#endif // __LINUX__
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
HRESULT hres = CoInitializeEx(0, COINIT_MULTITHREADED);
|
||||
|
@ -108,18 +110,8 @@ std::shared_ptr<EthernetTap> EthernetTap::newInstance(
|
|||
|
||||
{
|
||||
Mutex::Lock l(_comInit_m);
|
||||
if (!_comInit) {
|
||||
hres = CoInitializeSecurity(
|
||||
NULL,
|
||||
-1,
|
||||
NULL,
|
||||
NULL,
|
||||
RPC_C_AUTHN_LEVEL_PKT,
|
||||
RPC_C_IMP_LEVEL_IMPERSONATE,
|
||||
NULL,
|
||||
EOAC_NONE,
|
||||
NULL
|
||||
);
|
||||
if (! _comInit) {
|
||||
hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
|
||||
if (FAILED(hres)) {
|
||||
CoUninitialize();
|
||||
fprintf(stderr, "WinEthernetTap: Failed to initialize security");
|
||||
|
@ -128,33 +120,37 @@ std::shared_ptr<EthernetTap> EthernetTap::newInstance(
|
|||
_comInit = true;
|
||||
}
|
||||
}
|
||||
return std::shared_ptr<EthernetTap>(new WindowsEthernetTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg));
|
||||
#endif // __WINDOWS__
|
||||
return std::shared_ptr<EthernetTap>(new WindowsEthernetTap(homePath, mac, mtu, metric, nwid, friendlyName, handler, arg));
|
||||
#endif // __WINDOWS__
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
return std::shared_ptr<EthernetTap>(new BSDEthernetTap(homePath,concurrency,pinning,mac,mtu,metric,nwid,friendlyName,handler,arg));
|
||||
#endif // __FreeBSD__
|
||||
return std::shared_ptr<EthernetTap>(new BSDEthernetTap(homePath, concurrency, pinning, mac, mtu, metric, nwid, friendlyName, handler, arg));
|
||||
#endif // __FreeBSD__
|
||||
|
||||
#ifdef __NetBSD__
|
||||
return std::shared_ptr<EthernetTap>(new NetBSDEthernetTap(homePath,mac,mtu,metric,nwid,friendlyName,handler,arg));
|
||||
#endif // __NetBSD__
|
||||
return std::shared_ptr<EthernetTap>(new NetBSDEthernetTap(homePath, mac, mtu, metric, nwid, friendlyName, handler, arg));
|
||||
#endif // __NetBSD__
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
return std::shared_ptr<EthernetTap>(new BSDEthernetTap(homePath,concurrency,pinning,mac,mtu,metric,nwid,friendlyName,handler,arg));
|
||||
#endif // __OpenBSD__
|
||||
return std::shared_ptr<EthernetTap>(new BSDEthernetTap(homePath, concurrency, pinning, mac, mtu, metric, nwid, friendlyName, handler, arg));
|
||||
#endif // __OpenBSD__
|
||||
|
||||
#endif // ZT_SDK?
|
||||
#endif // ZT_SDK?
|
||||
|
||||
return std::shared_ptr<EthernetTap>();
|
||||
}
|
||||
|
||||
EthernetTap::EthernetTap() {}
|
||||
EthernetTap::~EthernetTap() {}
|
||||
EthernetTap::EthernetTap()
|
||||
{
|
||||
}
|
||||
EthernetTap::~EthernetTap()
|
||||
{
|
||||
}
|
||||
|
||||
bool EthernetTap::addIps(std::vector<InetAddress> ips)
|
||||
{
|
||||
for(std::vector<InetAddress>::const_iterator i(ips.begin());i!=ips.end();++i) {
|
||||
if (!addIp(*i))
|
||||
for (std::vector<InetAddress>::const_iterator i(ips.begin()); i != ips.end(); ++i) {
|
||||
if (! addIp(*i))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -166,4 +162,4 @@ std::string EthernetTap::friendlyName() const
|
|||
return std::string();
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -15,52 +15,51 @@
|
|||
#define ZT_ETHERNETTAP_HPP
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/MAC.hpp"
|
||||
#include "../node/InetAddress.hpp"
|
||||
#include "../node/MAC.hpp"
|
||||
#include "../node/MulticastGroup.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define GETIFADDRS_CACHE_TIME 1000
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class EthernetTap
|
||||
{
|
||||
public:
|
||||
class EthernetTap {
|
||||
public:
|
||||
static std::shared_ptr<EthernetTap> newInstance(
|
||||
const char *tapDeviceType, // OS-specific, NULL for default
|
||||
const char* tapDeviceType, // OS-specific, NULL for default
|
||||
unsigned int concurrency,
|
||||
bool pinning,
|
||||
const char *homePath,
|
||||
const MAC &mac,
|
||||
const char* homePath,
|
||||
const MAC& mac,
|
||||
unsigned int mtu,
|
||||
unsigned int metric,
|
||||
uint64_t nwid,
|
||||
const char *friendlyName,
|
||||
void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
|
||||
void *arg);
|
||||
const char* friendlyName,
|
||||
void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
|
||||
void* arg);
|
||||
|
||||
EthernetTap();
|
||||
virtual ~EthernetTap();
|
||||
|
||||
virtual void setEnabled(bool en) = 0;
|
||||
virtual bool enabled() const = 0;
|
||||
virtual bool addIp(const InetAddress &ip) = 0;
|
||||
virtual bool addIps(std::vector<InetAddress> ips); // uses addIp() unless overridden
|
||||
virtual bool removeIp(const InetAddress &ip) = 0;
|
||||
virtual bool addIp(const InetAddress& ip) = 0;
|
||||
virtual bool addIps(std::vector<InetAddress> ips); // uses addIp() unless overridden
|
||||
virtual bool removeIp(const InetAddress& ip) = 0;
|
||||
virtual std::vector<InetAddress> ips() const = 0;
|
||||
virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) = 0;
|
||||
virtual void put(const MAC& from, const MAC& to, unsigned int etherType, const void* data, unsigned int len) = 0;
|
||||
virtual std::string deviceName() const = 0;
|
||||
virtual void setFriendlyName(const char *friendlyName) = 0;
|
||||
virtual void setFriendlyName(const char* friendlyName) = 0;
|
||||
virtual std::string friendlyName() const;
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed) = 0;
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed) = 0;
|
||||
virtual void setMtu(unsigned int mtu) = 0;
|
||||
virtual void setDns(const char *domain, const std::vector<InetAddress> &servers) = 0;
|
||||
virtual void setDns(const char* domain, const std::vector<InetAddress>& servers) = 0;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
|
206
osdep/Http.cpp
206
osdep/Http.cpp
|
@ -11,15 +11,16 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "Http.hpp"
|
||||
#include "Phy.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/Utils.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
#include "Phy.hpp"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef ZT_USE_SYSTEM_HTTP_PARSER
|
||||
#include <http_parser.h>
|
||||
|
@ -31,90 +32,87 @@ namespace ZeroTier {
|
|||
|
||||
namespace {
|
||||
|
||||
static int ShttpOnMessageBegin(http_parser *parser);
|
||||
static int ShttpOnUrl(http_parser *parser,const char *ptr,size_t length);
|
||||
static int ShttpOnMessageBegin(http_parser* parser);
|
||||
static int ShttpOnUrl(http_parser* parser, const char* ptr, size_t length);
|
||||
#if (HTTP_PARSER_VERSION_MAJOR >= 2) && (HTTP_PARSER_VERSION_MINOR >= 2)
|
||||
static int ShttpOnStatus(http_parser *parser,const char *ptr,size_t length);
|
||||
static int ShttpOnStatus(http_parser* parser, const char* ptr, size_t length);
|
||||
#else
|
||||
static int ShttpOnStatus(http_parser *parser);
|
||||
static int ShttpOnStatus(http_parser* parser);
|
||||
#endif
|
||||
static int ShttpOnHeaderField(http_parser *parser,const char *ptr,size_t length);
|
||||
static int ShttpOnValue(http_parser *parser,const char *ptr,size_t length);
|
||||
static int ShttpOnHeadersComplete(http_parser *parser);
|
||||
static int ShttpOnBody(http_parser *parser,const char *ptr,size_t length);
|
||||
static int ShttpOnMessageComplete(http_parser *parser);
|
||||
static int ShttpOnHeaderField(http_parser* parser, const char* ptr, size_t length);
|
||||
static int ShttpOnValue(http_parser* parser, const char* ptr, size_t length);
|
||||
static int ShttpOnHeadersComplete(http_parser* parser);
|
||||
static int ShttpOnBody(http_parser* parser, const char* ptr, size_t length);
|
||||
static int ShttpOnMessageComplete(http_parser* parser);
|
||||
|
||||
#if (HTTP_PARSER_VERSION_MAJOR >= 2) && (HTTP_PARSER_VERSION_MINOR >= 1)
|
||||
static const struct http_parser_settings HTTP_PARSER_SETTINGS = {
|
||||
ShttpOnMessageBegin,
|
||||
ShttpOnUrl,
|
||||
ShttpOnStatus,
|
||||
ShttpOnHeaderField,
|
||||
ShttpOnValue,
|
||||
ShttpOnHeadersComplete,
|
||||
ShttpOnBody,
|
||||
ShttpOnMessageComplete
|
||||
};
|
||||
static const struct http_parser_settings HTTP_PARSER_SETTINGS = { ShttpOnMessageBegin, ShttpOnUrl, ShttpOnStatus, ShttpOnHeaderField, ShttpOnValue, ShttpOnHeadersComplete, ShttpOnBody, ShttpOnMessageComplete };
|
||||
#else
|
||||
static const struct http_parser_settings HTTP_PARSER_SETTINGS = {
|
||||
ShttpOnMessageBegin,
|
||||
ShttpOnUrl,
|
||||
ShttpOnHeaderField,
|
||||
ShttpOnValue,
|
||||
ShttpOnHeadersComplete,
|
||||
ShttpOnBody,
|
||||
ShttpOnMessageComplete
|
||||
};
|
||||
static const struct http_parser_settings HTTP_PARSER_SETTINGS = { ShttpOnMessageBegin, ShttpOnUrl, ShttpOnHeaderField, ShttpOnValue, ShttpOnHeadersComplete, ShttpOnBody, ShttpOnMessageComplete };
|
||||
#endif
|
||||
|
||||
struct HttpPhyHandler
|
||||
{
|
||||
struct HttpPhyHandler {
|
||||
// not used
|
||||
inline void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len) {}
|
||||
inline void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from) {}
|
||||
inline void phyOnDatagram(PhySocket* sock, void** uptr, const struct sockaddr* localAddr, const struct sockaddr* from, void* data, unsigned long len)
|
||||
{
|
||||
}
|
||||
inline void phyOnTcpAccept(PhySocket* sockL, PhySocket* sockN, void** uptrL, void** uptrN, const struct sockaddr* from)
|
||||
{
|
||||
}
|
||||
|
||||
inline void phyOnTcpConnect(PhySocket *sock,void **uptr,bool success)
|
||||
inline void phyOnTcpConnect(PhySocket* sock, void** uptr, bool success)
|
||||
{
|
||||
if (success) {
|
||||
phy->setNotifyWritable(sock,true);
|
||||
} else {
|
||||
phy->setNotifyWritable(sock, true);
|
||||
}
|
||||
else {
|
||||
*responseBody = "connection failed";
|
||||
error = true;
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
inline void phyOnTcpClose(PhySocket *sock,void **uptr)
|
||||
inline void phyOnTcpClose(PhySocket* sock, void** uptr)
|
||||
{
|
||||
done = true;
|
||||
}
|
||||
|
||||
inline void phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len)
|
||||
inline void phyOnTcpData(PhySocket* sock, void** uptr, void* data, unsigned long len)
|
||||
{
|
||||
lastActivity = OSUtils::now();
|
||||
http_parser_execute(&parser,&HTTP_PARSER_SETTINGS,(const char *)data,len);
|
||||
if ((parser.upgrade)||(parser.http_errno != HPE_OK))
|
||||
http_parser_execute(&parser, &HTTP_PARSER_SETTINGS, (const char*)data, len);
|
||||
if ((parser.upgrade) || (parser.http_errno != HPE_OK))
|
||||
phy->close(sock);
|
||||
}
|
||||
|
||||
inline void phyOnTcpWritable(PhySocket *sock,void **uptr)
|
||||
inline void phyOnTcpWritable(PhySocket* sock, void** uptr)
|
||||
{
|
||||
if (writePtr < (unsigned long)writeBuf.length()) {
|
||||
long n = phy->streamSend(sock,writeBuf.data() + writePtr,(unsigned long)writeBuf.length() - writePtr,true);
|
||||
long n = phy->streamSend(sock, writeBuf.data() + writePtr, (unsigned long)writeBuf.length() - writePtr, true);
|
||||
if (n > 0)
|
||||
writePtr += n;
|
||||
}
|
||||
if (writePtr >= (unsigned long)writeBuf.length())
|
||||
phy->setNotifyWritable(sock,false);
|
||||
phy->setNotifyWritable(sock, false);
|
||||
}
|
||||
|
||||
inline void phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable) {}
|
||||
inline void phyOnFileDescriptorActivity(PhySocket* sock, void** uptr, bool readable, bool writable)
|
||||
{
|
||||
}
|
||||
#ifdef __UNIX_LIKE__
|
||||
inline void phyOnUnixAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN) {}
|
||||
inline void phyOnUnixClose(PhySocket *sock,void **uptr) {}
|
||||
inline void phyOnUnixData(PhySocket *sock,void **uptr,void *data,unsigned long len) {}
|
||||
inline void phyOnUnixWritable(PhySocket *sock,void **uptr) {}
|
||||
#endif // __UNIX_LIKE__
|
||||
inline void phyOnUnixAccept(PhySocket* sockL, PhySocket* sockN, void** uptrL, void** uptrN)
|
||||
{
|
||||
}
|
||||
inline void phyOnUnixClose(PhySocket* sock, void** uptr)
|
||||
{
|
||||
}
|
||||
inline void phyOnUnixData(PhySocket* sock, void** uptr, void* data, unsigned long len)
|
||||
{
|
||||
}
|
||||
inline void phyOnUnixWritable(PhySocket* sock, void** uptr)
|
||||
{
|
||||
}
|
||||
#endif // __UNIX_LIKE__
|
||||
|
||||
http_parser parser;
|
||||
std::string currentHeaderField;
|
||||
|
@ -125,27 +123,27 @@ struct HttpPhyHandler
|
|||
std::string writeBuf;
|
||||
|
||||
unsigned long maxResponseSize;
|
||||
std::map<std::string,std::string> *responseHeaders;
|
||||
std::string *responseBody;
|
||||
std::map<std::string, std::string>* responseHeaders;
|
||||
std::string* responseBody;
|
||||
bool error;
|
||||
bool done;
|
||||
|
||||
Phy<HttpPhyHandler *> *phy;
|
||||
PhySocket *sock;
|
||||
Phy<HttpPhyHandler*>* phy;
|
||||
PhySocket* sock;
|
||||
};
|
||||
|
||||
static int ShttpOnMessageBegin(http_parser *parser)
|
||||
static int ShttpOnMessageBegin(http_parser* parser)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static int ShttpOnUrl(http_parser *parser,const char *ptr,size_t length)
|
||||
static int ShttpOnUrl(http_parser* parser, const char* ptr, size_t length)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#if (HTTP_PARSER_VERSION_MAJOR >= 2) && (HTTP_PARSER_VERSION_MINOR >= 2)
|
||||
static int ShttpOnStatus(http_parser *parser,const char *ptr,size_t length)
|
||||
static int ShttpOnStatus(http_parser* parser, const char* ptr, size_t length)
|
||||
#else
|
||||
static int ShttpOnStatus(http_parser *parser)
|
||||
static int ShttpOnStatus(http_parser* parser)
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
|
@ -156,66 +154,66 @@ static int ShttpOnStatus(http_parser *parser)
|
|||
*/
|
||||
return 0;
|
||||
}
|
||||
static int ShttpOnHeaderField(http_parser *parser,const char *ptr,size_t length)
|
||||
static int ShttpOnHeaderField(http_parser* parser, const char* ptr, size_t length)
|
||||
{
|
||||
HttpPhyHandler *hh = reinterpret_cast<HttpPhyHandler *>(parser->data);
|
||||
HttpPhyHandler* hh = reinterpret_cast<HttpPhyHandler*>(parser->data);
|
||||
hh->messageSize += (unsigned long)length;
|
||||
if (hh->messageSize > hh->maxResponseSize)
|
||||
return -1;
|
||||
if ((hh->currentHeaderField.length())&&(hh->currentHeaderValue.length())) {
|
||||
if ((hh->currentHeaderField.length()) && (hh->currentHeaderValue.length())) {
|
||||
(*hh->responseHeaders)[hh->currentHeaderField] = hh->currentHeaderValue;
|
||||
hh->currentHeaderField = "";
|
||||
hh->currentHeaderValue = "";
|
||||
}
|
||||
for(size_t i=0;i<length;++i)
|
||||
for (size_t i = 0; i < length; ++i)
|
||||
hh->currentHeaderField.push_back(OSUtils::toLower(ptr[i]));
|
||||
return 0;
|
||||
}
|
||||
static int ShttpOnValue(http_parser *parser,const char *ptr,size_t length)
|
||||
static int ShttpOnValue(http_parser* parser, const char* ptr, size_t length)
|
||||
{
|
||||
HttpPhyHandler *hh = reinterpret_cast<HttpPhyHandler *>(parser->data);
|
||||
HttpPhyHandler* hh = reinterpret_cast<HttpPhyHandler*>(parser->data);
|
||||
hh->messageSize += (unsigned long)length;
|
||||
if (hh->messageSize > hh->maxResponseSize)
|
||||
return -1;
|
||||
hh->currentHeaderValue.append(ptr,length);
|
||||
hh->currentHeaderValue.append(ptr, length);
|
||||
return 0;
|
||||
}
|
||||
static int ShttpOnHeadersComplete(http_parser *parser)
|
||||
static int ShttpOnHeadersComplete(http_parser* parser)
|
||||
{
|
||||
HttpPhyHandler *hh = reinterpret_cast<HttpPhyHandler *>(parser->data);
|
||||
if ((hh->currentHeaderField.length())&&(hh->currentHeaderValue.length()))
|
||||
HttpPhyHandler* hh = reinterpret_cast<HttpPhyHandler*>(parser->data);
|
||||
if ((hh->currentHeaderField.length()) && (hh->currentHeaderValue.length()))
|
||||
(*hh->responseHeaders)[hh->currentHeaderField] = hh->currentHeaderValue;
|
||||
return 0;
|
||||
}
|
||||
static int ShttpOnBody(http_parser *parser,const char *ptr,size_t length)
|
||||
static int ShttpOnBody(http_parser* parser, const char* ptr, size_t length)
|
||||
{
|
||||
HttpPhyHandler *hh = reinterpret_cast<HttpPhyHandler *>(parser->data);
|
||||
HttpPhyHandler* hh = reinterpret_cast<HttpPhyHandler*>(parser->data);
|
||||
hh->messageSize += (unsigned long)length;
|
||||
if (hh->messageSize > hh->maxResponseSize)
|
||||
return -1;
|
||||
hh->responseBody->append(ptr,length);
|
||||
hh->responseBody->append(ptr, length);
|
||||
return 0;
|
||||
}
|
||||
static int ShttpOnMessageComplete(http_parser *parser)
|
||||
static int ShttpOnMessageComplete(http_parser* parser)
|
||||
{
|
||||
HttpPhyHandler *hh = reinterpret_cast<HttpPhyHandler *>(parser->data);
|
||||
HttpPhyHandler* hh = reinterpret_cast<HttpPhyHandler*>(parser->data);
|
||||
hh->phy->close(hh->sock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
} // anonymous namespace
|
||||
|
||||
unsigned int Http::_do(
|
||||
const char *method,
|
||||
const char* method,
|
||||
unsigned long maxResponseSize,
|
||||
unsigned long timeout,
|
||||
const struct sockaddr *remoteAddress,
|
||||
const char *path,
|
||||
const std::map<std::string,std::string> &requestHeaders,
|
||||
const void *requestBody,
|
||||
const struct sockaddr* remoteAddress,
|
||||
const char* path,
|
||||
const std::map<std::string, std::string>& requestHeaders,
|
||||
const void* requestBody,
|
||||
unsigned long requestBodyLength,
|
||||
std::map<std::string,std::string> &responseHeaders,
|
||||
std::string &responseBody)
|
||||
std::map<std::string, std::string>& responseHeaders,
|
||||
std::string& responseBody)
|
||||
{
|
||||
try {
|
||||
responseHeaders.clear();
|
||||
|
@ -223,31 +221,33 @@ unsigned int Http::_do(
|
|||
|
||||
HttpPhyHandler handler;
|
||||
|
||||
http_parser_init(&(handler.parser),HTTP_RESPONSE);
|
||||
handler.parser.data = (void *)&handler;
|
||||
http_parser_init(&(handler.parser), HTTP_RESPONSE);
|
||||
handler.parser.data = (void*)&handler;
|
||||
handler.messageSize = 0;
|
||||
handler.writePtr = 0;
|
||||
handler.lastActivity = OSUtils::now();
|
||||
|
||||
try {
|
||||
char tmp[1024];
|
||||
OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s %s HTTP/1.1\r\n",method,path);
|
||||
OSUtils::ztsnprintf(tmp, sizeof(tmp), "%s %s HTTP/1.1\r\n", method, path);
|
||||
handler.writeBuf.append(tmp);
|
||||
for(std::map<std::string,std::string>::const_iterator h(requestHeaders.begin());h!=requestHeaders.end();++h) {
|
||||
OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s: %s\r\n",h->first.c_str(),h->second.c_str());
|
||||
for (std::map<std::string, std::string>::const_iterator h(requestHeaders.begin()); h != requestHeaders.end(); ++h) {
|
||||
OSUtils::ztsnprintf(tmp, sizeof(tmp), "%s: %s\r\n", h->first.c_str(), h->second.c_str());
|
||||
handler.writeBuf.append(tmp);
|
||||
}
|
||||
handler.writeBuf.append("\r\n");
|
||||
if ((requestBody)&&(requestBodyLength))
|
||||
handler.writeBuf.append((const char *)requestBody,requestBodyLength);
|
||||
} catch ( ... ) {
|
||||
if ((requestBody) && (requestBodyLength))
|
||||
handler.writeBuf.append((const char*)requestBody, requestBodyLength);
|
||||
}
|
||||
catch (...) {
|
||||
responseBody = "request too large";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (maxResponseSize) {
|
||||
handler.maxResponseSize = maxResponseSize;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
handler.maxResponseSize = 2147483647;
|
||||
}
|
||||
handler.responseHeaders = &responseHeaders;
|
||||
|
@ -255,19 +255,19 @@ unsigned int Http::_do(
|
|||
handler.error = false;
|
||||
handler.done = false;
|
||||
|
||||
Phy<HttpPhyHandler *> phy(&handler,true,true);
|
||||
Phy<HttpPhyHandler*> phy(&handler, true, true);
|
||||
|
||||
bool instantConnect = false;
|
||||
handler.phy = &phy;
|
||||
handler.sock = phy.tcpConnect((const struct sockaddr *)remoteAddress,instantConnect,(void *)0,true);
|
||||
if (!handler.sock) {
|
||||
handler.sock = phy.tcpConnect((const struct sockaddr*)remoteAddress, instantConnect, (void*)0, true);
|
||||
if (! handler.sock) {
|
||||
responseBody = "connection failed (2)";
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (!handler.done) {
|
||||
while (! handler.done) {
|
||||
phy.poll(timeout / 2);
|
||||
if ((timeout)&&((unsigned long)(OSUtils::now() - handler.lastActivity) > timeout)) {
|
||||
if ((timeout) && ((unsigned long)(OSUtils::now() - handler.lastActivity) > timeout)) {
|
||||
phy.close(handler.sock);
|
||||
responseBody = "timed out";
|
||||
return 0;
|
||||
|
@ -275,13 +275,15 @@ unsigned int Http::_do(
|
|||
}
|
||||
|
||||
return ((handler.error) ? 0 : ((handler.parser.http_errno != HPE_OK) ? 0 : handler.parser.status_code));
|
||||
} catch (std::exception &exc) {
|
||||
}
|
||||
catch (std::exception& exc) {
|
||||
responseBody = exc.what();
|
||||
return 0;
|
||||
} catch ( ... ) {
|
||||
}
|
||||
catch (...) {
|
||||
responseBody = "unknown exception";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
|
141
osdep/Http.hpp
141
osdep/Http.hpp
|
@ -14,21 +14,21 @@
|
|||
#ifndef ZT_HTTP_HPP
|
||||
#define ZT_HTTP_HPP
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace ZeroTier {
|
||||
|
@ -36,9 +36,8 @@ namespace ZeroTier {
|
|||
/**
|
||||
* Simple synchronous HTTP client used for updater and cli
|
||||
*/
|
||||
class Http
|
||||
{
|
||||
public:
|
||||
class Http {
|
||||
public:
|
||||
/**
|
||||
* Make HTTP GET request
|
||||
*
|
||||
|
@ -46,26 +45,16 @@ public:
|
|||
*
|
||||
* @return HTTP status code or 0 on error (responseBody will contain error message)
|
||||
*/
|
||||
static inline unsigned int GET(
|
||||
unsigned long maxResponseSize,
|
||||
static inline unsigned int
|
||||
GET(unsigned long maxResponseSize,
|
||||
unsigned long timeout,
|
||||
const struct sockaddr *remoteAddress,
|
||||
const char *path,
|
||||
const std::map<std::string,std::string> &requestHeaders,
|
||||
std::map<std::string,std::string> &responseHeaders,
|
||||
std::string &responseBody)
|
||||
const struct sockaddr* remoteAddress,
|
||||
const char* path,
|
||||
const std::map<std::string, std::string>& requestHeaders,
|
||||
std::map<std::string, std::string>& responseHeaders,
|
||||
std::string& responseBody)
|
||||
{
|
||||
return _do(
|
||||
"GET",
|
||||
maxResponseSize,
|
||||
timeout,
|
||||
remoteAddress,
|
||||
path,
|
||||
requestHeaders,
|
||||
(const void *)0,
|
||||
0,
|
||||
responseHeaders,
|
||||
responseBody);
|
||||
return _do("GET", maxResponseSize, timeout, remoteAddress, path, requestHeaders, (const void*)0, 0, responseHeaders, responseBody);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,26 +64,16 @@ public:
|
|||
*
|
||||
* @return HTTP status code or 0 on error (responseBody will contain error message)
|
||||
*/
|
||||
static inline unsigned int DEL(
|
||||
unsigned long maxResponseSize,
|
||||
static inline unsigned int
|
||||
DEL(unsigned long maxResponseSize,
|
||||
unsigned long timeout,
|
||||
const struct sockaddr *remoteAddress,
|
||||
const char *path,
|
||||
const std::map<std::string,std::string> &requestHeaders,
|
||||
std::map<std::string,std::string> &responseHeaders,
|
||||
std::string &responseBody)
|
||||
const struct sockaddr* remoteAddress,
|
||||
const char* path,
|
||||
const std::map<std::string, std::string>& requestHeaders,
|
||||
std::map<std::string, std::string>& responseHeaders,
|
||||
std::string& responseBody)
|
||||
{
|
||||
return _do(
|
||||
"DELETE",
|
||||
maxResponseSize,
|
||||
timeout,
|
||||
remoteAddress,
|
||||
path,
|
||||
requestHeaders,
|
||||
(const void *)0,
|
||||
0,
|
||||
responseHeaders,
|
||||
responseBody);
|
||||
return _do("DELETE", maxResponseSize, timeout, remoteAddress, path, requestHeaders, (const void*)0, 0, responseHeaders, responseBody);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,25 +88,15 @@ public:
|
|||
static inline unsigned int POST(
|
||||
unsigned long maxResponseSize,
|
||||
unsigned long timeout,
|
||||
const struct sockaddr *remoteAddress,
|
||||
const char *path,
|
||||
const std::map<std::string,std::string> &requestHeaders,
|
||||
const void *postData,
|
||||
const struct sockaddr* remoteAddress,
|
||||
const char* path,
|
||||
const std::map<std::string, std::string>& requestHeaders,
|
||||
const void* postData,
|
||||
unsigned long postDataLength,
|
||||
std::map<std::string,std::string> &responseHeaders,
|
||||
std::string &responseBody)
|
||||
std::map<std::string, std::string>& responseHeaders,
|
||||
std::string& responseBody)
|
||||
{
|
||||
return _do(
|
||||
"POST",
|
||||
maxResponseSize,
|
||||
timeout,
|
||||
remoteAddress,
|
||||
path,
|
||||
requestHeaders,
|
||||
postData,
|
||||
postDataLength,
|
||||
responseHeaders,
|
||||
responseBody);
|
||||
return _do("POST", maxResponseSize, timeout, remoteAddress, path, requestHeaders, postData, postDataLength, responseHeaders, responseBody);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -139,44 +108,34 @@ public:
|
|||
*
|
||||
* @return HTTP status code or 0 on error (responseBody will contain error message)
|
||||
*/
|
||||
static inline unsigned int PUT(
|
||||
unsigned long maxResponseSize,
|
||||
static inline unsigned int
|
||||
PUT(unsigned long maxResponseSize,
|
||||
unsigned long timeout,
|
||||
const struct sockaddr *remoteAddress,
|
||||
const char *path,
|
||||
const std::map<std::string,std::string> &requestHeaders,
|
||||
const void *postData,
|
||||
const struct sockaddr* remoteAddress,
|
||||
const char* path,
|
||||
const std::map<std::string, std::string>& requestHeaders,
|
||||
const void* postData,
|
||||
unsigned long postDataLength,
|
||||
std::map<std::string,std::string> &responseHeaders,
|
||||
std::string &responseBody)
|
||||
std::map<std::string, std::string>& responseHeaders,
|
||||
std::string& responseBody)
|
||||
{
|
||||
return _do(
|
||||
"PUT",
|
||||
maxResponseSize,
|
||||
timeout,
|
||||
remoteAddress,
|
||||
path,
|
||||
requestHeaders,
|
||||
postData,
|
||||
postDataLength,
|
||||
responseHeaders,
|
||||
responseBody);
|
||||
return _do("PUT", maxResponseSize, timeout, remoteAddress, path, requestHeaders, postData, postDataLength, responseHeaders, responseBody);
|
||||
}
|
||||
|
||||
private:
|
||||
static unsigned int _do(
|
||||
const char *method,
|
||||
private:
|
||||
static unsigned int
|
||||
_do(const char* method,
|
||||
unsigned long maxResponseSize,
|
||||
unsigned long timeout,
|
||||
const struct sockaddr *remoteAddress,
|
||||
const char *path,
|
||||
const std::map<std::string,std::string> &requestHeaders,
|
||||
const void *requestBody,
|
||||
const struct sockaddr* remoteAddress,
|
||||
const char* path,
|
||||
const std::map<std::string, std::string>& requestHeaders,
|
||||
const void* requestBody,
|
||||
unsigned long requestBodyLength,
|
||||
std::map<std::string,std::string> &responseHeaders,
|
||||
std::string &responseBody);
|
||||
std::map<std::string, std::string>& responseHeaders,
|
||||
std::string& responseBody);
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,42 +19,39 @@
|
|||
|
||||
#ifdef __LINUX__
|
||||
|
||||
#include "../node/Utils.hpp"
|
||||
#include "../node/Mutex.hpp"
|
||||
#include "../node/Dictionary.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
#include "../node/Mutex.hpp"
|
||||
#include "../node/Utils.hpp"
|
||||
#include "LinuxEthernetTap.hpp"
|
||||
#include "LinuxNetLink.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <arpa/inet.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_addr.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <netinet/in.h>
|
||||
#include <signal.h>
|
||||
#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 <algorithm>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <utility>
|
||||
|
||||
#ifndef IFNAMSIZ
|
||||
#define IFNAMSIZ 16
|
||||
|
@ -63,7 +60,7 @@
|
|||
#define ZT_TAP_BUF_SIZE (1024 * 16)
|
||||
|
||||
// ff:ff:ff:ff:ff:ff with no ADI
|
||||
static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff),0);
|
||||
static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff), 0);
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -72,9 +69,10 @@ namespace ZeroTier {
|
|||
// the tap devices.
|
||||
//
|
||||
// Returns true if the kernel major version is < 3
|
||||
bool isOldLinuxKernel() {
|
||||
bool isOldLinuxKernel()
|
||||
{
|
||||
struct utsname buffer;
|
||||
char *p;
|
||||
char* p;
|
||||
long ver[16];
|
||||
int i = 0;
|
||||
if (uname(&buffer) != 0) {
|
||||
|
@ -84,20 +82,21 @@ bool isOldLinuxKernel() {
|
|||
|
||||
p = buffer.release;
|
||||
|
||||
while (*p) {
|
||||
if (isdigit(*p)) {
|
||||
ver[i] = strtol(p, &p, 10);
|
||||
i++;
|
||||
} else {
|
||||
p++;
|
||||
}
|
||||
}
|
||||
while (*p) {
|
||||
if (isdigit(*p)) {
|
||||
ver[i] = strtol(p, &p, 10);
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
return ver[0] < 3;
|
||||
}
|
||||
|
||||
static const char _base32_chars[32] = { 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','2','3','4','5','6','7' };
|
||||
static void _base32_5_to_8(const uint8_t *in,char *out)
|
||||
static const char _base32_chars[32] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '2', '3', '4', '5', '6', '7' };
|
||||
static void _base32_5_to_8(const uint8_t* in, char* out)
|
||||
{
|
||||
out[0] = _base32_chars[(in[0]) >> 3];
|
||||
out[1] = _base32_chars[(in[0] & 0x07) << 2 | (in[1] & 0xc0) >> 6];
|
||||
|
@ -110,87 +109,89 @@ static void _base32_5_to_8(const uint8_t *in,char *out)
|
|||
}
|
||||
|
||||
LinuxEthernetTap::LinuxEthernetTap(
|
||||
const char *homePath,
|
||||
const char* homePath,
|
||||
unsigned int concurrency,
|
||||
bool pinning,
|
||||
const MAC &mac,
|
||||
const MAC& mac,
|
||||
unsigned int mtu,
|
||||
unsigned int metric,
|
||||
uint64_t nwid,
|
||||
const char *friendlyName,
|
||||
void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
|
||||
void *arg) :
|
||||
_handler(handler),
|
||||
_arg(arg),
|
||||
_nwid(nwid),
|
||||
_mac(mac),
|
||||
_homePath(homePath),
|
||||
_mtu(mtu),
|
||||
_fd(0),
|
||||
_enabled(true),
|
||||
_run(true),
|
||||
_lastIfAddrsUpdate(0)
|
||||
const char* friendlyName,
|
||||
void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
|
||||
void* arg)
|
||||
: _handler(handler)
|
||||
, _arg(arg)
|
||||
, _nwid(nwid)
|
||||
, _mac(mac)
|
||||
, _homePath(homePath)
|
||||
, _mtu(mtu)
|
||||
, _fd(0)
|
||||
, _enabled(true)
|
||||
, _run(true)
|
||||
, _lastIfAddrsUpdate(0)
|
||||
{
|
||||
static std::mutex s_tapCreateLock;
|
||||
char procpath[128],nwids[32];
|
||||
char procpath[128], nwids[32];
|
||||
struct stat sbuf;
|
||||
|
||||
|
||||
// Create only one tap at a time globally.
|
||||
std::lock_guard<std::mutex> tapCreateLock(s_tapCreateLock);
|
||||
|
||||
// Make sure Linux netlink is initialized.
|
||||
(void)LinuxNetLink::getInstance();
|
||||
|
||||
OSUtils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid);
|
||||
OSUtils::ztsnprintf(nwids, sizeof(nwids), "%.16llx", nwid);
|
||||
|
||||
_fd = ::open("/dev/net/tun",O_RDWR);
|
||||
_fd = ::open("/dev/net/tun", O_RDWR);
|
||||
if (_fd <= 0) {
|
||||
_fd = ::open("/dev/tun",O_RDWR);
|
||||
_fd = ::open("/dev/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));
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
|
||||
// Restore device names from legacy devicemap, but for new devices we use a base32-based
|
||||
// canonical device name.
|
||||
std::map<std::string,std::string> globalDeviceMap;
|
||||
FILE *devmapf = fopen((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(),"r");
|
||||
std::map<std::string, std::string> globalDeviceMap;
|
||||
FILE* devmapf = fopen((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(), "r");
|
||||
if (devmapf) {
|
||||
char buf[256];
|
||||
while (fgets(buf,sizeof(buf),devmapf)) {
|
||||
char *x = (char *)0;
|
||||
char *y = (char *)0;
|
||||
char *saveptr = (char *)0;
|
||||
for(char *f=Utils::stok(buf,"\r\n=",&saveptr);(f);f=Utils::stok((char *)0,"\r\n=",&saveptr)) {
|
||||
if (!x) x = f;
|
||||
else if (!y) y = f;
|
||||
else break;
|
||||
while (fgets(buf, sizeof(buf), devmapf)) {
|
||||
char* x = (char*)0;
|
||||
char* y = (char*)0;
|
||||
char* saveptr = (char*)0;
|
||||
for (char* f = Utils::stok(buf, "\r\n=", &saveptr); (f); f = Utils::stok((char*)0, "\r\n=", &saveptr)) {
|
||||
if (! x)
|
||||
x = f;
|
||||
else if (! y)
|
||||
y = f;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if ((x)&&(y)&&(x[0])&&(y[0]))
|
||||
if ((x) && (y) && (x[0]) && (y[0]))
|
||||
globalDeviceMap[x] = y;
|
||||
}
|
||||
fclose(devmapf);
|
||||
}
|
||||
bool recalledDevice = false;
|
||||
std::map<std::string,std::string>::const_iterator gdmEntry = globalDeviceMap.find(nwids);
|
||||
std::map<std::string, std::string>::const_iterator gdmEntry = globalDeviceMap.find(nwids);
|
||||
if (gdmEntry != globalDeviceMap.end()) {
|
||||
Utils::scopy(ifr.ifr_name,sizeof(ifr.ifr_name),gdmEntry->second.c_str());
|
||||
OSUtils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name);
|
||||
recalledDevice = (stat(procpath,&sbuf) != 0);
|
||||
Utils::scopy(ifr.ifr_name, sizeof(ifr.ifr_name), gdmEntry->second.c_str());
|
||||
OSUtils::ztsnprintf(procpath, sizeof(procpath), "/proc/sys/net/ipv4/conf/%s", ifr.ifr_name);
|
||||
recalledDevice = (stat(procpath, &sbuf) != 0);
|
||||
}
|
||||
|
||||
if (!recalledDevice) {
|
||||
if (! recalledDevice) {
|
||||
#ifdef __SYNOLOGY__
|
||||
int devno = 50;
|
||||
do {
|
||||
OSUtils::ztsnprintf(ifr.ifr_name,sizeof(ifr.ifr_name),"eth%d",devno++);
|
||||
OSUtils::ztsnprintf(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
|
||||
OSUtils::ztsnprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "eth%d", devno++);
|
||||
OSUtils::ztsnprintf(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
|
||||
#else
|
||||
uint64_t trial = 0; // incremented in the very unlikely event of a name collision with another network
|
||||
uint64_t trial = 0; // incremented in the very unlikely event of a name collision with another network
|
||||
do {
|
||||
const uint64_t nwid40 = (nwid ^ (nwid >> 24)) + trial++;
|
||||
uint8_t tmp2[5];
|
||||
|
@ -202,29 +203,28 @@ LinuxEthernetTap::LinuxEthernetTap(
|
|||
tmp2[4] = (uint8_t)(nwid40 & 0xff);
|
||||
tmp3[0] = 'z';
|
||||
tmp3[1] = 't';
|
||||
_base32_5_to_8(tmp2,tmp3 + 2);
|
||||
_base32_5_to_8(tmp2, tmp3 + 2);
|
||||
tmp3[10] = (char)0;
|
||||
memcpy(ifr.ifr_name,tmp3,11);
|
||||
OSUtils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name);
|
||||
} while (stat(procpath,&sbuf) == 0);
|
||||
memcpy(ifr.ifr_name, tmp3, 11);
|
||||
OSUtils::ztsnprintf(procpath, sizeof(procpath), "/proc/sys/net/ipv4/conf/%s", ifr.ifr_name);
|
||||
} while (stat(procpath, &sbuf) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
|
||||
if (ioctl(_fd,TUNSETIFF,(void *)&ifr) < 0) {
|
||||
if (ioctl(_fd, TUNSETIFF, (void*)&ifr) < 0) {
|
||||
::close(_fd);
|
||||
throw std::runtime_error("unable to configure TUN/TAP device for TAP operation");
|
||||
}
|
||||
|
||||
::ioctl(_fd,TUNSETPERSIST,0); // valgrind may generate a false alarm here
|
||||
::ioctl(_fd, TUNSETPERSIST, 0); // valgrind may generate a false alarm here
|
||||
_dev = ifr.ifr_name;
|
||||
::fcntl(_fd,F_SETFD,fcntl(_fd,F_GETFD) | FD_CLOEXEC);
|
||||
::fcntl(_fd, F_SETFD, fcntl(_fd, F_GETFD) | FD_CLOEXEC);
|
||||
|
||||
(void)::pipe(_shutdownSignalPipe);
|
||||
|
||||
for (unsigned int i = 0; i < concurrency; ++i) {
|
||||
_rxThreads.push_back(std::thread([this, i, concurrency, pinning] {
|
||||
|
||||
if (pinning) {
|
||||
int pinCore = i % concurrency;
|
||||
fprintf(stderr, "Pinning tap thread %d to core %d\n", i, pinCore);
|
||||
|
@ -233,8 +233,7 @@ LinuxEthernetTap::LinuxEthernetTap(
|
|||
CPU_ZERO(&cpuset);
|
||||
CPU_SET(pinCore, &cpuset);
|
||||
int rc = pthread_setaffinity_np(self, sizeof(cpu_set_t), &cpuset);
|
||||
if (rc != 0)
|
||||
{
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "Failed to pin tap thread %d to core %d: %s\n", i, pinCore, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
@ -364,11 +363,11 @@ LinuxEthernetTap::LinuxEthernetTap(
|
|||
LinuxEthernetTap::~LinuxEthernetTap()
|
||||
{
|
||||
_run = false;
|
||||
(void)::write(_shutdownSignalPipe[1],"\0",1);
|
||||
(void)::write(_shutdownSignalPipe[1], "\0", 1);
|
||||
::close(_fd);
|
||||
::close(_shutdownSignalPipe[0]);
|
||||
::close(_shutdownSignalPipe[1]);
|
||||
for (std::thread &t : _rxThreads) {
|
||||
for (std::thread& t : _rxThreads) {
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
|
@ -383,7 +382,7 @@ bool LinuxEthernetTap::enabled() const
|
|||
return _enabled;
|
||||
}
|
||||
|
||||
static bool ___removeIp(const std::string &_dev,const InetAddress &ip)
|
||||
static bool ___removeIp(const std::string& _dev, const InetAddress& ip)
|
||||
{
|
||||
LinuxNetLink::getInstance().removeAddress(ip, _dev.c_str());
|
||||
return true;
|
||||
|
@ -392,55 +391,54 @@ static bool ___removeIp(const std::string &_dev,const InetAddress &ip)
|
|||
bool LinuxEthernetTap::addIps(std::vector<InetAddress> ips)
|
||||
{
|
||||
#ifdef __SYNOLOGY__
|
||||
std::string filepath = "/etc/sysconfig/network-scripts/ifcfg-"+_dev;
|
||||
std::string cfg_contents = "DEVICE="+_dev+"\nBOOTPROTO=static";
|
||||
int ip4=0,ip6=0,ip4_tot=0,ip6_tot=0;
|
||||
std::string filepath = "/etc/sysconfig/network-scripts/ifcfg-" + _dev;
|
||||
std::string cfg_contents = "DEVICE=" + _dev + "\nBOOTPROTO=static";
|
||||
int ip4 = 0, ip6 = 0, ip4_tot = 0, ip6_tot = 0;
|
||||
|
||||
for(int i=0; i<(int)ips.size(); i++) {
|
||||
for (int i = 0; i < (int)ips.size(); i++) {
|
||||
if (ips[i].isV4())
|
||||
ip4_tot++;
|
||||
else
|
||||
ip6_tot++;
|
||||
}
|
||||
// Assemble and write contents of ifcfg-dev file
|
||||
for(int i=0; i<(int)ips.size(); i++) {
|
||||
for (int i = 0; i < (int)ips.size(); i++) {
|
||||
if (ips[i].isV4()) {
|
||||
char iptmp[64],iptmp2[64];
|
||||
char iptmp[64], iptmp2[64];
|
||||
std::string numstr4 = ip4_tot > 1 ? std::to_string(ip4) : "";
|
||||
cfg_contents += "\nIPADDR"+numstr4+"="+ips[i].toIpString(iptmp)
|
||||
+ "\nNETMASK"+numstr4+"="+ips[i].netmask().toIpString(iptmp2)+"\n";
|
||||
cfg_contents += "\nIPADDR" + numstr4 + "=" + ips[i].toIpString(iptmp) + "\nNETMASK" + numstr4 + "=" + ips[i].netmask().toIpString(iptmp2) + "\n";
|
||||
ip4++;
|
||||
} else {
|
||||
char iptmp[64],iptmp2[64];
|
||||
}
|
||||
else {
|
||||
char iptmp[64], iptmp2[64];
|
||||
std::string numstr6 = ip6_tot > 1 ? std::to_string(ip6) : "";
|
||||
cfg_contents += "\nIPV6ADDR"+numstr6+"="+ips[i].toIpString(iptmp)
|
||||
+ "\nNETMASK"+numstr6+"="+ips[i].netmask().toIpString(iptmp2)+"\n";
|
||||
cfg_contents += "\nIPV6ADDR" + numstr6 + "=" + ips[i].toIpString(iptmp) + "\nNETMASK" + numstr6 + "=" + ips[i].netmask().toIpString(iptmp2) + "\n";
|
||||
ip6++;
|
||||
}
|
||||
}
|
||||
OSUtils::writeFile(filepath.c_str(), cfg_contents.c_str(), cfg_contents.length());
|
||||
// Finally, add IPs
|
||||
for(int i=0; i<(int)ips.size(); i++){
|
||||
for (int i = 0; i < (int)ips.size(); i++) {
|
||||
LinuxNetLink::getInstance().addAddress(ips[i], _dev.c_str());
|
||||
}
|
||||
return true;
|
||||
#endif // __SYNOLOGY__
|
||||
#endif // __SYNOLOGY__
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LinuxEthernetTap::addIp(const InetAddress &ip)
|
||||
bool LinuxEthernetTap::addIp(const InetAddress& ip)
|
||||
{
|
||||
if (!ip)
|
||||
if (! ip)
|
||||
return false;
|
||||
|
||||
std::vector<InetAddress> allIps(ips());
|
||||
if (std::binary_search(allIps.begin(),allIps.end(),ip))
|
||||
if (std::binary_search(allIps.begin(), allIps.end(), ip))
|
||||
return true;
|
||||
|
||||
// Remove and reconfigure if address is the same but netmask is different
|
||||
for(std::vector<InetAddress>::iterator i(allIps.begin());i!=allIps.end();++i) {
|
||||
for (std::vector<InetAddress>::iterator i(allIps.begin()); i != allIps.end(); ++i) {
|
||||
if (i->ipsEqual(ip))
|
||||
___removeIp(_dev,*i);
|
||||
___removeIp(_dev, *i);
|
||||
}
|
||||
|
||||
LinuxNetLink::getInstance().addAddress(ip, _dev.c_str());
|
||||
|
@ -448,13 +446,13 @@ bool LinuxEthernetTap::addIp(const InetAddress &ip)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool LinuxEthernetTap::removeIp(const InetAddress &ip)
|
||||
bool LinuxEthernetTap::removeIp(const InetAddress& ip)
|
||||
{
|
||||
if (!ip)
|
||||
if (! ip)
|
||||
return true;
|
||||
std::vector<InetAddress> allIps(ips());
|
||||
if (std::find(allIps.begin(),allIps.end(),ip) != allIps.end()) {
|
||||
if (___removeIp(_dev,ip))
|
||||
if (std::find(allIps.begin(), allIps.end(), ip) != allIps.end()) {
|
||||
if (___removeIp(_dev, ip))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -462,7 +460,6 @@ bool LinuxEthernetTap::removeIp(const InetAddress &ip)
|
|||
|
||||
std::vector<InetAddress> LinuxEthernetTap::ips() const
|
||||
{
|
||||
|
||||
uint64_t now = OSUtils::now();
|
||||
|
||||
if ((now - _lastIfAddrsUpdate) <= GETIFADDRS_CACHE_TIME) {
|
||||
|
@ -470,28 +467,28 @@ std::vector<InetAddress> LinuxEthernetTap::ips() const
|
|||
}
|
||||
_lastIfAddrsUpdate = now;
|
||||
|
||||
struct ifaddrs *ifa = (struct ifaddrs *)0;
|
||||
struct ifaddrs* ifa = (struct ifaddrs*)0;
|
||||
if (getifaddrs(&ifa))
|
||||
return std::vector<InetAddress>();
|
||||
|
||||
std::vector<InetAddress> r;
|
||||
|
||||
struct ifaddrs *p = ifa;
|
||||
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) {
|
||||
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.push_back(InetAddress(&(sin->sin_addr.s_addr),4,Utils::countBits((uint32_t)nm->sin_addr.s_addr)));
|
||||
} break;
|
||||
struct sockaddr_in* sin = (struct sockaddr_in*)p->ifa_addr;
|
||||
struct sockaddr_in* nm = (struct sockaddr_in*)p->ifa_netmask;
|
||||
r.push_back(InetAddress(&(sin->sin_addr.s_addr), 4, Utils::countBits((uint32_t)nm->sin_addr.s_addr)));
|
||||
} break;
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *sin = (struct sockaddr_in6 *)p->ifa_addr;
|
||||
struct sockaddr_in6 *nm = (struct sockaddr_in6 *)p->ifa_netmask;
|
||||
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.push_back(InetAddress(sin->sin6_addr.s6_addr,16,Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3])));
|
||||
} break;
|
||||
memcpy(b, nm->sin6_addr.s6_addr, sizeof(b));
|
||||
r.push_back(InetAddress(sin->sin6_addr.s6_addr, 16, Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3])));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
p = p->ifa_next;
|
||||
|
@ -500,24 +497,24 @@ std::vector<InetAddress> LinuxEthernetTap::ips() const
|
|||
if (ifa)
|
||||
freeifaddrs(ifa);
|
||||
|
||||
std::sort(r.begin(),r.end());
|
||||
r.erase(std::unique(r.begin(),r.end()),r.end());
|
||||
std::sort(r.begin(), r.end());
|
||||
r.erase(std::unique(r.begin(), r.end()), r.end());
|
||||
|
||||
_ifaddrs = r;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void LinuxEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
|
||||
void LinuxEthernetTap::put(const MAC& from, const MAC& to, unsigned int etherType, const void* data, unsigned int len)
|
||||
{
|
||||
char putBuf[ZT_MAX_MTU + 64];
|
||||
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);
|
||||
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;
|
||||
(void)::write(_fd,putBuf,len);
|
||||
(void)::write(_fd, putBuf, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -526,53 +523,53 @@ std::string LinuxEthernetTap::deviceName() const
|
|||
return _dev;
|
||||
}
|
||||
|
||||
void LinuxEthernetTap::setFriendlyName(const char *friendlyName)
|
||||
void LinuxEthernetTap::setFriendlyName(const char* friendlyName)
|
||||
{
|
||||
}
|
||||
|
||||
void LinuxEthernetTap::scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed)
|
||||
void LinuxEthernetTap::scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed)
|
||||
{
|
||||
char *ptr,*ptr2;
|
||||
char *ptr, *ptr2;
|
||||
unsigned char mac[6];
|
||||
std::vector<MulticastGroup> newGroups;
|
||||
|
||||
int fd = ::open("/proc/net/dev_mcast",O_RDONLY);
|
||||
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))) {
|
||||
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)) {
|
||||
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)) {
|
||||
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.push_back(MulticastGroup(MAC(mac,6),0));
|
||||
if ((devname) && (! strcmp(devname, _dev.c_str())) && (mcastmac) && (Utils::unhex(mcastmac, mac, 6) == 6))
|
||||
newGroups.push_back(MulticastGroup(MAC(mac, 6), 0));
|
||||
}
|
||||
}
|
||||
::close(fd);
|
||||
}
|
||||
|
||||
std::vector<InetAddress> allIps(ips());
|
||||
for(std::vector<InetAddress>::iterator ip(allIps.begin());ip!=allIps.end();++ip)
|
||||
for (std::vector<InetAddress>::iterator ip(allIps.begin()); ip != allIps.end(); ++ip)
|
||||
newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip));
|
||||
|
||||
std::sort(newGroups.begin(),newGroups.end());
|
||||
newGroups.erase(std::unique(newGroups.begin(),newGroups.end()),newGroups.end());
|
||||
std::sort(newGroups.begin(), newGroups.end());
|
||||
newGroups.erase(std::unique(newGroups.begin(), newGroups.end()), newGroups.end());
|
||||
|
||||
for(std::vector<MulticastGroup>::iterator m(newGroups.begin());m!=newGroups.end();++m) {
|
||||
if (!std::binary_search(_multicastGroups.begin(),_multicastGroups.end(),*m))
|
||||
for (std::vector<MulticastGroup>::iterator m(newGroups.begin()); m != newGroups.end(); ++m) {
|
||||
if (! std::binary_search(_multicastGroups.begin(), _multicastGroups.end(), *m))
|
||||
added.push_back(*m);
|
||||
}
|
||||
for(std::vector<MulticastGroup>::iterator m(_multicastGroups.begin());m!=_multicastGroups.end();++m) {
|
||||
if (!std::binary_search(newGroups.begin(),newGroups.end(),*m))
|
||||
for (std::vector<MulticastGroup>::iterator m(_multicastGroups.begin()); m != _multicastGroups.end(); ++m) {
|
||||
if (! std::binary_search(newGroups.begin(), newGroups.end(), *m))
|
||||
removed.push_back(*m);
|
||||
}
|
||||
|
||||
|
@ -583,13 +580,13 @@ void LinuxEthernetTap::setMtu(unsigned int mtu)
|
|||
{
|
||||
if (_mtu != mtu) {
|
||||
_mtu = mtu;
|
||||
int sock = socket(AF_INET,SOCK_DGRAM,0);
|
||||
int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock > 0) {
|
||||
struct ifreq ifr;
|
||||
memset(&ifr,0,sizeof(ifr));
|
||||
strcpy(ifr.ifr_name,_dev.c_str());
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strcpy(ifr.ifr_name, _dev.c_str());
|
||||
ifr.ifr_ifru.ifru_mtu = (int)mtu;
|
||||
if (ioctl(sock,SIOCSIFMTU,(void *)&ifr) < 0) {
|
||||
if (ioctl(sock, SIOCSIFMTU, (void*)&ifr) < 0) {
|
||||
printf("WARNING: ioctl() failed updating existing Linux tap device (set MTU)\n");
|
||||
}
|
||||
close(sock);
|
||||
|
@ -597,6 +594,6 @@ void LinuxEthernetTap::setMtu(unsigned int mtu)
|
|||
}
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif // __LINUX__
|
||||
#endif // __LINUX__
|
||||
|
|
|
@ -14,55 +14,56 @@
|
|||
#ifndef ZT_LINUXETHERNETTAP_HPP
|
||||
#define ZT_LINUXETHERNETTAP_HPP
|
||||
|
||||
#include "../node/MulticastGroup.hpp"
|
||||
#include "BlockingQueue.hpp"
|
||||
#include "EthernetTap.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <atomic>
|
||||
#include <array>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include "../node/MulticastGroup.hpp"
|
||||
#include "EthernetTap.hpp"
|
||||
#include "BlockingQueue.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class LinuxEthernetTap : public EthernetTap
|
||||
{
|
||||
public:
|
||||
class LinuxEthernetTap : public EthernetTap {
|
||||
public:
|
||||
LinuxEthernetTap(
|
||||
const char *homePath,
|
||||
const char* homePath,
|
||||
unsigned int concurrency,
|
||||
bool pinning,
|
||||
const MAC &mac,
|
||||
const MAC& mac,
|
||||
unsigned int mtu,
|
||||
unsigned int metric,
|
||||
uint64_t nwid,
|
||||
const char *friendlyName,
|
||||
void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
|
||||
void *arg);
|
||||
const char* friendlyName,
|
||||
void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
|
||||
void* arg);
|
||||
|
||||
virtual ~LinuxEthernetTap();
|
||||
|
||||
virtual void setEnabled(bool en);
|
||||
virtual bool enabled() const;
|
||||
virtual bool addIp(const InetAddress &ip);
|
||||
virtual bool addIp(const InetAddress& ip);
|
||||
virtual bool addIps(std::vector<InetAddress> ips);
|
||||
virtual bool removeIp(const InetAddress &ip);
|
||||
virtual bool removeIp(const InetAddress& ip);
|
||||
virtual std::vector<InetAddress> ips() const;
|
||||
virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len);
|
||||
virtual void put(const MAC& from, const MAC& to, unsigned int etherType, const void* data, unsigned int len);
|
||||
virtual std::string deviceName() const;
|
||||
virtual void setFriendlyName(const char *friendlyName);
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
|
||||
virtual void setFriendlyName(const char* friendlyName);
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed);
|
||||
virtual void setMtu(unsigned int mtu);
|
||||
virtual void setDns(const char *domain, const std::vector<InetAddress> &servers) {}
|
||||
virtual void setDns(const char* domain, const std::vector<InetAddress>& servers)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
void (*_handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
|
||||
void *_arg;
|
||||
private:
|
||||
void (*_handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int);
|
||||
void* _arg;
|
||||
uint64_t _nwid;
|
||||
MAC _mac;
|
||||
std::string _homePath;
|
||||
|
@ -78,6 +79,6 @@ private:
|
|||
std::vector<std::thread> _rxThreads;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -18,68 +18,77 @@
|
|||
|
||||
#ifdef __LINUX__
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <asm/types.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <sys/socket.h>
|
||||
//#include <linux/if.h>
|
||||
#include <vector>
|
||||
// #include <linux/if.h>
|
||||
|
||||
#include "../node/Hashtable.hpp"
|
||||
#include "../node/InetAddress.hpp"
|
||||
#include "../node/MAC.hpp"
|
||||
#include "Thread.hpp"
|
||||
#include "../node/Hashtable.hpp"
|
||||
#include "../node/Mutex.hpp"
|
||||
|
||||
#include "Thread.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* Interface with Linux's RTNETLINK
|
||||
*/
|
||||
class LinuxNetLink
|
||||
{
|
||||
private:
|
||||
class LinuxNetLink {
|
||||
private:
|
||||
LinuxNetLink();
|
||||
~LinuxNetLink();
|
||||
|
||||
public:
|
||||
public:
|
||||
struct Route {
|
||||
InetAddress target;
|
||||
InetAddress via;
|
||||
InetAddress src;
|
||||
int ifidx;
|
||||
|
||||
inline bool operator==(const Route &r) const
|
||||
{ return ((target == r.target)&&(via == r.via)&&(src == r.src)&&(ifidx == r.ifidx)); }
|
||||
inline bool operator!=(const Route &r) const
|
||||
{ return (!(*this == r)); }
|
||||
inline bool operator<(const Route &r) const
|
||||
inline bool operator==(const Route& r) const
|
||||
{
|
||||
return ((target == r.target) && (via == r.via) && (src == r.src) && (ifidx == r.ifidx));
|
||||
}
|
||||
inline bool operator!=(const Route& r) const
|
||||
{
|
||||
return (! (*this == r));
|
||||
}
|
||||
inline bool operator<(const Route& r) const
|
||||
{
|
||||
if (target < r.target) {
|
||||
return true;
|
||||
} else if (target == r.target) {
|
||||
}
|
||||
else if (target == r.target) {
|
||||
if (via < r.via) {
|
||||
return true;
|
||||
} else if (via == r.via) {
|
||||
}
|
||||
else if (via == r.via) {
|
||||
if (src < r.src) {
|
||||
return true;
|
||||
} else if (src == r.src) {
|
||||
}
|
||||
else if (src == r.src) {
|
||||
return (ifidx < r.ifidx);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
inline bool operator>(const Route &r) const
|
||||
{ return (r < *this); }
|
||||
inline bool operator<=(const Route &r) const
|
||||
{ return !(r < *this); }
|
||||
inline bool operator>=(const Route &r) const
|
||||
{ return !(*this < r); }
|
||||
inline bool operator>(const Route& r) const
|
||||
{
|
||||
return (r < *this);
|
||||
}
|
||||
inline bool operator<=(const Route& r) const
|
||||
{
|
||||
return ! (r < *this);
|
||||
}
|
||||
inline bool operator>=(const Route& r) const
|
||||
{
|
||||
return ! (*this < r);
|
||||
}
|
||||
};
|
||||
|
||||
static LinuxNetLink& getInstance()
|
||||
|
@ -91,32 +100,32 @@ public:
|
|||
LinuxNetLink(LinuxNetLink const&) = delete;
|
||||
void operator=(LinuxNetLink const&) = delete;
|
||||
|
||||
void addRoute(const InetAddress &target, const InetAddress &via, const InetAddress &src, const char *ifaceName);
|
||||
void delRoute(const InetAddress &target, const InetAddress &via, const InetAddress &src, const char *ifaceName);
|
||||
void addRoute(const InetAddress& target, const InetAddress& via, const InetAddress& src, const char* ifaceName);
|
||||
void delRoute(const InetAddress& target, const InetAddress& via, const InetAddress& src, const char* ifaceName);
|
||||
|
||||
void addAddress(const InetAddress &addr, const char *iface);
|
||||
void removeAddress(const InetAddress &addr, const char *iface);
|
||||
void addAddress(const InetAddress& addr, const char* iface);
|
||||
void removeAddress(const InetAddress& addr, const char* iface);
|
||||
|
||||
bool routeIsSet(const InetAddress &target, const InetAddress &via, const InetAddress &src, const char *ifname);
|
||||
bool routeIsSet(const InetAddress& target, const InetAddress& via, const InetAddress& src, const char* ifname);
|
||||
|
||||
void threadMain() throw();
|
||||
|
||||
private:
|
||||
private:
|
||||
int _doRecv(int fd);
|
||||
|
||||
void _processMessage(struct nlmsghdr *nlp, int nll);
|
||||
void _routeAdded(struct nlmsghdr *nlp);
|
||||
void _routeDeleted(struct nlmsghdr *nlp);
|
||||
void _linkAdded(struct nlmsghdr *nlp);
|
||||
void _linkDeleted(struct nlmsghdr *nlp);
|
||||
void _ipAddressAdded(struct nlmsghdr *nlp);
|
||||
void _ipAddressDeleted(struct nlmsghdr *nlp);
|
||||
void _processMessage(struct nlmsghdr* nlp, int nll);
|
||||
void _routeAdded(struct nlmsghdr* nlp);
|
||||
void _routeDeleted(struct nlmsghdr* nlp);
|
||||
void _linkAdded(struct nlmsghdr* nlp);
|
||||
void _linkDeleted(struct nlmsghdr* nlp);
|
||||
void _ipAddressAdded(struct nlmsghdr* nlp);
|
||||
void _ipAddressDeleted(struct nlmsghdr* nlp);
|
||||
|
||||
void _requestInterfaceList();
|
||||
void _requestIPv4Routes();
|
||||
void _requestIPv6Routes();
|
||||
|
||||
int _indexForInterface(const char *iface);
|
||||
int _indexForInterface(const char* iface);
|
||||
|
||||
void _setSocketTimeout(int fd, int seconds = 1);
|
||||
|
||||
|
@ -125,14 +134,16 @@ private:
|
|||
|
||||
uint32_t _seq;
|
||||
|
||||
std::map< InetAddress,std::set<LinuxNetLink::Route> > _routes;
|
||||
std::map<InetAddress, std::set<LinuxNetLink::Route> > _routes;
|
||||
Mutex _routes_m;
|
||||
|
||||
struct iface_entry {
|
||||
iface_entry()
|
||||
{ memset(this,0,sizeof(iface_entry)); }
|
||||
{
|
||||
memset(this, 0, sizeof(iface_entry));
|
||||
}
|
||||
int index;
|
||||
char ifacename[16]; // IFNAMSIZ on Linux == 16
|
||||
char ifacename[16]; // IFNAMSIZ on Linux == 16
|
||||
char mac[18];
|
||||
char mac_bin[6];
|
||||
unsigned int mtu;
|
||||
|
@ -145,8 +156,8 @@ private:
|
|||
struct sockaddr_nl _la;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
||||
#endif // ZT_LINUX_NETLINK_HPPS
|
||||
#endif // ZT_LINUX_NETLINK_HPPS
|
|
@ -1,23 +1,23 @@
|
|||
#ifndef MAC_DNS_HELPER
|
||||
#define MAC_DNS_HELPER
|
||||
|
||||
#include <vector>
|
||||
#include "../node/InetAddress.hpp"
|
||||
#include "../node/MAC.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class MacDNSHelper
|
||||
{
|
||||
public:
|
||||
static void setDNS(uint64_t nwid, const char *domain, const std::vector<InetAddress> &servers);
|
||||
static void removeDNS(uint64_t nwid);
|
||||
static bool addIps4(uint64_t nwid, const MAC mac, const char *dev, const std::vector<InetAddress> &addrs);
|
||||
static bool addIps6(uint64_t nwid, const MAC mac, const char *dev, const std::vector<InetAddress> &addrs);
|
||||
static bool removeIps4(uint64_t nwid);
|
||||
static bool removeIps6(uint64_t nwid);
|
||||
class MacDNSHelper {
|
||||
public:
|
||||
static void setDNS(uint64_t nwid, const char* domain, const std::vector<InetAddress>& servers);
|
||||
static void removeDNS(uint64_t nwid);
|
||||
static bool addIps4(uint64_t nwid, const MAC mac, const char* dev, const std::vector<InetAddress>& addrs);
|
||||
static bool addIps6(uint64_t nwid, const MAC mac, const char* dev, const std::vector<InetAddress>& addrs);
|
||||
static bool removeIps4(uint64_t nwid);
|
||||
static bool removeIps6(uint64_t nwid);
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,49 +15,45 @@
|
|||
|
||||
#ifdef __APPLE__
|
||||
|
||||
#include "../node/Utils.hpp"
|
||||
#include "../node/Mutex.hpp"
|
||||
#include "../node/Dictionary.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
#include "../node/Mutex.hpp"
|
||||
#include "../node/Utils.hpp"
|
||||
#include "MacDNSHelper.hpp"
|
||||
#include "MacEthernetTap.hpp"
|
||||
#include "MacEthernetTapAgent.h"
|
||||
#include "MacDNSHelper.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <filesystem>
|
||||
#include <ifaddrs.h>
|
||||
#include <map>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <set>
|
||||
#include <signal.h>
|
||||
#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/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_dl.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <ifaddrs.h>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff),0);
|
||||
static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff), 0);
|
||||
|
||||
#define MACOS_FETH_MAX_MTU_SYSCTL "net.link.fake.max_mtu"
|
||||
|
||||
|
@ -68,45 +64,45 @@ static bool globalTapInitialized = false;
|
|||
static bool fethMaxMtuAdjusted = false;
|
||||
|
||||
MacEthernetTap::MacEthernetTap(
|
||||
const char *homePath,
|
||||
const MAC &mac,
|
||||
const char* homePath,
|
||||
const MAC& mac,
|
||||
unsigned int mtu,
|
||||
unsigned int metric,
|
||||
uint64_t nwid,
|
||||
const char *friendlyName,
|
||||
void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *data,unsigned int len),
|
||||
void *arg) :
|
||||
_handler(handler),
|
||||
_arg(arg),
|
||||
_nwid(nwid),
|
||||
_homePath(homePath),
|
||||
_mtu(mtu),
|
||||
_metric(metric),
|
||||
_devNo(0),
|
||||
_agentStdin(-1),
|
||||
_agentStdout(-1),
|
||||
_agentStderr(-1),
|
||||
_agentStdin2(-1),
|
||||
_agentStdout2(-1),
|
||||
_agentStderr2(-1),
|
||||
_agentPid(-1),
|
||||
_enabled(true),
|
||||
_lastIfAddrsUpdate(0)
|
||||
const char* friendlyName,
|
||||
void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void* data, unsigned int len),
|
||||
void* arg)
|
||||
: _handler(handler)
|
||||
, _arg(arg)
|
||||
, _nwid(nwid)
|
||||
, _homePath(homePath)
|
||||
, _mtu(mtu)
|
||||
, _metric(metric)
|
||||
, _devNo(0)
|
||||
, _agentStdin(-1)
|
||||
, _agentStdout(-1)
|
||||
, _agentStderr(-1)
|
||||
, _agentStdin2(-1)
|
||||
, _agentStdout2(-1)
|
||||
, _agentStderr2(-1)
|
||||
, _agentPid(-1)
|
||||
, _enabled(true)
|
||||
, _lastIfAddrsUpdate(0)
|
||||
{
|
||||
char ethaddr[64],mtustr[16],devnostr[16],devstr[16],metricstr[16];
|
||||
OSUtils::ztsnprintf(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]);
|
||||
OSUtils::ztsnprintf(mtustr,sizeof(mtustr),"%u",mtu);
|
||||
OSUtils::ztsnprintf(metricstr,sizeof(metricstr),"%u",metric);
|
||||
char ethaddr[64], mtustr[16], devnostr[16], devstr[16], metricstr[16];
|
||||
OSUtils::ztsnprintf(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]);
|
||||
OSUtils::ztsnprintf(mtustr, sizeof(mtustr), "%u", mtu);
|
||||
OSUtils::ztsnprintf(metricstr, sizeof(metricstr), "%u", metric);
|
||||
|
||||
std::string agentPath(homePath);
|
||||
agentPath.push_back(ZT_PATH_SEPARATOR);
|
||||
agentPath.append("MacEthernetTapAgent");
|
||||
if (!OSUtils::fileExists(agentPath.c_str()))
|
||||
if (! OSUtils::fileExists(agentPath.c_str()))
|
||||
throw std::runtime_error("MacEthernetTapAgent not present in ZeroTier home");
|
||||
|
||||
Mutex::Lock _gl(globalTapCreateLock); // only make one at a time
|
||||
Mutex::Lock _gl(globalTapCreateLock); // only make one at a time
|
||||
|
||||
if (!fethMaxMtuAdjusted) {
|
||||
if (! fethMaxMtuAdjusted) {
|
||||
fethMaxMtuAdjusted = true;
|
||||
int old_mtu = 0;
|
||||
size_t old_mtu_len = sizeof(old_mtu);
|
||||
|
@ -116,29 +112,30 @@ MacEthernetTap::MacEthernetTap(
|
|||
|
||||
// Destroy all feth devices on first tap start in case ZeroTier did not exit cleanly last time.
|
||||
// We leave interfaces less than feth100 alone in case something else is messing with feth devices.
|
||||
if (!globalTapInitialized) {
|
||||
if (! globalTapInitialized) {
|
||||
globalTapInitialized = true;
|
||||
struct ifaddrs *ifa = (struct ifaddrs *)0;
|
||||
struct ifaddrs* ifa = (struct ifaddrs*)0;
|
||||
std::set<std::string> deleted;
|
||||
if (!getifaddrs(&ifa)) {
|
||||
struct ifaddrs *p = ifa;
|
||||
if (! getifaddrs(&ifa)) {
|
||||
struct ifaddrs* p = ifa;
|
||||
while (p) {
|
||||
int nameLen = (int)strlen(p->ifa_name);
|
||||
// Delete feth# from feth0 to feth9999, but don't touch >10000.
|
||||
if ((!strncmp(p->ifa_name,"feth",4))&&(nameLen >= 5)&&(nameLen <= 8)&&(deleted.count(std::string(p->ifa_name)) == 0)) {
|
||||
if ((! strncmp(p->ifa_name, "feth", 4)) && (nameLen >= 5) && (nameLen <= 8) && (deleted.count(std::string(p->ifa_name)) == 0)) {
|
||||
deleted.insert(std::string(p->ifa_name));
|
||||
const char *args[4];
|
||||
const char* args[4];
|
||||
args[0] = "/sbin/ifconfig";
|
||||
args[1] = p->ifa_name;
|
||||
args[2] = "destroy";
|
||||
args[3] = (char *)0;
|
||||
args[3] = (char*)0;
|
||||
const pid_t pid = vfork();
|
||||
if (pid == 0) {
|
||||
execv(args[0],const_cast<char **>(args));
|
||||
execv(args[0], const_cast<char**>(args));
|
||||
_exit(-1);
|
||||
} else if (pid > 0) {
|
||||
}
|
||||
else if (pid > 0) {
|
||||
int rv = 0;
|
||||
waitpid(pid,&rv,0);
|
||||
waitpid(pid, &rv, 0);
|
||||
}
|
||||
}
|
||||
p = p->ifa_next;
|
||||
|
@ -148,15 +145,15 @@ MacEthernetTap::MacEthernetTap(
|
|||
}
|
||||
|
||||
unsigned int devNo = 100 + ((nwid ^ (nwid >> 32) ^ (nwid >> 48)) % 4900);
|
||||
for(;;) {
|
||||
OSUtils::ztsnprintf(devnostr,sizeof(devnostr),"%u",devNo);
|
||||
OSUtils::ztsnprintf(devstr,sizeof(devstr),"feth%u",devNo);
|
||||
for (;;) {
|
||||
OSUtils::ztsnprintf(devnostr, sizeof(devnostr), "%u", devNo);
|
||||
OSUtils::ztsnprintf(devstr, sizeof(devstr), "feth%u", devNo);
|
||||
bool duplicate = false;
|
||||
struct ifaddrs *ifa = (struct ifaddrs *)0;
|
||||
if (!getifaddrs(&ifa)) {
|
||||
struct ifaddrs *p = ifa;
|
||||
struct ifaddrs* ifa = (struct ifaddrs*)0;
|
||||
if (! getifaddrs(&ifa)) {
|
||||
struct ifaddrs* p = ifa;
|
||||
while (p) {
|
||||
if (!strcmp(p->ifa_name,devstr)) {
|
||||
if (! strcmp(p->ifa_name, devstr)) {
|
||||
duplicate = true;
|
||||
break;
|
||||
}
|
||||
|
@ -168,7 +165,8 @@ MacEthernetTap::MacEthernetTap(
|
|||
devNo = (devNo + 1) % 5000;
|
||||
if (devNo < 100)
|
||||
devNo = 100;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
_dev = devstr;
|
||||
_devNo = devNo;
|
||||
break;
|
||||
|
@ -196,29 +194,31 @@ MacEthernetTap::MacEthernetTap(
|
|||
long apid = (long)fork();
|
||||
if (apid < 0) {
|
||||
throw std::runtime_error("fork failed");
|
||||
} else if (apid == 0) {
|
||||
::dup2(agentStdin[0],STDIN_FILENO);
|
||||
::dup2(agentStdout[1],STDOUT_FILENO);
|
||||
::dup2(agentStderr[1],STDERR_FILENO);
|
||||
}
|
||||
else if (apid == 0) {
|
||||
::dup2(agentStdin[0], STDIN_FILENO);
|
||||
::dup2(agentStdout[1], STDOUT_FILENO);
|
||||
::dup2(agentStderr[1], STDERR_FILENO);
|
||||
::close(agentStdin[0]);
|
||||
::close(agentStdin[1]);
|
||||
::close(agentStdout[0]);
|
||||
::close(agentStdout[1]);
|
||||
::close(agentStderr[0]);
|
||||
::close(agentStderr[1]);
|
||||
::execl(agentPath.c_str(),agentPath.c_str(),devnostr,ethaddr,mtustr,metricstr,(char *)0);
|
||||
::execl(agentPath.c_str(), agentPath.c_str(), devnostr, ethaddr, mtustr, metricstr, (char*)0);
|
||||
::_exit(-1);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
_agentPid = apid;
|
||||
|
||||
// Wait up to 10 seconds for the subprocess to actually create the device. This prevents
|
||||
// things like routes from being created before the device exists.
|
||||
for(int waitLoops=0;;++waitLoops) {
|
||||
struct ifaddrs *ifa = (struct ifaddrs *)0;
|
||||
if (!getifaddrs(&ifa)) {
|
||||
struct ifaddrs *p = ifa;
|
||||
for (int waitLoops = 0;; ++waitLoops) {
|
||||
struct ifaddrs* ifa = (struct ifaddrs*)0;
|
||||
if (! getifaddrs(&ifa)) {
|
||||
struct ifaddrs* p = ifa;
|
||||
while (p) {
|
||||
if ((p->ifa_name)&&(!strcmp(devstr, p->ifa_name))) {
|
||||
if ((p->ifa_name) && (! strcmp(devstr, p->ifa_name))) {
|
||||
waitLoops = -1;
|
||||
break;
|
||||
}
|
||||
|
@ -228,7 +228,8 @@ MacEthernetTap::MacEthernetTap(
|
|||
}
|
||||
if (waitLoops == -1) {
|
||||
break;
|
||||
} else if (waitLoops >= 100) { // 10 seconds
|
||||
}
|
||||
else if (waitLoops >= 100) { // 10 seconds
|
||||
throw std::runtime_error("feth device creation timed out");
|
||||
}
|
||||
Thread::sleep(100);
|
||||
|
@ -241,61 +242,67 @@ MacEthernetTap::MacEthernetTap(
|
|||
MacEthernetTap::~MacEthernetTap()
|
||||
{
|
||||
char tmp[64];
|
||||
const char *args[4];
|
||||
pid_t pid0,pid1;
|
||||
const char* args[4];
|
||||
pid_t pid0, pid1;
|
||||
|
||||
MacDNSHelper::removeDNS(_nwid);
|
||||
MacDNSHelper::removeIps4(_nwid);
|
||||
MacDNSHelper::removeIps6(_nwid);
|
||||
|
||||
Mutex::Lock _gl(globalTapCreateLock);
|
||||
::write(_shutdownSignalPipe[1],"\0",1); // causes thread to exit
|
||||
::write(_shutdownSignalPipe[1], "\0", 1); // causes thread to exit
|
||||
|
||||
int ec = 0;
|
||||
::kill(_agentPid,SIGKILL);
|
||||
::waitpid(_agentPid,&ec,0);
|
||||
::kill(_agentPid, SIGKILL);
|
||||
::waitpid(_agentPid, &ec, 0);
|
||||
|
||||
args[0] = "/sbin/ifconfig";
|
||||
args[1] = _dev.c_str();
|
||||
args[2] = "destroy";
|
||||
args[3] = (char *)0;
|
||||
args[3] = (char*)0;
|
||||
pid0 = vfork();
|
||||
if (pid0 == 0) {
|
||||
execv(args[0],const_cast<char **>(args));
|
||||
execv(args[0], const_cast<char**>(args));
|
||||
_exit(-1);
|
||||
}
|
||||
|
||||
snprintf(tmp,sizeof(tmp),"feth%u",_devNo + 5000);
|
||||
//args[0] = "/sbin/ifconfig";
|
||||
snprintf(tmp, sizeof(tmp), "feth%u", _devNo + 5000);
|
||||
// args[0] = "/sbin/ifconfig";
|
||||
args[1] = tmp;
|
||||
//args[2] = "destroy";
|
||||
//args[3] = (char *)0;
|
||||
// args[2] = "destroy";
|
||||
// args[3] = (char *)0;
|
||||
pid1 = vfork();
|
||||
if (pid1 == 0) {
|
||||
execv(args[0],const_cast<char **>(args));
|
||||
execv(args[0], const_cast<char**>(args));
|
||||
_exit(-1);
|
||||
}
|
||||
|
||||
if (pid0 > 0) {
|
||||
int rv = 0;
|
||||
waitpid(pid0,&rv,0);
|
||||
waitpid(pid0, &rv, 0);
|
||||
}
|
||||
if (pid1 > 0) {
|
||||
int rv = 0;
|
||||
waitpid(pid1,&rv,0);
|
||||
waitpid(pid1, &rv, 0);
|
||||
}
|
||||
|
||||
Thread::join(_thread);
|
||||
}
|
||||
|
||||
void MacEthernetTap::setEnabled(bool en) { _enabled = en; }
|
||||
bool MacEthernetTap::enabled() const { return _enabled; }
|
||||
void MacEthernetTap::setEnabled(bool en)
|
||||
{
|
||||
_enabled = en;
|
||||
}
|
||||
bool MacEthernetTap::enabled() const
|
||||
{
|
||||
return _enabled;
|
||||
}
|
||||
|
||||
bool MacEthernetTap::addIp(const InetAddress &ip)
|
||||
bool MacEthernetTap::addIp(const InetAddress& ip)
|
||||
{
|
||||
char tmp[128];
|
||||
|
||||
if (!ip)
|
||||
if (! ip)
|
||||
return false;
|
||||
|
||||
std::string cmd;
|
||||
|
@ -309,18 +316,18 @@ bool MacEthernetTap::addIp(const InetAddress &ip)
|
|||
|
||||
uint16_t l = (uint16_t)cmd.length();
|
||||
_putLock.lock();
|
||||
write(_agentStdin,&l,2);
|
||||
write(_agentStdin,cmd.data(),cmd.length());
|
||||
write(_agentStdin, &l, 2);
|
||||
write(_agentStdin, cmd.data(), cmd.length());
|
||||
_putLock.unlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacEthernetTap::removeIp(const InetAddress &ip)
|
||||
bool MacEthernetTap::removeIp(const InetAddress& ip)
|
||||
{
|
||||
char tmp[128];
|
||||
|
||||
if (!ip)
|
||||
if (! ip)
|
||||
return false;
|
||||
|
||||
std::string cmd;
|
||||
|
@ -334,8 +341,8 @@ bool MacEthernetTap::removeIp(const InetAddress &ip)
|
|||
|
||||
uint16_t l = (uint16_t)cmd.length();
|
||||
_putLock.lock();
|
||||
write(_agentStdin,&l,2);
|
||||
write(_agentStdin,cmd.data(),cmd.length());
|
||||
write(_agentStdin, &l, 2);
|
||||
write(_agentStdin, cmd.data(), cmd.length());
|
||||
_putLock.unlock();
|
||||
|
||||
return true;
|
||||
|
@ -350,49 +357,49 @@ std::vector<InetAddress> MacEthernetTap::ips() const
|
|||
}
|
||||
_lastIfAddrsUpdate = now;
|
||||
|
||||
struct ifaddrs *ifa = (struct ifaddrs *)0;
|
||||
struct ifaddrs* ifa = (struct ifaddrs*)0;
|
||||
std::vector<InetAddress> r;
|
||||
|
||||
if (!getifaddrs(&ifa)) {
|
||||
struct ifaddrs *p = ifa;
|
||||
if (! getifaddrs(&ifa)) {
|
||||
struct ifaddrs* p = ifa;
|
||||
while (p) {
|
||||
if ((p->ifa_name)&&(!strcmp(p->ifa_name,_dev.c_str()))&&(p->ifa_addr)) {
|
||||
switch(p->ifa_addr->sa_family) {
|
||||
if ((p->ifa_name) && (! strcmp(p->ifa_name, _dev.c_str())) && (p->ifa_addr)) {
|
||||
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.push_back(InetAddress(&(sin->sin_addr.s_addr),4,Utils::countBits((uint32_t)nm->sin_addr.s_addr)));
|
||||
} break;
|
||||
struct sockaddr_in* sin = (struct sockaddr_in*)p->ifa_addr;
|
||||
struct sockaddr_in* nm = (struct sockaddr_in*)p->ifa_netmask;
|
||||
r.push_back(InetAddress(&(sin->sin_addr.s_addr), 4, Utils::countBits((uint32_t)nm->sin_addr.s_addr)));
|
||||
} break;
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *sin = (struct sockaddr_in6 *)p->ifa_addr;
|
||||
struct sockaddr_in6 *nm = (struct sockaddr_in6 *)p->ifa_netmask;
|
||||
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.push_back(InetAddress(sin->sin6_addr.s6_addr,16,Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3])));
|
||||
} break;
|
||||
memcpy(b, nm->sin6_addr.s6_addr, sizeof(b));
|
||||
r.push_back(InetAddress(sin->sin6_addr.s6_addr, 16, Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3])));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
p = p->ifa_next;
|
||||
}
|
||||
freeifaddrs(ifa);
|
||||
}
|
||||
std::sort(r.begin(),r.end());
|
||||
r.erase(std::unique(r.begin(),r.end()),r.end());
|
||||
std::sort(r.begin(), r.end());
|
||||
r.erase(std::unique(r.begin(), r.end()), r.end());
|
||||
|
||||
_ifaddrs = r;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void MacEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
|
||||
void MacEthernetTap::put(const MAC& from, const MAC& to, unsigned int etherType, const void* data, unsigned int len)
|
||||
{
|
||||
struct iovec iov[3];
|
||||
unsigned char hdr[15];
|
||||
uint16_t l;
|
||||
if ((_agentStdin > 0)&&(len <= _mtu)&&(_enabled)) {
|
||||
if ((_agentStdin > 0) && (len <= _mtu) && (_enabled)) {
|
||||
hdr[0] = ZT_MACETHERNETTAPAGENT_STDIN_CMD_PACKET;
|
||||
to.copyTo(hdr + 1,6);
|
||||
from.copyTo(hdr + 7,6);
|
||||
to.copyTo(hdr + 1, 6);
|
||||
from.copyTo(hdr + 7, 6);
|
||||
hdr[13] = (unsigned char)((etherType >> 8) & 0xff);
|
||||
hdr[14] = (unsigned char)(etherType & 0xff);
|
||||
l = (uint16_t)(len + 15);
|
||||
|
@ -400,30 +407,35 @@ void MacEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,co
|
|||
iov[0].iov_len = 2;
|
||||
iov[1].iov_base = hdr;
|
||||
iov[1].iov_len = 15;
|
||||
iov[2].iov_base = const_cast<void *>(data);
|
||||
iov[2].iov_base = const_cast<void*>(data);
|
||||
iov[2].iov_len = len;
|
||||
_putLock.lock();
|
||||
writev(_agentStdin,iov,3);
|
||||
writev(_agentStdin, iov, 3);
|
||||
_putLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
std::string MacEthernetTap::deviceName() const { return _dev; }
|
||||
void MacEthernetTap::setFriendlyName(const char *friendlyName) {}
|
||||
std::string MacEthernetTap::deviceName() const
|
||||
{
|
||||
return _dev;
|
||||
}
|
||||
void MacEthernetTap::setFriendlyName(const char* friendlyName)
|
||||
{
|
||||
}
|
||||
|
||||
void MacEthernetTap::scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed)
|
||||
void MacEthernetTap::scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed)
|
||||
{
|
||||
std::vector<MulticastGroup> newGroups;
|
||||
|
||||
struct ifmaddrs *ifmap = (struct ifmaddrs *)0;
|
||||
if (!getifmaddrs(&ifmap)) {
|
||||
struct ifmaddrs *p = ifmap;
|
||||
struct ifmaddrs* ifmap = (struct ifmaddrs*)0;
|
||||
if (! getifmaddrs(&ifmap)) {
|
||||
struct 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.push_back(MulticastGroup(MAC(la->sdl_data + la->sdl_nlen,6),0));
|
||||
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.push_back(MulticastGroup(MAC(la->sdl_data + la->sdl_nlen, 6), 0));
|
||||
}
|
||||
p = p->ifma_next;
|
||||
}
|
||||
|
@ -431,18 +443,18 @@ void MacEthernetTap::scanMulticastGroups(std::vector<MulticastGroup> &added,std:
|
|||
}
|
||||
|
||||
std::vector<InetAddress> allIps(ips());
|
||||
for(std::vector<InetAddress>::iterator ip(allIps.begin());ip!=allIps.end();++ip)
|
||||
for (std::vector<InetAddress>::iterator ip(allIps.begin()); ip != allIps.end(); ++ip)
|
||||
newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip));
|
||||
|
||||
std::sort(newGroups.begin(),newGroups.end());
|
||||
newGroups.erase(std::unique(newGroups.begin(),newGroups.end()),newGroups.end());
|
||||
std::sort(newGroups.begin(), newGroups.end());
|
||||
newGroups.erase(std::unique(newGroups.begin(), newGroups.end()), newGroups.end());
|
||||
|
||||
for(std::vector<MulticastGroup>::iterator m(newGroups.begin());m!=newGroups.end();++m) {
|
||||
if (!std::binary_search(_multicastGroups.begin(),_multicastGroups.end(),*m))
|
||||
for (std::vector<MulticastGroup>::iterator m(newGroups.begin()); m != newGroups.end(); ++m) {
|
||||
if (! std::binary_search(_multicastGroups.begin(), _multicastGroups.end(), *m))
|
||||
added.push_back(*m);
|
||||
}
|
||||
for(std::vector<MulticastGroup>::iterator m(_multicastGroups.begin());m!=_multicastGroups.end();++m) {
|
||||
if (!std::binary_search(newGroups.begin(),newGroups.end(),*m))
|
||||
for (std::vector<MulticastGroup>::iterator m(_multicastGroups.begin()); m != _multicastGroups.end(); ++m) {
|
||||
if (! std::binary_search(newGroups.begin(), newGroups.end(), *m))
|
||||
removed.push_back(*m);
|
||||
}
|
||||
|
||||
|
@ -457,13 +469,13 @@ void MacEthernetTap::setMtu(unsigned int mtu)
|
|||
cmd.push_back((char)ZT_MACETHERNETTAPAGENT_STDIN_CMD_IFCONFIG);
|
||||
cmd.append("mtu");
|
||||
cmd.push_back(0);
|
||||
OSUtils::ztsnprintf(tmp,sizeof(tmp),"%u",mtu);
|
||||
OSUtils::ztsnprintf(tmp, sizeof(tmp), "%u", mtu);
|
||||
cmd.append(tmp);
|
||||
cmd.push_back(0);
|
||||
uint16_t l = (uint16_t)cmd.length();
|
||||
_putLock.lock();
|
||||
write(_agentStdin,&l,2);
|
||||
write(_agentStdin,cmd.data(),cmd.length());
|
||||
write(_agentStdin, &l, 2);
|
||||
write(_agentStdin, cmd.data(), cmd.length());
|
||||
_putLock.unlock();
|
||||
_mtu = mtu;
|
||||
}
|
||||
|
@ -471,61 +483,62 @@ void MacEthernetTap::setMtu(unsigned int mtu)
|
|||
|
||||
#define ZT_MACETHERNETTAP_AGENT_READ_BUF_SIZE 131072
|
||||
|
||||
void MacEthernetTap::threadMain()
|
||||
throw()
|
||||
void MacEthernetTap::threadMain() throw()
|
||||
{
|
||||
char agentReadBuf[ZT_MACETHERNETTAP_AGENT_READ_BUF_SIZE];
|
||||
char agentStderrBuf[256];
|
||||
fd_set readfds,nullfds;
|
||||
MAC to,from;
|
||||
fd_set readfds, nullfds;
|
||||
MAC to, from;
|
||||
|
||||
Thread::sleep(250);
|
||||
|
||||
const int nfds = std::max(std::max(_shutdownSignalPipe[0],_agentStdout),_agentStderr) + 1;
|
||||
const int nfds = std::max(std::max(_shutdownSignalPipe[0], _agentStdout), _agentStderr) + 1;
|
||||
long agentReadPtr = 0;
|
||||
fcntl(_agentStdout,F_SETFL,fcntl(_agentStdout,F_GETFL)|O_NONBLOCK);
|
||||
fcntl(_agentStderr,F_SETFL,fcntl(_agentStderr,F_GETFL)|O_NONBLOCK);
|
||||
fcntl(_agentStdout, F_SETFL, fcntl(_agentStdout, F_GETFL) | O_NONBLOCK);
|
||||
fcntl(_agentStderr, F_SETFL, fcntl(_agentStderr, F_GETFL) | O_NONBLOCK);
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_ZERO(&nullfds);
|
||||
for(;;) {
|
||||
FD_SET(_shutdownSignalPipe[0],&readfds);
|
||||
FD_SET(_agentStdout,&readfds);
|
||||
FD_SET(_agentStderr,&readfds);
|
||||
select(nfds,&readfds,&nullfds,&nullfds,(struct timeval *)0);
|
||||
for (;;) {
|
||||
FD_SET(_shutdownSignalPipe[0], &readfds);
|
||||
FD_SET(_agentStdout, &readfds);
|
||||
FD_SET(_agentStderr, &readfds);
|
||||
select(nfds, &readfds, &nullfds, &nullfds, (struct timeval*)0);
|
||||
|
||||
if (FD_ISSET(_shutdownSignalPipe[0],&readfds))
|
||||
if (FD_ISSET(_shutdownSignalPipe[0], &readfds))
|
||||
break;
|
||||
|
||||
if (FD_ISSET(_agentStdout,&readfds)) {
|
||||
long n = (long)read(_agentStdout,agentReadBuf + agentReadPtr,ZT_MACETHERNETTAP_AGENT_READ_BUF_SIZE - agentReadPtr);
|
||||
if (FD_ISSET(_agentStdout, &readfds)) {
|
||||
long n = (long)read(_agentStdout, agentReadBuf + agentReadPtr, ZT_MACETHERNETTAP_AGENT_READ_BUF_SIZE - agentReadPtr);
|
||||
if (n > 0) {
|
||||
agentReadPtr += n;
|
||||
while (agentReadPtr >= 2) {
|
||||
long len = *((uint16_t *)agentReadBuf);
|
||||
long len = *((uint16_t*)agentReadBuf);
|
||||
if (agentReadPtr >= (len + 2)) {
|
||||
char *msg = agentReadBuf + 2;
|
||||
char* msg = agentReadBuf + 2;
|
||||
|
||||
if ((len > 14)&&(_enabled)) {
|
||||
to.setTo(msg,6);
|
||||
from.setTo(msg + 6,6);
|
||||
_handler(_arg,(void *)0,_nwid,from,to,ntohs(((const uint16_t *)msg)[6]),0,(const void *)(msg + 14),(unsigned int)len - 14);
|
||||
if ((len > 14) && (_enabled)) {
|
||||
to.setTo(msg, 6);
|
||||
from.setTo(msg + 6, 6);
|
||||
_handler(_arg, (void*)0, _nwid, from, to, ntohs(((const uint16_t*)msg)[6]), 0, (const void*)(msg + 14), (unsigned int)len - 14);
|
||||
}
|
||||
|
||||
if (agentReadPtr > (len + 2)) {
|
||||
memmove(agentReadBuf,agentReadBuf + len + 2,agentReadPtr -= (len + 2));
|
||||
} else {
|
||||
memmove(agentReadBuf, agentReadBuf + len + 2, agentReadPtr -= (len + 2));
|
||||
}
|
||||
else {
|
||||
agentReadPtr = 0;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (FD_ISSET(_agentStderr,&readfds)) {
|
||||
read(_agentStderr,agentStderrBuf,sizeof(agentStderrBuf));
|
||||
if (FD_ISSET(_agentStderr, &readfds)) {
|
||||
read(_agentStderr, agentStderrBuf, sizeof(agentStderrBuf));
|
||||
/*
|
||||
const ssize_t n = read(_agentStderr,agentStderrBuf,sizeof(agentStderrBuf));
|
||||
if (n > 0)
|
||||
|
@ -544,11 +557,11 @@ void MacEthernetTap::threadMain()
|
|||
::close(_shutdownSignalPipe[1]);
|
||||
}
|
||||
|
||||
void MacEthernetTap::setDns(const char *domain, const std::vector<InetAddress> &servers)
|
||||
void MacEthernetTap::setDns(const char* domain, const std::vector<InetAddress>& servers)
|
||||
{
|
||||
MacDNSHelper::setDNS(this->_nwid, domain, servers);
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif // __APPLE__
|
||||
#endif // __APPLE__
|
||||
|
|
|
@ -15,55 +15,52 @@
|
|||
#define ZT_OSXETHERNETTAP_HPP
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/MAC.hpp"
|
||||
#include "../node/InetAddress.hpp"
|
||||
#include "../node/MAC.hpp"
|
||||
#include "../node/MulticastGroup.hpp"
|
||||
#include "../node/Mutex.hpp"
|
||||
#include "Thread.hpp"
|
||||
#include "EthernetTap.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "Thread.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class MacEthernetTap : public EthernetTap
|
||||
{
|
||||
public:
|
||||
class MacEthernetTap : public EthernetTap {
|
||||
public:
|
||||
MacEthernetTap(
|
||||
const char *homePath,
|
||||
const MAC &mac,
|
||||
const char* homePath,
|
||||
const MAC& mac,
|
||||
unsigned int mtu,
|
||||
unsigned int metric,
|
||||
uint64_t nwid,
|
||||
const char *friendlyName,
|
||||
void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
|
||||
void *arg);
|
||||
const char* friendlyName,
|
||||
void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
|
||||
void* arg);
|
||||
|
||||
virtual ~MacEthernetTap();
|
||||
|
||||
virtual void setEnabled(bool en);
|
||||
virtual bool enabled() const;
|
||||
virtual bool addIp(const InetAddress &ip);
|
||||
virtual bool removeIp(const InetAddress &ip);
|
||||
virtual bool addIp(const InetAddress& ip);
|
||||
virtual bool removeIp(const InetAddress& ip);
|
||||
virtual std::vector<InetAddress> ips() const;
|
||||
virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len);
|
||||
virtual void put(const MAC& from, const MAC& to, unsigned int etherType, const void* data, unsigned int len);
|
||||
virtual std::string deviceName() const;
|
||||
virtual void setFriendlyName(const char *friendlyName);
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
|
||||
virtual void setFriendlyName(const char* friendlyName);
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed);
|
||||
virtual void setMtu(unsigned int mtu);
|
||||
virtual void setDns(const char *domain, const std::vector<InetAddress> &servers);
|
||||
virtual void setDns(const char* domain, const std::vector<InetAddress>& servers);
|
||||
|
||||
void threadMain()
|
||||
throw();
|
||||
void threadMain() throw();
|
||||
|
||||
private:
|
||||
void (*_handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
|
||||
void *_arg;
|
||||
private:
|
||||
void (*_handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int);
|
||||
void* _arg;
|
||||
uint64_t _nwid;
|
||||
Thread _thread;
|
||||
std::string _homePath;
|
||||
|
@ -74,14 +71,13 @@ private:
|
|||
unsigned int _metric;
|
||||
unsigned int _devNo;
|
||||
int _shutdownSignalPipe[2];
|
||||
int _agentStdin,_agentStdout,_agentStderr,_agentStdin2,_agentStdout2,_agentStderr2;
|
||||
int _agentStdin, _agentStdout, _agentStderr, _agentStdin2, _agentStdout2, _agentStderr2;
|
||||
long _agentPid;
|
||||
volatile bool _enabled;
|
||||
mutable std::vector<InetAddress> _ifaddrs;
|
||||
mutable uint64_t _lastIfAddrsUpdate;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,39 +11,36 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "MacDNSHelper.hpp"
|
||||
|
||||
#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/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/route.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_media.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <netinet6/in6_var.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/icmp6.h>
|
||||
|
||||
#include "MacDNSHelper.hpp"
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet6/in6_var.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// OSX compile fix... in6_var defines this in a struct which namespaces it for C++ ... why?!?
|
||||
struct prf_ra {
|
||||
|
@ -52,15 +49,15 @@ struct prf_ra {
|
|||
u_char reserved : 6;
|
||||
} prf_ra;
|
||||
|
||||
#include <netinet6/nd6.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <netinet6/nd6.h>
|
||||
|
||||
// These are KERNEL_PRIVATE... why?
|
||||
#ifndef SIOCAUTOCONF_START
|
||||
#define SIOCAUTOCONF_START _IOWR('i', 132, struct in6_ifreq) /* accept rtadvd on this interface */
|
||||
#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 */
|
||||
#define SIOCAUTOCONF_STOP _IOWR('i', 133, struct in6_ifreq) /* stop accepting rtadv for this interface */
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
@ -69,33 +66,32 @@ struct prf_ra {
|
|||
// 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)
|
||||
#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
|
||||
// #define DARWIN_COMPAT
|
||||
|
||||
//#ifdef 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
|
||||
#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;
|
||||
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)
|
||||
static inline int _intl_getifmaddrs(struct _intl_ifmaddrs** pif)
|
||||
{
|
||||
int icnt = 1;
|
||||
int dcnt = 0;
|
||||
|
@ -104,25 +100,25 @@ static inline int _intl_getifmaddrs(struct _intl_ifmaddrs **pif)
|
|||
size_t needed;
|
||||
int mib[6];
|
||||
int i;
|
||||
char *buf;
|
||||
char *data;
|
||||
char *next;
|
||||
char *p;
|
||||
struct ifma_msghdr2 *ifmam;
|
||||
char* buf;
|
||||
char* data;
|
||||
char* next;
|
||||
char* p;
|
||||
struct ifma_msghdr2* ifmam;
|
||||
struct _intl_ifmaddrs *ifa, *ift;
|
||||
struct rt_msghdr *rtm;
|
||||
struct sockaddr *sa;
|
||||
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[2] = 0; /* protocol */
|
||||
mib[3] = 0; /* wildcard address family */
|
||||
mib[4] = GIM_SYSCTL_MIB;
|
||||
mib[5] = 0; /* no flags */
|
||||
mib[5] = 0; /* no flags */
|
||||
do {
|
||||
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
|
||||
return (-1);
|
||||
if ((buf = (char *)malloc(needed)) == NULL)
|
||||
if ((buf = (char*)malloc(needed)) == NULL)
|
||||
return (-1);
|
||||
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
|
||||
if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
|
||||
|
@ -135,21 +131,20 @@ static inline int _intl_getifmaddrs(struct _intl_ifmaddrs **pif)
|
|||
} while (buf == NULL);
|
||||
|
||||
for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
|
||||
rtm = (struct rt_msghdr *)(void *)next;
|
||||
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;
|
||||
ifmam = (struct ifma_msghdr2*)(void*)rtm;
|
||||
if ((ifmam->ifmam_addrs & RTA_IFA) == 0)
|
||||
break;
|
||||
icnt++;
|
||||
p = (char *)(ifmam + 1);
|
||||
p = (char*)(ifmam + 1);
|
||||
for (i = 0; i < RTAX_MAX; i++) {
|
||||
if ((RTA_MASKS & ifmam->ifmam_addrs &
|
||||
(1 << i)) == 0)
|
||||
if ((RTA_MASKS & ifmam->ifmam_addrs & (1 << i)) == 0)
|
||||
continue;
|
||||
sa = (struct sockaddr *)(void *)p;
|
||||
sa = (struct sockaddr*)(void*)p;
|
||||
len = SA_RLEN(sa);
|
||||
dcnt += len;
|
||||
p += len;
|
||||
|
@ -158,54 +153,50 @@ static inline int _intl_getifmaddrs(struct _intl_ifmaddrs **pif)
|
|||
}
|
||||
}
|
||||
|
||||
data = (char *)malloc(sizeof(struct _intl_ifmaddrs) * icnt + dcnt);
|
||||
data = (char*)malloc(sizeof(struct _intl_ifmaddrs) * icnt + dcnt);
|
||||
if (data == NULL) {
|
||||
free(buf);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
ifa = (struct _intl_ifmaddrs *)(void *)data;
|
||||
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;
|
||||
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;
|
||||
ifmam = (struct ifma_msghdr2*)(void*)rtm;
|
||||
if ((ifmam->ifmam_addrs & RTA_IFA) == 0)
|
||||
break;
|
||||
|
||||
p = (char *)(ifmam + 1);
|
||||
p = (char*)(ifmam + 1);
|
||||
for (i = 0; i < RTAX_MAX; i++) {
|
||||
if ((RTA_MASKS & ifmam->ifmam_addrs &
|
||||
(1 << i)) == 0)
|
||||
if ((RTA_MASKS & ifmam->ifmam_addrs & (1 << i)) == 0)
|
||||
continue;
|
||||
sa = (struct sockaddr *)(void *)p;
|
||||
sa = (struct sockaddr*)(void*)p;
|
||||
len = SA_RLEN(sa);
|
||||
switch (i) {
|
||||
case RTAX_GATEWAY:
|
||||
ift->ifma_lladdr =
|
||||
(struct sockaddr *)(void *)data;
|
||||
ift->ifma_lladdr = (struct sockaddr*)(void*)data;
|
||||
memcpy(data, p, len);
|
||||
data += len;
|
||||
break;
|
||||
|
||||
case RTAX_IFP:
|
||||
ift->ifma_name =
|
||||
(struct sockaddr *)(void *)data;
|
||||
ift->ifma_name = (struct sockaddr*)(void*)data;
|
||||
memcpy(data, p, len);
|
||||
data += len;
|
||||
break;
|
||||
|
||||
case RTAX_IFA:
|
||||
ift->ifma_addr =
|
||||
(struct sockaddr *)(void *)data;
|
||||
ift->ifma_addr = (struct sockaddr*)(void*)data;
|
||||
memcpy(data, p, len);
|
||||
data += len;
|
||||
break;
|
||||
|
@ -228,14 +219,15 @@ static inline int _intl_getifmaddrs(struct _intl_ifmaddrs **pif)
|
|||
ift--;
|
||||
ift->ifma_next = NULL;
|
||||
*pif = ifa;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
*pif = NULL;
|
||||
free(ifa);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static inline void _intl_freeifmaddrs(struct _intl_ifmaddrs *ifmp)
|
||||
static inline void _intl_freeifmaddrs(struct _intl_ifmaddrs* ifmp)
|
||||
{
|
||||
free(ifmp);
|
||||
}
|
||||
|
@ -243,34 +235,34 @@ static inline void _intl_freeifmaddrs(struct _intl_ifmaddrs *ifmp)
|
|||
// --------------------------------------------------------------------------
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#include <string>
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/Dictionary.hpp"
|
||||
#include "../node/Mutex.hpp"
|
||||
#include "../node/Utils.hpp"
|
||||
#include "MacKextEthernetTap.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/Utils.hpp"
|
||||
#include "../node/Mutex.hpp"
|
||||
#include "../node/Dictionary.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
#include "MacKextEthernetTap.hpp"
|
||||
#include <string>
|
||||
|
||||
// ff:ff:ff:ff:ff:ff with no ADI
|
||||
static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff),0);
|
||||
static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff), 0);
|
||||
|
||||
static inline bool _setIpv6Stuff(const char *ifname,bool performNUD,bool acceptRouterAdverts)
|
||||
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);
|
||||
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));
|
||||
memset(&nd, 0, sizeof(nd));
|
||||
strncpy(nd.ifname, ifname, sizeof(nd.ifname));
|
||||
|
||||
if (ioctl(s,SIOCGIFINFO_IN6,&nd)) {
|
||||
if (ioctl(s, SIOCGIFINFO_IN6, &nd)) {
|
||||
close(s);
|
||||
return false;
|
||||
}
|
||||
|
@ -279,18 +271,19 @@ static inline bool _setIpv6Stuff(const char *ifname,bool performNUD,bool acceptR
|
|||
|
||||
if (performNUD)
|
||||
nd.ndi.flags |= ND6_IFF_PERFORMNUD;
|
||||
else 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)) {
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
|
@ -305,71 +298,76 @@ static long globalTapsRunning = 0;
|
|||
static Mutex globalTapCreateLock;
|
||||
|
||||
MacKextEthernetTap::MacKextEthernetTap(
|
||||
const char *homePath,
|
||||
const MAC &mac,
|
||||
const char* homePath,
|
||||
const MAC& mac,
|
||||
unsigned int mtu,
|
||||
unsigned int metric,
|
||||
uint64_t nwid,
|
||||
const char *friendlyName,
|
||||
void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *data,unsigned int len),
|
||||
void *arg) :
|
||||
_handler(handler),
|
||||
_arg(arg),
|
||||
_nwid(nwid),
|
||||
_homePath(homePath),
|
||||
_mtu(mtu),
|
||||
_metric(metric),
|
||||
_fd(0),
|
||||
_enabled(true)
|
||||
const char* friendlyName,
|
||||
void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void* data, unsigned int len),
|
||||
void* arg)
|
||||
: _handler(handler)
|
||||
, _arg(arg)
|
||||
, _nwid(nwid)
|
||||
, _homePath(homePath)
|
||||
, _mtu(mtu)
|
||||
, _metric(metric)
|
||||
, _fd(0)
|
||||
, _enabled(true)
|
||||
{
|
||||
char devpath[64],ethaddr[64],mtustr[32],metstr[32],nwids[32];
|
||||
char devpath[64], ethaddr[64], mtustr[32], metstr[32], nwids[32];
|
||||
struct stat stattmp;
|
||||
|
||||
OSUtils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid);
|
||||
OSUtils::ztsnprintf(nwids, sizeof(nwids), "%.16llx", nwid);
|
||||
|
||||
Mutex::Lock _gl(globalTapCreateLock);
|
||||
|
||||
if (::stat("/dev/zt0",&stattmp)) {
|
||||
if (::stat("/dev/zt0", &stattmp)) {
|
||||
long kextpid = (long)fork();
|
||||
if (kextpid == 0) {
|
||||
::chdir(homePath);
|
||||
OSUtils::redirectUnixOutputs("/dev/null",(const char *)0);
|
||||
::execl("/sbin/kextload","/sbin/kextload","-q","-repository",homePath,"tap.kext",(const char *)0);
|
||||
OSUtils::redirectUnixOutputs("/dev/null", (const char*)0);
|
||||
::execl("/sbin/kextload", "/sbin/kextload", "-q", "-repository", homePath, "tap.kext", (const char*)0);
|
||||
::_exit(-1);
|
||||
} else if (kextpid > 0) {
|
||||
int exitcode = -1;
|
||||
::waitpid(kextpid,&exitcode,0);
|
||||
}
|
||||
::usleep(500); // give tap device driver time to start up and try again
|
||||
if (::stat("/dev/zt0",&stattmp))
|
||||
else if (kextpid > 0) {
|
||||
int exitcode = -1;
|
||||
::waitpid(kextpid, &exitcode, 0);
|
||||
}
|
||||
::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 cannot load tap.kext");
|
||||
}
|
||||
|
||||
// Try to reopen the last device we had, if we had one and it's still unused.
|
||||
std::map<std::string,std::string> globalDeviceMap;
|
||||
FILE *devmapf = fopen((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(),"r");
|
||||
std::map<std::string, std::string> globalDeviceMap;
|
||||
FILE* devmapf = fopen((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(), "r");
|
||||
if (devmapf) {
|
||||
char buf[256];
|
||||
while (fgets(buf,sizeof(buf),devmapf)) {
|
||||
char *x = (char *)0;
|
||||
char *y = (char *)0;
|
||||
char *saveptr = (char *)0;
|
||||
for(char *f=Utils::stok(buf,"\r\n=",&saveptr);(f);f=Utils::stok((char *)0,"\r\n=",&saveptr)) {
|
||||
if (!x) x = f;
|
||||
else if (!y) y = f;
|
||||
else break;
|
||||
while (fgets(buf, sizeof(buf), devmapf)) {
|
||||
char* x = (char*)0;
|
||||
char* y = (char*)0;
|
||||
char* saveptr = (char*)0;
|
||||
for (char* f = Utils::stok(buf, "\r\n=", &saveptr); (f); f = Utils::stok((char*)0, "\r\n=", &saveptr)) {
|
||||
if (! x)
|
||||
x = f;
|
||||
else if (! y)
|
||||
y = f;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if ((x)&&(y)&&(x[0])&&(y[0]))
|
||||
if ((x) && (y) && (x[0]) && (y[0]))
|
||||
globalDeviceMap[x] = y;
|
||||
}
|
||||
fclose(devmapf);
|
||||
}
|
||||
bool recalledDevice = false;
|
||||
std::map<std::string,std::string>::const_iterator gdmEntry = globalDeviceMap.find(nwids);
|
||||
std::map<std::string, std::string>::const_iterator gdmEntry = globalDeviceMap.find(nwids);
|
||||
if (gdmEntry != globalDeviceMap.end()) {
|
||||
std::string devpath("/dev/"); devpath.append(gdmEntry->second);
|
||||
if (stat(devpath.c_str(),&stattmp) == 0) {
|
||||
_fd = ::open(devpath.c_str(),O_RDWR);
|
||||
std::string devpath("/dev/");
|
||||
devpath.append(gdmEntry->second);
|
||||
if (stat(devpath.c_str(), &stattmp) == 0) {
|
||||
_fd = ::open(devpath.c_str(), O_RDWR);
|
||||
if (_fd > 0) {
|
||||
_dev = gdmEntry->second;
|
||||
recalledDevice = true;
|
||||
|
@ -378,15 +376,15 @@ MacKextEthernetTap::MacKextEthernetTap(
|
|||
}
|
||||
|
||||
// Open the first unused tap device if we didn't recall a previous one.
|
||||
if (!recalledDevice) {
|
||||
for(int i=0;i<64;++i) {
|
||||
OSUtils::ztsnprintf(devpath,sizeof(devpath),"/dev/zt%d",i);
|
||||
if (stat(devpath,&stattmp))
|
||||
if (! recalledDevice) {
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
OSUtils::ztsnprintf(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);
|
||||
_fd = ::open(devpath, O_RDWR);
|
||||
if (_fd > 0) {
|
||||
char foo[16];
|
||||
OSUtils::ztsnprintf(foo,sizeof(foo),"zt%d",i);
|
||||
OSUtils::ztsnprintf(foo, sizeof(foo), "zt%d", i);
|
||||
_dev = foo;
|
||||
break;
|
||||
}
|
||||
|
@ -396,43 +394,44 @@ MacKextEthernetTap::MacKextEthernetTap(
|
|||
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) {
|
||||
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
|
||||
OSUtils::ztsnprintf(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]);
|
||||
OSUtils::ztsnprintf(mtustr,sizeof(mtustr),"%u",_mtu);
|
||||
OSUtils::ztsnprintf(metstr,sizeof(metstr),"%u",_metric);
|
||||
OSUtils::ztsnprintf(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]);
|
||||
OSUtils::ztsnprintf(mtustr, sizeof(mtustr), "%u", _mtu);
|
||||
OSUtils::ztsnprintf(metstr, sizeof(metstr), "%u", _metric);
|
||||
long cpid = (long)fork();
|
||||
if (cpid == 0) {
|
||||
::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"lladdr",ethaddr,"mtu",mtustr,"metric",metstr,"up",(const char *)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) {
|
||||
}
|
||||
else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
::waitpid(cpid,&exitcode,0);
|
||||
::waitpid(cpid, &exitcode, 0);
|
||||
if (exitcode) {
|
||||
::close(_fd);
|
||||
throw std::runtime_error("ifconfig failure setting link-layer address and activating tap interface");
|
||||
}
|
||||
}
|
||||
|
||||
_setIpv6Stuff(_dev.c_str(),true,false);
|
||||
_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);
|
||||
fcntl(_fd, F_SETFD, fcntl(_fd, F_GETFD) | FD_CLOEXEC);
|
||||
|
||||
::pipe(_shutdownSignalPipe);
|
||||
|
||||
++globalTapsRunning;
|
||||
|
||||
globalDeviceMap[nwids] = _dev;
|
||||
devmapf = fopen((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(),"w");
|
||||
devmapf = fopen((_homePath + ZT_PATH_SEPARATOR_S + "devicemap").c_str(), "w");
|
||||
if (devmapf) {
|
||||
gdmEntry = globalDeviceMap.begin();
|
||||
while (gdmEntry != globalDeviceMap.end()) {
|
||||
fprintf(devmapf,"%s=%s\n",gdmEntry->first.c_str(),gdmEntry->second.c_str());
|
||||
fprintf(devmapf, "%s=%s\n", gdmEntry->first.c_str(), gdmEntry->second.c_str());
|
||||
++gdmEntry;
|
||||
}
|
||||
fclose(devmapf);
|
||||
|
@ -445,9 +444,9 @@ MacKextEthernetTap::~MacKextEthernetTap()
|
|||
{
|
||||
MacDNSHelper::removeDNS(_nwid);
|
||||
|
||||
::write(_shutdownSignalPipe[1],"\0",1); // causes thread to exit
|
||||
::write(_shutdownSignalPipe[1], "\0", 1); // causes thread to exit
|
||||
Thread::join(_thread);
|
||||
for (std::thread &t : _rxThreads) {
|
||||
for (std::thread& t : _rxThreads) {
|
||||
t.join();
|
||||
}
|
||||
::close(_fd);
|
||||
|
@ -457,18 +456,19 @@ MacKextEthernetTap::~MacKextEthernetTap()
|
|||
{
|
||||
Mutex::Lock _gl(globalTapCreateLock);
|
||||
if (--globalTapsRunning <= 0) {
|
||||
globalTapsRunning = 0; // sanity check -- should not be possible
|
||||
globalTapsRunning = 0; // sanity check -- should not be possible
|
||||
|
||||
char tmp[16384];
|
||||
sprintf(tmp,"%s/%s",_homePath.c_str(),"tap.kext");
|
||||
sprintf(tmp, "%s/%s", _homePath.c_str(), "tap.kext");
|
||||
long kextpid = (long)fork();
|
||||
if (kextpid == 0) {
|
||||
OSUtils::redirectUnixOutputs("/dev/null",(const char *)0);
|
||||
::execl("/sbin/kextunload","/sbin/kextunload",tmp,(const char *)0);
|
||||
OSUtils::redirectUnixOutputs("/dev/null", (const char*)0);
|
||||
::execl("/sbin/kextunload", "/sbin/kextunload", tmp, (const char*)0);
|
||||
::_exit(-1);
|
||||
} else if (kextpid > 0) {
|
||||
}
|
||||
else if (kextpid > 0) {
|
||||
int exitcode = -1;
|
||||
::waitpid(kextpid,&exitcode,0);
|
||||
::waitpid(kextpid, &exitcode, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -485,40 +485,42 @@ bool MacKextEthernetTap::enabled() const
|
|||
return _enabled;
|
||||
}
|
||||
|
||||
bool MacKextEthernetTap::addIp(const InetAddress &ip)
|
||||
bool MacKextEthernetTap::addIp(const InetAddress& ip)
|
||||
{
|
||||
if (!ip)
|
||||
if (! ip)
|
||||
return false;
|
||||
|
||||
long cpid = (long)fork();
|
||||
if (cpid == 0) {
|
||||
char tmp[128];
|
||||
::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),(ip.ss_family == AF_INET6) ? "inet6" : "inet",ip.toString(tmp),"alias",(const char *)0);
|
||||
::execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), (ip.ss_family == AF_INET6) ? "inet6" : "inet", ip.toString(tmp), "alias", (const char*)0);
|
||||
::_exit(-1);
|
||||
} else if (cpid > 0) {
|
||||
}
|
||||
else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
::waitpid(cpid,&exitcode,0);
|
||||
::waitpid(cpid, &exitcode, 0);
|
||||
return (exitcode == 0);
|
||||
} // else return false...
|
||||
} // else return false...
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacKextEthernetTap::removeIp(const InetAddress &ip)
|
||||
bool MacKextEthernetTap::removeIp(const InetAddress& ip)
|
||||
{
|
||||
if (!ip)
|
||||
if (! ip)
|
||||
return true;
|
||||
std::vector<InetAddress> allIps(ips());
|
||||
for(std::vector<InetAddress>::iterator i(allIps.begin());i!=allIps.end();++i) {
|
||||
for (std::vector<InetAddress>::iterator i(allIps.begin()); i != allIps.end(); ++i) {
|
||||
if (*i == ip) {
|
||||
long cpid = (long)fork();
|
||||
if (cpid == 0) {
|
||||
char tmp[128];
|
||||
execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),(ip.ss_family == AF_INET6) ? "inet6" : "inet",ip.toIpString(tmp),"-alias",(const char *)0);
|
||||
execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), (ip.ss_family == AF_INET6) ? "inet6" : "inet", ip.toIpString(tmp), "-alias", (const char*)0);
|
||||
_exit(-1);
|
||||
} else if (cpid > 0) {
|
||||
}
|
||||
else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
waitpid(cpid,&exitcode,0);
|
||||
waitpid(cpid, &exitcode, 0);
|
||||
return (exitcode == 0);
|
||||
}
|
||||
}
|
||||
|
@ -528,28 +530,28 @@ bool MacKextEthernetTap::removeIp(const InetAddress &ip)
|
|||
|
||||
std::vector<InetAddress> MacKextEthernetTap::ips() const
|
||||
{
|
||||
struct ifaddrs *ifa = (struct ifaddrs *)0;
|
||||
struct ifaddrs* ifa = (struct ifaddrs*)0;
|
||||
if (getifaddrs(&ifa))
|
||||
return std::vector<InetAddress>();
|
||||
|
||||
std::vector<InetAddress> r;
|
||||
|
||||
struct ifaddrs *p = ifa;
|
||||
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) {
|
||||
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.push_back(InetAddress(&(sin->sin_addr.s_addr),4,Utils::countBits((uint32_t)nm->sin_addr.s_addr)));
|
||||
} break;
|
||||
struct sockaddr_in* sin = (struct sockaddr_in*)p->ifa_addr;
|
||||
struct sockaddr_in* nm = (struct sockaddr_in*)p->ifa_netmask;
|
||||
r.push_back(InetAddress(&(sin->sin_addr.s_addr), 4, Utils::countBits((uint32_t)nm->sin_addr.s_addr)));
|
||||
} break;
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *sin = (struct sockaddr_in6 *)p->ifa_addr;
|
||||
struct sockaddr_in6 *nm = (struct sockaddr_in6 *)p->ifa_netmask;
|
||||
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.push_back(InetAddress(sin->sin6_addr.s6_addr,16,Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3])));
|
||||
} break;
|
||||
memcpy(b, nm->sin6_addr.s6_addr, sizeof(b));
|
||||
r.push_back(InetAddress(sin->sin6_addr.s6_addr, 16, Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3])));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
p = p->ifa_next;
|
||||
|
@ -558,22 +560,22 @@ std::vector<InetAddress> MacKextEthernetTap::ips() const
|
|||
if (ifa)
|
||||
freeifaddrs(ifa);
|
||||
|
||||
std::sort(r.begin(),r.end());
|
||||
r.erase(std::unique(r.begin(),r.end()),r.end());
|
||||
std::sort(r.begin(), r.end());
|
||||
r.erase(std::unique(r.begin(), r.end()), r.end());
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void MacKextEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
|
||||
void MacKextEthernetTap::put(const MAC& from, const MAC& to, unsigned int etherType, const void* data, unsigned int len)
|
||||
{
|
||||
char putBuf[ZT_MAX_MTU + 64];
|
||||
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);
|
||||
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);
|
||||
::write(_fd, putBuf, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -582,23 +584,23 @@ std::string MacKextEthernetTap::deviceName() const
|
|||
return _dev;
|
||||
}
|
||||
|
||||
void MacKextEthernetTap::setFriendlyName(const char *friendlyName)
|
||||
void MacKextEthernetTap::setFriendlyName(const char* friendlyName)
|
||||
{
|
||||
}
|
||||
|
||||
void MacKextEthernetTap::scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed)
|
||||
void MacKextEthernetTap::scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed)
|
||||
{
|
||||
std::vector<MulticastGroup> newGroups;
|
||||
|
||||
struct _intl_ifmaddrs *ifmap = (struct _intl_ifmaddrs *)0;
|
||||
if (!_intl_getifmaddrs(&ifmap)) {
|
||||
struct _intl_ifmaddrs *p = ifmap;
|
||||
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.push_back(MulticastGroup(MAC(la->sdl_data + la->sdl_nlen,6),0));
|
||||
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.push_back(MulticastGroup(MAC(la->sdl_data + la->sdl_nlen, 6), 0));
|
||||
}
|
||||
p = p->ifma_next;
|
||||
}
|
||||
|
@ -606,18 +608,18 @@ void MacKextEthernetTap::scanMulticastGroups(std::vector<MulticastGroup> &added,
|
|||
}
|
||||
|
||||
std::vector<InetAddress> allIps(ips());
|
||||
for(std::vector<InetAddress>::iterator ip(allIps.begin());ip!=allIps.end();++ip)
|
||||
for (std::vector<InetAddress>::iterator ip(allIps.begin()); ip != allIps.end(); ++ip)
|
||||
newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip));
|
||||
|
||||
std::sort(newGroups.begin(),newGroups.end());
|
||||
std::unique(newGroups.begin(),newGroups.end());
|
||||
std::sort(newGroups.begin(), newGroups.end());
|
||||
std::unique(newGroups.begin(), newGroups.end());
|
||||
|
||||
for(std::vector<MulticastGroup>::iterator m(newGroups.begin());m!=newGroups.end();++m) {
|
||||
if (!std::binary_search(_multicastGroups.begin(),_multicastGroups.end(),*m))
|
||||
for (std::vector<MulticastGroup>::iterator m(newGroups.begin()); m != newGroups.end(); ++m) {
|
||||
if (! std::binary_search(_multicastGroups.begin(), _multicastGroups.end(), *m))
|
||||
added.push_back(*m);
|
||||
}
|
||||
for(std::vector<MulticastGroup>::iterator m(_multicastGroups.begin());m!=_multicastGroups.end();++m) {
|
||||
if (!std::binary_search(newGroups.begin(),newGroups.end(),*m))
|
||||
for (std::vector<MulticastGroup>::iterator m(_multicastGroups.begin()); m != _multicastGroups.end(); ++m) {
|
||||
if (! std::binary_search(newGroups.begin(), newGroups.end(), *m))
|
||||
removed.push_back(*m);
|
||||
}
|
||||
|
||||
|
@ -631,59 +633,60 @@ void MacKextEthernetTap::setMtu(unsigned int mtu)
|
|||
long cpid = (long)fork();
|
||||
if (cpid == 0) {
|
||||
char tmp[64];
|
||||
OSUtils::ztsnprintf(tmp,sizeof(tmp),"%u",mtu);
|
||||
execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"mtu",tmp,(const char *)0);
|
||||
OSUtils::ztsnprintf(tmp, sizeof(tmp), "%u", mtu);
|
||||
execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "mtu", tmp, (const char*)0);
|
||||
_exit(-1);
|
||||
} else if (cpid > 0) {
|
||||
}
|
||||
else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
waitpid(cpid,&exitcode,0);
|
||||
waitpid(cpid, &exitcode, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MacKextEthernetTap::threadMain()
|
||||
throw()
|
||||
void MacKextEthernetTap::threadMain() throw()
|
||||
{
|
||||
fd_set readfds,nullfds;
|
||||
MAC to,from;
|
||||
int n,nfds,r;
|
||||
fd_set readfds, nullfds;
|
||||
MAC to, from;
|
||||
int n, nfds, r;
|
||||
char getBuf[ZT_MAX_MTU + 64];
|
||||
|
||||
Thread::sleep(500);
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_ZERO(&nullfds);
|
||||
nfds = (int)std::max(_shutdownSignalPipe[0],_fd) + 1;
|
||||
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);
|
||||
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
|
||||
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 (FD_ISSET(_fd, &readfds)) {
|
||||
n = (int)::read(_fd, getBuf + r, sizeof(getBuf) - r);
|
||||
if (n < 0) {
|
||||
if ((errno != EINTR)&&(errno != ETIMEDOUT))
|
||||
if ((errno != EINTR) && (errno != ETIMEDOUT))
|
||||
break;
|
||||
} else {
|
||||
}
|
||||
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
|
||||
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]);
|
||||
to.setTo(getBuf, 6);
|
||||
from.setTo(getBuf + 6, 6);
|
||||
unsigned int etherType = ntohs(((const uint16_t*)getBuf)[6]);
|
||||
// TODO: VLAN support
|
||||
_handler(_arg,(void *)0,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14);
|
||||
_handler(_arg, (void*)0, _nwid, from, to, etherType, 0, (const void*)(getBuf + 14), r - 14);
|
||||
}
|
||||
|
||||
r = 0;
|
||||
|
@ -693,9 +696,9 @@ void MacKextEthernetTap::threadMain()
|
|||
}
|
||||
}
|
||||
|
||||
void MacKextEthernetTap::setDns(const char *domain, const std::vector<InetAddress> &servers)
|
||||
void MacKextEthernetTap::setDns(const char* domain, const std::vector<InetAddress>& servers)
|
||||
{
|
||||
MacDNSHelper::setDNS(_nwid, domain, servers);
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -14,58 +14,53 @@
|
|||
#ifndef ZT_MacKextEthernetTap_HPP
|
||||
#define ZT_MacKextEthernetTap_HPP
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/InetAddress.hpp"
|
||||
#include "../node/MAC.hpp"
|
||||
#include "../node/MulticastGroup.hpp"
|
||||
#include "EthernetTap.hpp"
|
||||
#include "Thread.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/MAC.hpp"
|
||||
#include "../node/InetAddress.hpp"
|
||||
#include "../node/MulticastGroup.hpp"
|
||||
|
||||
#include "Thread.hpp"
|
||||
#include "EthernetTap.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class MacKextEthernetTap : public EthernetTap
|
||||
{
|
||||
public:
|
||||
class MacKextEthernetTap : public EthernetTap {
|
||||
public:
|
||||
MacKextEthernetTap(
|
||||
const char *homePath,
|
||||
const MAC &mac,
|
||||
const char* homePath,
|
||||
const MAC& mac,
|
||||
unsigned int mtu,
|
||||
unsigned int metric,
|
||||
uint64_t nwid,
|
||||
const char *friendlyName,
|
||||
void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
|
||||
void *arg);
|
||||
const char* friendlyName,
|
||||
void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
|
||||
void* arg);
|
||||
|
||||
virtual ~MacKextEthernetTap();
|
||||
|
||||
virtual void setEnabled(bool en);
|
||||
virtual bool enabled() const;
|
||||
virtual bool addIp(const InetAddress &ip);
|
||||
virtual bool removeIp(const InetAddress &ip);
|
||||
virtual bool addIp(const InetAddress& ip);
|
||||
virtual bool removeIp(const InetAddress& ip);
|
||||
virtual std::vector<InetAddress> ips() const;
|
||||
virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len);
|
||||
virtual void put(const MAC& from, const MAC& to, unsigned int etherType, const void* data, unsigned int len);
|
||||
virtual std::string deviceName() const;
|
||||
virtual void setFriendlyName(const char *friendlyName);
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
|
||||
virtual void setFriendlyName(const char* friendlyName);
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed);
|
||||
virtual void setMtu(unsigned int mtu);
|
||||
virtual void setDns(const char *domain, const std::vector<InetAddress> &servers);
|
||||
virtual void setDns(const char* domain, const std::vector<InetAddress>& servers);
|
||||
|
||||
void threadMain() throw();
|
||||
|
||||
void threadMain()
|
||||
throw();
|
||||
|
||||
private:
|
||||
void (*_handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
|
||||
void *_arg;
|
||||
private:
|
||||
void (*_handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int);
|
||||
void* _arg;
|
||||
uint64_t _nwid;
|
||||
Thread _thread;
|
||||
std::string _homePath;
|
||||
|
@ -79,6 +74,6 @@ private:
|
|||
std::vector<std::thread> _rxThreads;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,20 +20,20 @@
|
|||
#include <string.h>
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <netioapi.h>
|
||||
#include <IPHlpApi.h>
|
||||
#include <netioapi.h>
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#ifdef __UNIX_LIKE__
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#ifndef ZT_SDK
|
||||
#include <net/route.h>
|
||||
#endif
|
||||
|
@ -45,11 +45,11 @@
|
|||
#include <ifaddrs.h>
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
#include "ManagedRoute.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#include "ManagedRoute.hpp"
|
||||
#include <vector>
|
||||
#ifdef __LINUX__
|
||||
#include "LinuxNetLink.hpp"
|
||||
#endif
|
||||
|
@ -62,7 +62,7 @@ namespace {
|
|||
|
||||
// Fork a target into two more specific targets e.g. 0.0.0.0/0 -> 0.0.0.0/1, 128.0.0.0/1
|
||||
// If the target is already maximally-specific, 'right' will be unchanged and 'left' will be 't'
|
||||
static void _forkTarget(const InetAddress &t,InetAddress &left,InetAddress &right)
|
||||
static void _forkTarget(const InetAddress& t, InetAddress& left, InetAddress& right)
|
||||
{
|
||||
const unsigned int bits = t.netmaskBits() + 1;
|
||||
left = t;
|
||||
|
@ -70,26 +70,28 @@ static void _forkTarget(const InetAddress &t,InetAddress &left,InetAddress &righ
|
|||
if (bits <= 32) {
|
||||
left.setPort(bits);
|
||||
right = t;
|
||||
reinterpret_cast<struct sockaddr_in *>(&right)->sin_addr.s_addr ^= Utils::hton((uint32_t)(1 << (32 - bits)));
|
||||
reinterpret_cast<struct sockaddr_in*>(&right)->sin_addr.s_addr ^= Utils::hton((uint32_t)(1 << (32 - bits)));
|
||||
right.setPort(bits);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
right.zero();
|
||||
}
|
||||
} else if (t.ss_family == AF_INET6) {
|
||||
}
|
||||
else if (t.ss_family == AF_INET6) {
|
||||
if (bits <= 128) {
|
||||
left.setPort(bits);
|
||||
right = t;
|
||||
uint8_t *b = reinterpret_cast<uint8_t *>(reinterpret_cast<struct sockaddr_in6 *>(&right)->sin6_addr.s6_addr);
|
||||
uint8_t* b = reinterpret_cast<uint8_t*>(reinterpret_cast<struct sockaddr_in6*>(&right)->sin6_addr.s6_addr);
|
||||
b[bits / 8] ^= 1 << (8 - (bits % 8));
|
||||
right.setPort(bits);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
right.zero();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct _RTE
|
||||
{
|
||||
struct _RTE {
|
||||
InetAddress target;
|
||||
InetAddress via;
|
||||
char device[128];
|
||||
|
@ -98,11 +100,11 @@ struct _RTE
|
|||
bool isDefault;
|
||||
};
|
||||
|
||||
#ifdef __BSD__ // ------------------------------------------------------------
|
||||
#ifdef __BSD__ // ------------------------------------------------------------
|
||||
#define ZT_ROUTING_SUPPORT_FOUND 1
|
||||
|
||||
#ifndef ZT_SDK
|
||||
static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains)
|
||||
static std::vector<_RTE> _getRTEs(const InetAddress& target, bool contains)
|
||||
{
|
||||
std::vector<_RTE> rtes;
|
||||
int mib[6];
|
||||
|
@ -114,29 +116,29 @@ static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains)
|
|||
mib[3] = 0;
|
||||
mib[4] = NET_RT_DUMP;
|
||||
mib[5] = 0;
|
||||
if (!sysctl(mib,6,NULL,&needed,NULL,0)) {
|
||||
if (! sysctl(mib, 6, NULL, &needed, NULL, 0)) {
|
||||
if (needed <= 0)
|
||||
return rtes;
|
||||
|
||||
char *buf = (char *)::malloc(needed);
|
||||
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 (! 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;
|
||||
|
||||
InetAddress sa_t,sa_v;
|
||||
InetAddress sa_t, sa_v;
|
||||
int deviceIndex = -9999;
|
||||
bool isDefault = false;
|
||||
|
||||
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)) {
|
||||
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)) {
|
||||
int which = 0;
|
||||
while (saptr < saend) {
|
||||
struct sockaddr *sa = (struct sockaddr *)saptr;
|
||||
struct sockaddr* sa = (struct sockaddr*)saptr;
|
||||
unsigned int salen = sa->sa_len;
|
||||
if (!salen)
|
||||
if (! salen)
|
||||
break;
|
||||
|
||||
// Skip missing fields in rtm_addrs bit field
|
||||
|
@ -150,32 +152,33 @@ static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains)
|
|||
break;
|
||||
|
||||
rtm->rtm_addrs >>= 1;
|
||||
switch(which++) {
|
||||
switch (which++) {
|
||||
case 0:
|
||||
//printf("RTA_DST\n");
|
||||
// printf("RTA_DST\n");
|
||||
if (sa->sa_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
|
||||
if ((sin6->sin6_addr.s6_addr[0] == 0xfe)&&((sin6->sin6_addr.s6_addr[1] & 0xc0) == 0x80)) {
|
||||
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)sa;
|
||||
if ((sin6->sin6_addr.s6_addr[0] == 0xfe) && ((sin6->sin6_addr.s6_addr[1] & 0xc0) == 0x80)) {
|
||||
// BSD uses this fucking strange in-band signaling method to encode device scope IDs for IPv6 addresses... probably a holdover from very early versions of the spec.
|
||||
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)
|
||||
if (! sin6->sin6_scope_id)
|
||||
sin6->sin6_scope_id = interfaceIndex;
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
isDefault = IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && !(rtm->rtm_flags & RTF_IFSCOPE);
|
||||
isDefault = IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && ! (rtm->rtm_flags & RTF_IFSCOPE);
|
||||
#endif
|
||||
} else {
|
||||
struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
|
||||
}
|
||||
else {
|
||||
struct sockaddr_in* sin4 = (struct sockaddr_in*)sa;
|
||||
isDefault = sin4->sin_addr.s_addr == 0;
|
||||
}
|
||||
sa_t = *sa;
|
||||
break;
|
||||
case 1:
|
||||
//printf("RTA_GATEWAY\n");
|
||||
switch(sa->sa_family) {
|
||||
// printf("RTA_GATEWAY\n");
|
||||
switch (sa->sa_family) {
|
||||
case AF_LINK:
|
||||
// deviceIndex = (int)((const struct sockaddr_dl *)sa)->sdl_index;
|
||||
case AF_INET:
|
||||
|
@ -185,53 +188,54 @@ static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains)
|
|||
}
|
||||
break;
|
||||
case 2: {
|
||||
//printf("RTA_NETMASK\n");
|
||||
// printf("RTA_NETMASK\n");
|
||||
if (sa_t.ss_family == AF_INET6) {
|
||||
salen = sizeof(struct sockaddr_in6);
|
||||
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];
|
||||
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;
|
||||
else
|
||||
break;
|
||||
}
|
||||
sa_t.setPort(bits);
|
||||
} else if (sa_t.ss_family == AF_INET) {
|
||||
salen = sizeof(struct sockaddr_in);
|
||||
sa_t.setPort((unsigned int)Utils::countBits((uint32_t)((const struct sockaddr_in *)sa)->sin_addr.s_addr));
|
||||
}
|
||||
} 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;
|
||||
*/
|
||||
else if (sa_t.ss_family == AF_INET) {
|
||||
salen = sizeof(struct sockaddr_in);
|
||||
sa_t.setPort((unsigned int)Utils::countBits((uint32_t)((const struct sockaddr_in*)sa)->sin_addr.s_addr));
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
||||
|
||||
deviceIndex = rtm->rtm_index;
|
||||
|
||||
|
||||
if (((contains)&&(sa_t.containsAddress(target)))||(sa_t == target)) {
|
||||
if (((contains) && (sa_t.containsAddress(target))) || (sa_t == target)) {
|
||||
rtes.push_back(_RTE());
|
||||
rtes.back().target = sa_t;
|
||||
rtes.back().via = sa_v;
|
||||
rtes.back().isDefault = isDefault;
|
||||
if (deviceIndex >= 0) {
|
||||
if_indextoname(deviceIndex,rtes.back().device);
|
||||
} else {
|
||||
if_indextoname(deviceIndex, rtes.back().device);
|
||||
}
|
||||
else {
|
||||
rtes.back().device[0] = (char)0;
|
||||
}
|
||||
rtes.back().metric = ((int)rtm->rtm_rmx.rmx_hopcount < 0) ? 0 : (int)rtm->rtm_rmx.rmx_hopcount;
|
||||
|
@ -250,60 +254,64 @@ static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void _routeCmd(const char *op,const InetAddress &target,const InetAddress &via,const char *ifscope,const char *localInterface)
|
||||
static void _routeCmd(const char* op, const InetAddress& target, const InetAddress& via, const char* ifscope, const char* localInterface)
|
||||
{
|
||||
// char f1[1024],f2[1024]; printf("cmd %s %s %s %s %s\n",op,target.toString(f1),via.toString(f2),ifscope,localInterface);
|
||||
long p = (long)fork();
|
||||
if (p > 0) {
|
||||
int exitcode = -1;
|
||||
::waitpid(p,&exitcode,0);
|
||||
} else if (p == 0) {
|
||||
::waitpid(p, &exitcode, 0);
|
||||
}
|
||||
else if (p == 0) {
|
||||
::close(STDOUT_FILENO);
|
||||
::close(STDERR_FILENO);
|
||||
char ttmp[64];
|
||||
char iptmp[64];
|
||||
if (via) {
|
||||
if ((ifscope)&&(ifscope[0])) {
|
||||
if ((ifscope) && (ifscope[0])) {
|
||||
#ifdef ZT_TRACE
|
||||
fprintf(stderr, "DEBUG: route %s -ifscope %s %s %s" ZT_EOL_S, ifscope,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString(ttmp),via.toIpString(iptmp));
|
||||
fprintf(stderr, "DEBUG: route %s -ifscope %s %s %s" ZT_EOL_S, ifscope, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), via.toIpString(iptmp));
|
||||
#endif
|
||||
::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,"-ifscope",ifscope,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString(ttmp),via.toIpString(iptmp),(const char *)0);
|
||||
} else {
|
||||
#ifdef ZT_TRACE
|
||||
fprintf(stderr, "DEBUG: route %s %s %s %s" ZT_EOL_S, op,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString(ttmp),via.toIpString(iptmp));
|
||||
#endif
|
||||
::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString(ttmp),via.toIpString(iptmp),(const char *)0);
|
||||
::execl(ZT_BSD_ROUTE_CMD, ZT_BSD_ROUTE_CMD, op, "-ifscope", ifscope, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), via.toIpString(iptmp), (const char*)0);
|
||||
}
|
||||
} else if ((localInterface)&&(localInterface[0])) {
|
||||
if ((ifscope)&&(ifscope[0])) {
|
||||
else {
|
||||
#ifdef ZT_TRACE
|
||||
fprintf(stderr, "DEBUG: route %s -ifscope %s %s %s -interface %s" ZT_EOL_S, op, ifscope,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString(ttmp),localInterface);
|
||||
fprintf(stderr, "DEBUG: route %s %s %s %s" ZT_EOL_S, op, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), via.toIpString(iptmp));
|
||||
#endif
|
||||
::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,"-ifscope",ifscope,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString(ttmp),"-interface",localInterface,(const char *)0);
|
||||
} else {
|
||||
::execl(ZT_BSD_ROUTE_CMD, ZT_BSD_ROUTE_CMD, op, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), via.toIpString(iptmp), (const char*)0);
|
||||
}
|
||||
}
|
||||
else if ((localInterface) && (localInterface[0])) {
|
||||
if ((ifscope) && (ifscope[0])) {
|
||||
#ifdef ZT_TRACE
|
||||
fprintf(stderr, "DEBUG: route %s %s %s -interface %s" ZT_EOL_S, op,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString(ttmp),localInterface);
|
||||
fprintf(stderr, "DEBUG: route %s -ifscope %s %s %s -interface %s" ZT_EOL_S, op, ifscope, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), localInterface);
|
||||
#endif
|
||||
::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString(ttmp),"-interface",localInterface,(const char *)0);
|
||||
::execl(ZT_BSD_ROUTE_CMD, ZT_BSD_ROUTE_CMD, op, "-ifscope", ifscope, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), "-interface", localInterface, (const char*)0);
|
||||
}
|
||||
else {
|
||||
#ifdef ZT_TRACE
|
||||
fprintf(stderr, "DEBUG: route %s %s %s -interface %s" ZT_EOL_S, op, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), localInterface);
|
||||
#endif
|
||||
::execl(ZT_BSD_ROUTE_CMD, ZT_BSD_ROUTE_CMD, op, ((target.ss_family == AF_INET6) ? "-inet6" : "-inet"), target.toString(ttmp), "-interface", localInterface, (const char*)0);
|
||||
}
|
||||
}
|
||||
::_exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __BSD__ ------------------------------------------------------------
|
||||
#endif // __BSD__ ------------------------------------------------------------
|
||||
|
||||
#ifdef __LINUX__ // ----------------------------------------------------------
|
||||
#ifdef __LINUX__ // ----------------------------------------------------------
|
||||
#define ZT_ROUTING_SUPPORT_FOUND 1
|
||||
|
||||
// This has been replaced by LinuxNetLink
|
||||
|
||||
#endif // __LINUX__ ----------------------------------------------------------
|
||||
#endif // __LINUX__ ----------------------------------------------------------
|
||||
|
||||
#ifdef __WINDOWS__ // --------------------------------------------------------
|
||||
#ifdef __WINDOWS__ // --------------------------------------------------------
|
||||
#define ZT_ROUTING_SUPPORT_FOUND 1
|
||||
|
||||
static bool _winRoute(bool del,const NET_LUID &interfaceLuid,const NET_IFINDEX &interfaceIndex,const InetAddress &target,const InetAddress &via)
|
||||
static bool _winRoute(bool del, const NET_LUID& interfaceLuid, const NET_IFINDEX& interfaceIndex, const InetAddress& target, const InetAddress& via)
|
||||
{
|
||||
MIB_IPFORWARD_ROW2 rtrow;
|
||||
InitializeIpForwardEntry(&rtrow);
|
||||
|
@ -312,22 +320,24 @@ static bool _winRoute(bool del,const NET_LUID &interfaceLuid,const NET_IFINDEX &
|
|||
if (target.ss_family == AF_INET) {
|
||||
rtrow.DestinationPrefix.Prefix.si_family = AF_INET;
|
||||
rtrow.DestinationPrefix.Prefix.Ipv4.sin_family = AF_INET;
|
||||
rtrow.DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast<const struct sockaddr_in *>(&target)->sin_addr.S_un.S_addr;
|
||||
rtrow.DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast<const struct sockaddr_in*>(&target)->sin_addr.S_un.S_addr;
|
||||
if (via.ss_family == AF_INET) {
|
||||
rtrow.NextHop.si_family = AF_INET;
|
||||
rtrow.NextHop.Ipv4.sin_family = AF_INET;
|
||||
rtrow.NextHop.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast<const struct sockaddr_in *>(&via)->sin_addr.S_un.S_addr;
|
||||
rtrow.NextHop.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast<const struct sockaddr_in*>(&via)->sin_addr.S_un.S_addr;
|
||||
}
|
||||
} else if (target.ss_family == AF_INET6) {
|
||||
}
|
||||
else if (target.ss_family == AF_INET6) {
|
||||
rtrow.DestinationPrefix.Prefix.si_family = AF_INET6;
|
||||
rtrow.DestinationPrefix.Prefix.Ipv6.sin6_family = AF_INET6;
|
||||
memcpy(rtrow.DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Byte,reinterpret_cast<const struct sockaddr_in6 *>(&target)->sin6_addr.u.Byte,16);
|
||||
memcpy(rtrow.DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Byte, reinterpret_cast<const struct sockaddr_in6*>(&target)->sin6_addr.u.Byte, 16);
|
||||
if (via.ss_family == AF_INET6) {
|
||||
rtrow.NextHop.si_family = AF_INET6;
|
||||
rtrow.NextHop.Ipv6.sin6_family = AF_INET6;
|
||||
memcpy(rtrow.NextHop.Ipv6.sin6_addr.u.Byte,reinterpret_cast<const struct sockaddr_in6 *>(&via)->sin6_addr.u.Byte,16);
|
||||
memcpy(rtrow.NextHop.Ipv6.sin6_addr.u.Byte, reinterpret_cast<const struct sockaddr_in6*>(&via)->sin6_addr.u.Byte, 16);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
rtrow.DestinationPrefix.PrefixLength = target.netmaskBits();
|
||||
|
@ -344,19 +354,22 @@ static bool _winRoute(bool del,const NET_LUID &interfaceLuid,const NET_IFINDEX &
|
|||
rtrow.Origin = NlroManual;
|
||||
if (del) {
|
||||
return (DeleteIpForwardEntry2(&rtrow) == NO_ERROR);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
NTSTATUS r = CreateIpForwardEntry2(&rtrow);
|
||||
if (r == NO_ERROR) {
|
||||
return true;
|
||||
} else if (r == ERROR_OBJECT_ALREADY_EXISTS) {
|
||||
}
|
||||
else if (r == ERROR_OBJECT_ALREADY_EXISTS) {
|
||||
return (SetIpForwardEntry2(&rtrow) == NO_ERROR);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool _winHasRoute(const NET_LUID &interfaceLuid, const NET_IFINDEX &interfaceIndex, const InetAddress &target, const InetAddress &via)
|
||||
static bool _winHasRoute(const NET_LUID& interfaceLuid, const NET_IFINDEX& interfaceIndex, const InetAddress& target, const InetAddress& via)
|
||||
{
|
||||
MIB_IPFORWARD_ROW2 rtrow;
|
||||
InitializeIpForwardEntry(&rtrow);
|
||||
|
@ -365,22 +378,24 @@ static bool _winHasRoute(const NET_LUID &interfaceLuid, const NET_IFINDEX &inter
|
|||
if (target.ss_family == AF_INET) {
|
||||
rtrow.DestinationPrefix.Prefix.si_family = AF_INET;
|
||||
rtrow.DestinationPrefix.Prefix.Ipv4.sin_family = AF_INET;
|
||||
rtrow.DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast<const struct sockaddr_in *>(&target)->sin_addr.S_un.S_addr;
|
||||
rtrow.DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast<const struct sockaddr_in*>(&target)->sin_addr.S_un.S_addr;
|
||||
if (via.ss_family == AF_INET) {
|
||||
rtrow.NextHop.si_family = AF_INET;
|
||||
rtrow.NextHop.Ipv4.sin_family = AF_INET;
|
||||
rtrow.NextHop.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast<const struct sockaddr_in *>(&via)->sin_addr.S_un.S_addr;
|
||||
rtrow.NextHop.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast<const struct sockaddr_in*>(&via)->sin_addr.S_un.S_addr;
|
||||
}
|
||||
} else if (target.ss_family == AF_INET6) {
|
||||
}
|
||||
else if (target.ss_family == AF_INET6) {
|
||||
rtrow.DestinationPrefix.Prefix.si_family = AF_INET6;
|
||||
rtrow.DestinationPrefix.Prefix.Ipv6.sin6_family = AF_INET6;
|
||||
memcpy(rtrow.DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Byte, reinterpret_cast<const struct sockaddr_in6 *>(&target)->sin6_addr.u.Byte, 16);
|
||||
memcpy(rtrow.DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Byte, reinterpret_cast<const struct sockaddr_in6*>(&target)->sin6_addr.u.Byte, 16);
|
||||
if (via.ss_family == AF_INET6) {
|
||||
rtrow.NextHop.si_family = AF_INET6;
|
||||
rtrow.NextHop.Ipv6.sin6_family = AF_INET6;
|
||||
memcpy(rtrow.NextHop.Ipv6.sin6_addr.u.Byte, reinterpret_cast<const struct sockaddr_in6 *>(&via)->sin6_addr.u.Byte, 16);
|
||||
memcpy(rtrow.NextHop.Ipv6.sin6_addr.u.Byte, reinterpret_cast<const struct sockaddr_in6*>(&via)->sin6_addr.u.Byte, 16);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
rtrow.DestinationPrefix.PrefixLength = target.netmaskBits();
|
||||
|
@ -388,15 +403,16 @@ static bool _winHasRoute(const NET_LUID &interfaceLuid, const NET_IFINDEX &inter
|
|||
return (GetIpForwardEntry2(&rtrow) == NO_ERROR);
|
||||
}
|
||||
|
||||
#endif // __WINDOWS__ --------------------------------------------------------
|
||||
#endif // __WINDOWS__ --------------------------------------------------------
|
||||
|
||||
#ifndef ZT_ROUTING_SUPPORT_FOUND
|
||||
#error "ManagedRoute.cpp has no support for managing routes on this platform! You'll need to check and see if one of the existing ones will work and make sure proper defines are set, or write one. Please do a GitHub pull request if you do this for a new OS."
|
||||
#error \
|
||||
"ManagedRoute.cpp has no support for managing routes on this platform! You'll need to check and see if one of the existing ones will work and make sure proper defines are set, or write one. Please do a GitHub pull request if you do this for a new OS."
|
||||
#endif
|
||||
|
||||
} // anonymous namespace
|
||||
} // anonymous namespace
|
||||
|
||||
ManagedRoute::ManagedRoute(const InetAddress &target,const InetAddress &via,const InetAddress &src,const char *device)
|
||||
ManagedRoute::ManagedRoute(const InetAddress& target, const InetAddress& via, const InetAddress& src, const char* device)
|
||||
{
|
||||
_target = target;
|
||||
_via = via;
|
||||
|
@ -404,17 +420,19 @@ ManagedRoute::ManagedRoute(const InetAddress &target,const InetAddress &via,cons
|
|||
|
||||
if (_via.ss_family == AF_INET) {
|
||||
_via.setPort(32);
|
||||
} else if (_via.ss_family == AF_INET6) {
|
||||
}
|
||||
else if (_via.ss_family == AF_INET6) {
|
||||
_via.setPort(128);
|
||||
}
|
||||
|
||||
if (_src.ss_family == AF_INET) {
|
||||
_src.setPort(32);
|
||||
} else if (_src.ss_family == AF_INET6) {
|
||||
}
|
||||
else if (_src.ss_family == AF_INET6) {
|
||||
_src.setPort(128);
|
||||
}
|
||||
|
||||
Utils::scopy(_device,sizeof(_device),device);
|
||||
Utils::scopy(_device, sizeof(_device), device);
|
||||
_systemDevice[0] = (char)0;
|
||||
}
|
||||
|
||||
|
@ -440,26 +458,27 @@ bool ManagedRoute::sync()
|
|||
{
|
||||
#ifdef __WINDOWS__
|
||||
NET_LUID interfaceLuid;
|
||||
interfaceLuid.Value = (ULONG64)Utils::hexStrToU64(_device); // on Windows we use the hex LUID as the "interface name" for ManagedRoute
|
||||
interfaceLuid.Value = (ULONG64)Utils::hexStrToU64(_device); // on Windows we use the hex LUID as the "interface name" for ManagedRoute
|
||||
NET_IFINDEX interfaceIndex = -1;
|
||||
if (ConvertInterfaceLuidToIndex(&interfaceLuid,&interfaceIndex) != NO_ERROR)
|
||||
if (ConvertInterfaceLuidToIndex(&interfaceLuid, &interfaceIndex) != NO_ERROR)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
InetAddress leftt,rightt;
|
||||
if (_target.netmaskBits() == 0) // bifurcate only the default route
|
||||
_forkTarget(_target,leftt,rightt);
|
||||
else leftt = _target;
|
||||
InetAddress leftt, rightt;
|
||||
if (_target.netmaskBits() == 0) // bifurcate only the default route
|
||||
_forkTarget(_target, leftt, rightt);
|
||||
else
|
||||
leftt = _target;
|
||||
|
||||
#ifdef __BSD__ // ------------------------------------------------------------
|
||||
#ifdef __BSD__ // ------------------------------------------------------------
|
||||
|
||||
if (_device[0]) {
|
||||
bool haveDevice = false;
|
||||
struct ifaddrs *ifa = (struct ifaddrs *)0;
|
||||
if (!getifaddrs(&ifa)) {
|
||||
struct ifaddrs *p = ifa;
|
||||
struct ifaddrs* ifa = (struct ifaddrs*)0;
|
||||
if (! getifaddrs(&ifa)) {
|
||||
struct ifaddrs* p = ifa;
|
||||
while (p) {
|
||||
if ((p->ifa_name)&&(!strcmp(_device, p->ifa_name))) {
|
||||
if ((p->ifa_name) && (! strcmp(_device, p->ifa_name))) {
|
||||
haveDevice = true;
|
||||
break;
|
||||
}
|
||||
|
@ -467,112 +486,113 @@ bool ManagedRoute::sync()
|
|||
}
|
||||
freeifaddrs(ifa);
|
||||
}
|
||||
if (!haveDevice)
|
||||
if (! haveDevice)
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<_RTE> rtes(_getRTEs(_target,false));
|
||||
std::vector<_RTE> rtes(_getRTEs(_target, false));
|
||||
|
||||
bool hasRoute = false;
|
||||
for(std::vector<_RTE>::iterator r(rtes.begin());r!=rtes.end();++r) {
|
||||
hasRoute = _target == r->target && _via.ipOnly() == r->via.ipOnly() && (strcmp(r->device,_device) == 0);
|
||||
if (hasRoute) { break; }
|
||||
for (std::vector<_RTE>::iterator r(rtes.begin()); r != rtes.end(); ++r) {
|
||||
hasRoute = _target == r->target && _via.ipOnly() == r->via.ipOnly() && (strcmp(r->device, _device) == 0);
|
||||
if (hasRoute) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// char buf[255];
|
||||
// fprintf(stderr, "hasRoute %d %s\n", !!hasRoute, _target.toString(buf));
|
||||
|
||||
|
||||
if (!hasRoute) {
|
||||
if (_target && _target.netmaskBits() == 0) { // Allow Default
|
||||
if (! hasRoute) {
|
||||
if (_target && _target.netmaskBits() == 0) { // Allow Default
|
||||
InetAddress newSystemVia;
|
||||
char newSystemDevice[128];
|
||||
newSystemDevice[0] = (char)0;
|
||||
|
||||
// if our routes got deleted
|
||||
// delete the systemd via that we had added with -ifscope
|
||||
if (_systemVia && !!_systemDevice[0]) {
|
||||
_routeCmd("delete",_target,_systemVia,_systemDevice,(const char *)0);
|
||||
if (_systemVia && ! ! _systemDevice[0]) {
|
||||
_routeCmd("delete", _target, _systemVia, _systemDevice, (const char*)0);
|
||||
}
|
||||
|
||||
_systemVia = newSystemVia;
|
||||
Utils::scopy(_systemDevice,sizeof(_systemDevice),newSystemDevice);
|
||||
Utils::scopy(_systemDevice, sizeof(_systemDevice), newSystemDevice);
|
||||
// If macos has a network hiccup, it deletes what the route we set, and it's own physical routes.
|
||||
// if !hasRoute (our 0.0.0.0 has been deleted), the OS has changed stuff
|
||||
// So don't assume _systemX are valid anymore. Always get for _system{Via,Device}
|
||||
|
||||
// Find system default route that this route should override
|
||||
// We need to put it back when default route is turned off
|
||||
for(std::vector<_RTE>::iterator r(rtes.begin());r!=rtes.end();++r) {
|
||||
for (std::vector<_RTE>::iterator r(rtes.begin()); r != rtes.end(); ++r) {
|
||||
if (r->via) {
|
||||
if ( r->isDefault == 1 && (strcmp(r->device,_device) != 0) ) {
|
||||
|
||||
if (r->isDefault == 1 && (strcmp(r->device, _device) != 0)) {
|
||||
// char buf[255];
|
||||
// fprintf(stderr, "system device1 %s %s\n", r->via.toString(buf), r->device);
|
||||
|
||||
newSystemVia = r->via;
|
||||
Utils::scopy(newSystemDevice,sizeof(newSystemDevice),r->device);
|
||||
Utils::scopy(newSystemDevice, sizeof(newSystemDevice), r->device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newSystemVia) { _systemVia = newSystemVia; }
|
||||
if (newSystemVia) {
|
||||
_systemVia = newSystemVia;
|
||||
}
|
||||
if (newSystemDevice[0]) {
|
||||
Utils::scopy(_systemDevice,sizeof(_systemDevice),newSystemDevice);
|
||||
Utils::scopy(_systemDevice, sizeof(_systemDevice), newSystemDevice);
|
||||
}
|
||||
|
||||
// if there's no newSystemVia, the OS might not have
|
||||
// ipv4 or ipv6 connectivity.
|
||||
// we should still add our ZeroTier ipv4 or 6 routes though
|
||||
|
||||
if (!!_systemVia && !!_systemDevice[0]) {
|
||||
_routeCmd("delete",_target,_systemVia,(const char *)0,(const char *)0);
|
||||
if (! ! _systemVia && ! ! _systemDevice[0]) {
|
||||
_routeCmd("delete", _target, _systemVia, (const char*)0, (const char*)0);
|
||||
}
|
||||
|
||||
_routeCmd("add",_target,_via,(const char *)0,(const char *)0);
|
||||
_routeCmd("add", _target, _via, (const char*)0, (const char*)0);
|
||||
|
||||
if (!!_systemVia && !!_systemDevice[0]) {
|
||||
_routeCmd("add",_target,_systemVia,_systemDevice,(const char *)0);
|
||||
if (! ! _systemVia && ! ! _systemDevice[0]) {
|
||||
_routeCmd("add", _target, _systemVia, _systemDevice, (const char*)0);
|
||||
}
|
||||
|
||||
_applied[_target] = true;
|
||||
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// Do Non-Default route commands
|
||||
_applied[_target] = true;
|
||||
_routeCmd("add",leftt,_via,(const char *)0,(_via) ? (const char *)0 : _device);
|
||||
_routeCmd("add", leftt, _via, (const char*)0, (_via) ? (const char*)0 : _device);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __BSD__ ------------------------------------------------------------
|
||||
|
||||
#endif // __BSD__ ------------------------------------------------------------
|
||||
#ifdef __LINUX__ // ----------------------------------------------------------
|
||||
|
||||
#ifdef __LINUX__ // ----------------------------------------------------------
|
||||
|
||||
if ((leftt)&&(!LinuxNetLink::getInstance().routeIsSet(leftt,_via,_src,_device))) {
|
||||
_applied[leftt] = false; // boolean unused
|
||||
if ((leftt) && (! LinuxNetLink::getInstance().routeIsSet(leftt, _via, _src, _device))) {
|
||||
_applied[leftt] = false; // boolean unused
|
||||
LinuxNetLink::getInstance().addRoute(leftt, _via, _src, _device);
|
||||
}
|
||||
if ((rightt)&&(!LinuxNetLink::getInstance().routeIsSet(rightt,_via,_src,_device))) {
|
||||
_applied[rightt] = false; // boolean unused
|
||||
if ((rightt) && (! LinuxNetLink::getInstance().routeIsSet(rightt, _via, _src, _device))) {
|
||||
_applied[rightt] = false; // boolean unused
|
||||
LinuxNetLink::getInstance().addRoute(rightt, _via, _src, _device);
|
||||
}
|
||||
|
||||
#endif // __LINUX__ ----------------------------------------------------------
|
||||
#endif // __LINUX__ ----------------------------------------------------------
|
||||
|
||||
#ifdef __WINDOWS__ // --------------------------------------------------------
|
||||
#ifdef __WINDOWS__ // --------------------------------------------------------
|
||||
|
||||
if ( (!_applied.count(leftt)) || (!_winHasRoute(interfaceLuid,interfaceIndex,leftt,_via)) ) {
|
||||
_applied[leftt] = false; // boolean unused
|
||||
_winRoute(false,interfaceLuid,interfaceIndex,leftt,_via);
|
||||
if ((! _applied.count(leftt)) || (! _winHasRoute(interfaceLuid, interfaceIndex, leftt, _via))) {
|
||||
_applied[leftt] = false; // boolean unused
|
||||
_winRoute(false, interfaceLuid, interfaceIndex, leftt, _via);
|
||||
}
|
||||
if ( (rightt) && ( (!_applied.count(rightt)) || (!_winHasRoute(interfaceLuid,interfaceIndex,rightt,_via)) ) ) {
|
||||
_applied[rightt] = false; // boolean unused
|
||||
_winRoute(false,interfaceLuid,interfaceIndex,rightt,_via);
|
||||
if ((rightt) && ((! _applied.count(rightt)) || (! _winHasRoute(interfaceLuid, interfaceIndex, rightt, _via)))) {
|
||||
_applied[rightt] = false; // boolean unused
|
||||
_winRoute(false, interfaceLuid, interfaceIndex, rightt, _via);
|
||||
}
|
||||
|
||||
#endif // __WINDOWS__ --------------------------------------------------------
|
||||
#endif // __WINDOWS__ --------------------------------------------------------
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -582,39 +602,39 @@ void ManagedRoute::remove()
|
|||
{
|
||||
#ifdef __WINDOWS__
|
||||
NET_LUID interfaceLuid;
|
||||
interfaceLuid.Value = (ULONG64)Utils::hexStrToU64(_device); // on Windows we use the hex LUID as the "interface name" for ManagedRoute
|
||||
interfaceLuid.Value = (ULONG64)Utils::hexStrToU64(_device); // on Windows we use the hex LUID as the "interface name" for ManagedRoute
|
||||
NET_IFINDEX interfaceIndex = -1;
|
||||
if (ConvertInterfaceLuidToIndex(&interfaceLuid,&interfaceIndex) != NO_ERROR)
|
||||
if (ConvertInterfaceLuidToIndex(&interfaceLuid, &interfaceIndex) != NO_ERROR)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef __BSD__
|
||||
#endif // __BSD__ ------------------------------------------------------------
|
||||
#endif // __BSD__ ------------------------------------------------------------
|
||||
|
||||
for(std::map<InetAddress,bool>::iterator r(_applied.begin());r!=_applied.end();++r) {
|
||||
#ifdef __BSD__ // ------------------------------------------------------------
|
||||
for (std::map<InetAddress, bool>::iterator r(_applied.begin()); r != _applied.end(); ++r) {
|
||||
#ifdef __BSD__ // ------------------------------------------------------------
|
||||
if (_target && _target.netmaskBits() == 0) {
|
||||
_routeCmd("delete",_target,_via,(const char *)0,(const char *)0);
|
||||
_routeCmd("delete", _target, _via, (const char*)0, (const char*)0);
|
||||
if (_systemVia && _systemDevice[0]) {
|
||||
_routeCmd("delete",_target,_systemVia,_systemDevice,(const char *)0);
|
||||
|
||||
_routeCmd("add",_target,_systemVia,(const char *)0,(const char *)0);
|
||||
_routeCmd("delete", _target, _systemVia, _systemDevice, (const char*)0);
|
||||
|
||||
_routeCmd("add", _target, _systemVia, (const char*)0, (const char*)0);
|
||||
}
|
||||
} else {
|
||||
_routeCmd("delete",_target,_via, (const char *)0, _via ? (const char *)0 : _device);
|
||||
}
|
||||
break;
|
||||
#endif // __BSD__ ------------------------------------------------------------
|
||||
}
|
||||
else {
|
||||
_routeCmd("delete", _target, _via, (const char*)0, _via ? (const char*)0 : _device);
|
||||
}
|
||||
break;
|
||||
#endif // __BSD__ ------------------------------------------------------------
|
||||
|
||||
#ifdef __LINUX__ // ----------------------------------------------------------
|
||||
#ifdef __LINUX__ // ----------------------------------------------------------
|
||||
//_routeCmd("del",r->first,_via,(_via) ? (const char *)0 : _device);
|
||||
LinuxNetLink::getInstance().delRoute(r->first,_via,_src,(_via) ? (const char *)0 : _device);
|
||||
#endif // __LINUX__ ----------------------------------------------------------
|
||||
LinuxNetLink::getInstance().delRoute(r->first, _via, _src, (_via) ? (const char*)0 : _device);
|
||||
#endif // __LINUX__ ----------------------------------------------------------
|
||||
|
||||
#ifdef __WINDOWS__ // --------------------------------------------------------
|
||||
_winRoute(true,interfaceLuid,interfaceIndex,r->first,_via);
|
||||
#endif // __WINDOWS__ --------------------------------------------------------
|
||||
#ifdef __WINDOWS__ // --------------------------------------------------------
|
||||
_winRoute(true, interfaceLuid, interfaceIndex, r->first, _via);
|
||||
#endif // __WINDOWS__ --------------------------------------------------------
|
||||
}
|
||||
|
||||
_target.zero();
|
||||
|
@ -625,4 +645,4 @@ void ManagedRoute::remove()
|
|||
_applied.clear();
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -14,29 +14,27 @@
|
|||
#ifndef ZT_MANAGEDROUTE_HPP
|
||||
#define ZT_MANAGEDROUTE_HPP
|
||||
|
||||
#include "../node/AtomicCounter.hpp"
|
||||
#include "../node/InetAddress.hpp"
|
||||
#include "../node/SharedPtr.hpp"
|
||||
#include "../node/Utils.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../node/InetAddress.hpp"
|
||||
#include "../node/Utils.hpp"
|
||||
#include "../node/SharedPtr.hpp"
|
||||
#include "../node/AtomicCounter.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* A ZT-managed route that used C++ RAII semantics to automatically clean itself up on deallocate
|
||||
*/
|
||||
class ManagedRoute
|
||||
{
|
||||
class ManagedRoute {
|
||||
friend class SharedPtr<ManagedRoute>;
|
||||
|
||||
public:
|
||||
ManagedRoute(const InetAddress &target,const InetAddress &via,const InetAddress &src,const char *device);
|
||||
public:
|
||||
ManagedRoute(const InetAddress& target, const InetAddress& via, const InetAddress& src, const char* device);
|
||||
~ManagedRoute();
|
||||
|
||||
/**
|
||||
|
@ -58,26 +56,43 @@ public:
|
|||
*/
|
||||
void remove();
|
||||
|
||||
inline const InetAddress &target() const { return _target; }
|
||||
inline const InetAddress &via() const { return _via; }
|
||||
inline const InetAddress &src() const { return _src; }
|
||||
inline const char *device() const { return _device; }
|
||||
inline const InetAddress& target() const
|
||||
{
|
||||
return _target;
|
||||
}
|
||||
inline const InetAddress& via() const
|
||||
{
|
||||
return _via;
|
||||
}
|
||||
inline const InetAddress& src() const
|
||||
{
|
||||
return _src;
|
||||
}
|
||||
inline const char* device() const
|
||||
{
|
||||
return _device;
|
||||
}
|
||||
|
||||
private:
|
||||
ManagedRoute(const ManagedRoute &) {}
|
||||
inline ManagedRoute &operator=(const ManagedRoute &) { return *this; }
|
||||
private:
|
||||
ManagedRoute(const ManagedRoute&)
|
||||
{
|
||||
}
|
||||
inline ManagedRoute& operator=(const ManagedRoute&)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
InetAddress _target;
|
||||
InetAddress _via;
|
||||
InetAddress _src;
|
||||
InetAddress _systemVia; // for route overrides
|
||||
std::map<InetAddress,bool> _applied; // routes currently applied
|
||||
InetAddress _systemVia; // for route overrides
|
||||
std::map<InetAddress, bool> _applied; // routes currently applied
|
||||
char _device[128];
|
||||
char _systemDevice[128]; // for route overrides
|
||||
char _systemDevice[128]; // for route overrides
|
||||
|
||||
AtomicCounter __refCount;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,248 +12,240 @@
|
|||
/****/
|
||||
|
||||
#include "NeighborDiscovery.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
|
||||
#include "../include/ZeroTierOne.h"
|
||||
#include "OSUtils.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
uint16_t calc_checksum (uint16_t *addr, int len)
|
||||
uint16_t calc_checksum(uint16_t* addr, int len)
|
||||
{
|
||||
int count = len;
|
||||
uint32_t sum = 0;
|
||||
uint16_t answer = 0;
|
||||
int count = len;
|
||||
uint32_t sum = 0;
|
||||
uint16_t answer = 0;
|
||||
|
||||
// Sum up 2-byte values until none or only one byte left.
|
||||
while (count > 1) {
|
||||
sum += *(addr++);
|
||||
count -= 2;
|
||||
}
|
||||
// Sum up 2-byte values until none or only one byte left.
|
||||
while (count > 1) {
|
||||
sum += *(addr++);
|
||||
count -= 2;
|
||||
}
|
||||
|
||||
// Add left-over byte, if any.
|
||||
if (count > 0) {
|
||||
sum += *(uint8_t *) addr;
|
||||
}
|
||||
// Add left-over byte, if any.
|
||||
if (count > 0) {
|
||||
sum += *(uint8_t*)addr;
|
||||
}
|
||||
|
||||
// Fold 32-bit sum into 16 bits; we lose information by doing this,
|
||||
// increasing the chances of a collision.
|
||||
// sum = (lower 16 bits) + (upper 16 bits shifted right 16 bits)
|
||||
while (sum >> 16) {
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
}
|
||||
// Fold 32-bit sum into 16 bits; we lose information by doing this,
|
||||
// increasing the chances of a collision.
|
||||
// sum = (lower 16 bits) + (upper 16 bits shifted right 16 bits)
|
||||
while (sum >> 16) {
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
}
|
||||
|
||||
// Checksum is one's compliment of sum.
|
||||
answer = ~sum;
|
||||
// Checksum is one's compliment of sum.
|
||||
answer = ~sum;
|
||||
|
||||
return (answer);
|
||||
return (answer);
|
||||
}
|
||||
|
||||
struct _pseudo_header {
|
||||
uint8_t sourceAddr[16];
|
||||
uint8_t targetAddr[16];
|
||||
uint32_t length;
|
||||
uint8_t zeros[3];
|
||||
uint8_t next; // 58
|
||||
uint8_t sourceAddr[16];
|
||||
uint8_t targetAddr[16];
|
||||
uint32_t length;
|
||||
uint8_t zeros[3];
|
||||
uint8_t next; // 58
|
||||
};
|
||||
|
||||
struct _option {
|
||||
_option(int optionType)
|
||||
: type(optionType)
|
||||
, length(8)
|
||||
{
|
||||
memset(mac, 0, sizeof(mac));
|
||||
}
|
||||
_option(int optionType) : type(optionType), length(8)
|
||||
{
|
||||
memset(mac, 0, sizeof(mac));
|
||||
}
|
||||
|
||||
uint8_t type;
|
||||
uint8_t length;
|
||||
uint8_t mac[6];
|
||||
uint8_t type;
|
||||
uint8_t length;
|
||||
uint8_t mac[6];
|
||||
};
|
||||
|
||||
struct _neighbor_solicitation {
|
||||
_neighbor_solicitation()
|
||||
: type(135)
|
||||
, code(0)
|
||||
, checksum(0)
|
||||
, option(1)
|
||||
{
|
||||
memset(&reserved, 0, sizeof(reserved));
|
||||
memset(target, 0, sizeof(target));
|
||||
}
|
||||
_neighbor_solicitation() : type(135), code(0), checksum(0), option(1)
|
||||
{
|
||||
memset(&reserved, 0, sizeof(reserved));
|
||||
memset(target, 0, sizeof(target));
|
||||
}
|
||||
|
||||
void calculateChecksum(const sockaddr_storage &sourceIp, const sockaddr_storage &destIp) {
|
||||
_pseudo_header ph;
|
||||
memset(&ph, 0, sizeof(_pseudo_header));
|
||||
const sockaddr_in6 *src = (const sockaddr_in6*)&sourceIp;
|
||||
const sockaddr_in6 *dest = (const sockaddr_in6*)&destIp;
|
||||
void calculateChecksum(const sockaddr_storage& sourceIp, const sockaddr_storage& destIp)
|
||||
{
|
||||
_pseudo_header ph;
|
||||
memset(&ph, 0, sizeof(_pseudo_header));
|
||||
const sockaddr_in6* src = (const sockaddr_in6*)&sourceIp;
|
||||
const sockaddr_in6* dest = (const sockaddr_in6*)&destIp;
|
||||
|
||||
memcpy(ph.sourceAddr, &src->sin6_addr, sizeof(struct in6_addr));
|
||||
memcpy(ph.targetAddr, &dest->sin6_addr, sizeof(struct in6_addr));
|
||||
ph.next = 58;
|
||||
ph.length = htonl(sizeof(_neighbor_solicitation));
|
||||
memcpy(ph.sourceAddr, &src->sin6_addr, sizeof(struct in6_addr));
|
||||
memcpy(ph.targetAddr, &dest->sin6_addr, sizeof(struct in6_addr));
|
||||
ph.next = 58;
|
||||
ph.length = htonl(sizeof(_neighbor_solicitation));
|
||||
|
||||
size_t len = sizeof(_pseudo_header) + sizeof(_neighbor_solicitation);
|
||||
uint8_t *tmp = (uint8_t*)malloc(len);
|
||||
memcpy(tmp, &ph, sizeof(_pseudo_header));
|
||||
memcpy(tmp+sizeof(_pseudo_header), this, sizeof(_neighbor_solicitation));
|
||||
size_t len = sizeof(_pseudo_header) + sizeof(_neighbor_solicitation);
|
||||
uint8_t* tmp = (uint8_t*)malloc(len);
|
||||
memcpy(tmp, &ph, sizeof(_pseudo_header));
|
||||
memcpy(tmp + sizeof(_pseudo_header), this, sizeof(_neighbor_solicitation));
|
||||
|
||||
checksum = calc_checksum((uint16_t*)tmp, (int)len);
|
||||
checksum = calc_checksum((uint16_t*)tmp, (int)len);
|
||||
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
|
||||
uint8_t type; // 135
|
||||
uint8_t code; // 0
|
||||
uint16_t checksum;
|
||||
uint32_t reserved;
|
||||
uint8_t target[16];
|
||||
_option option;
|
||||
uint8_t type; // 135
|
||||
uint8_t code; // 0
|
||||
uint16_t checksum;
|
||||
uint32_t reserved;
|
||||
uint8_t target[16];
|
||||
_option option;
|
||||
};
|
||||
|
||||
struct _neighbor_advertisement {
|
||||
_neighbor_advertisement()
|
||||
: type(136)
|
||||
, code(0)
|
||||
, checksum(0)
|
||||
, rso(0x40)
|
||||
, option(2)
|
||||
{
|
||||
memset(padding, 0, sizeof(padding));
|
||||
memset(target, 0, sizeof(target));
|
||||
}
|
||||
_neighbor_advertisement() : type(136), code(0), checksum(0), rso(0x40), option(2)
|
||||
{
|
||||
memset(padding, 0, sizeof(padding));
|
||||
memset(target, 0, sizeof(target));
|
||||
}
|
||||
|
||||
void calculateChecksum(const sockaddr_storage &sourceIp, const sockaddr_storage &destIp) {
|
||||
_pseudo_header ph;
|
||||
memset(&ph, 0, sizeof(_pseudo_header));
|
||||
const sockaddr_in6 *src = (const sockaddr_in6*)&sourceIp;
|
||||
const sockaddr_in6 *dest = (const sockaddr_in6*)&destIp;
|
||||
void calculateChecksum(const sockaddr_storage& sourceIp, const sockaddr_storage& destIp)
|
||||
{
|
||||
_pseudo_header ph;
|
||||
memset(&ph, 0, sizeof(_pseudo_header));
|
||||
const sockaddr_in6* src = (const sockaddr_in6*)&sourceIp;
|
||||
const sockaddr_in6* dest = (const sockaddr_in6*)&destIp;
|
||||
|
||||
memcpy(ph.sourceAddr, &src->sin6_addr, sizeof(struct in6_addr));
|
||||
memcpy(ph.targetAddr, &dest->sin6_addr, sizeof(struct in6_addr));
|
||||
ph.next = 58;
|
||||
ph.length = htonl(sizeof(_neighbor_advertisement));
|
||||
memcpy(ph.sourceAddr, &src->sin6_addr, sizeof(struct in6_addr));
|
||||
memcpy(ph.targetAddr, &dest->sin6_addr, sizeof(struct in6_addr));
|
||||
ph.next = 58;
|
||||
ph.length = htonl(sizeof(_neighbor_advertisement));
|
||||
|
||||
size_t len = sizeof(_pseudo_header) + sizeof(_neighbor_advertisement);
|
||||
uint8_t *tmp = (uint8_t*)malloc(len);
|
||||
memcpy(tmp, &ph, sizeof(_pseudo_header));
|
||||
memcpy(tmp+sizeof(_pseudo_header), this, sizeof(_neighbor_advertisement));
|
||||
size_t len = sizeof(_pseudo_header) + sizeof(_neighbor_advertisement);
|
||||
uint8_t* tmp = (uint8_t*)malloc(len);
|
||||
memcpy(tmp, &ph, sizeof(_pseudo_header));
|
||||
memcpy(tmp + sizeof(_pseudo_header), this, sizeof(_neighbor_advertisement));
|
||||
|
||||
checksum = calc_checksum((uint16_t*)tmp, (int)len);
|
||||
checksum = calc_checksum((uint16_t*)tmp, (int)len);
|
||||
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
|
||||
uint8_t type; // 136
|
||||
uint8_t code; // 0
|
||||
uint16_t checksum;
|
||||
uint8_t rso;
|
||||
uint8_t padding[3];
|
||||
uint8_t target[16];
|
||||
_option option;
|
||||
uint8_t type; // 136
|
||||
uint8_t code; // 0
|
||||
uint16_t checksum;
|
||||
uint8_t rso;
|
||||
uint8_t padding[3];
|
||||
uint8_t target[16];
|
||||
_option option;
|
||||
};
|
||||
|
||||
NeighborDiscovery::NeighborDiscovery()
|
||||
: _cache(256)
|
||||
, _lastCleaned(OSUtils::now())
|
||||
{}
|
||||
|
||||
void NeighborDiscovery::addLocal(const sockaddr_storage &address, const MAC &mac)
|
||||
NeighborDiscovery::NeighborDiscovery() : _cache(256), _lastCleaned(OSUtils::now())
|
||||
{
|
||||
_NDEntry &e = _cache[InetAddress(address)];
|
||||
e.lastQuerySent = 0;
|
||||
e.lastResponseReceived = 0;
|
||||
e.mac = mac;
|
||||
e.local = true;
|
||||
}
|
||||
|
||||
void NeighborDiscovery::remove(const sockaddr_storage &address)
|
||||
void NeighborDiscovery::addLocal(const sockaddr_storage& address, const MAC& mac)
|
||||
{
|
||||
_cache.erase(InetAddress(address));
|
||||
_NDEntry& e = _cache[InetAddress(address)];
|
||||
e.lastQuerySent = 0;
|
||||
e.lastResponseReceived = 0;
|
||||
e.mac = mac;
|
||||
e.local = true;
|
||||
}
|
||||
|
||||
sockaddr_storage NeighborDiscovery::processIncomingND(const uint8_t *nd, unsigned int len, const sockaddr_storage &localIp, uint8_t *response, unsigned int &responseLen, MAC &responseDest)
|
||||
void NeighborDiscovery::remove(const sockaddr_storage& address)
|
||||
{
|
||||
assert(sizeof(_neighbor_solicitation) == 28);
|
||||
assert(sizeof(_neighbor_advertisement) == 32);
|
||||
|
||||
const uint64_t now = OSUtils::now();
|
||||
sockaddr_storage ip = {0};
|
||||
|
||||
if (len >= sizeof(_neighbor_solicitation) && nd[0] == 0x87) {
|
||||
// respond to Neighbor Solicitation request for local address
|
||||
_neighbor_solicitation solicitation;
|
||||
memcpy(&solicitation, nd, len);
|
||||
InetAddress targetAddress(solicitation.target, 16, 0);
|
||||
_NDEntry *targetEntry = _cache.get(targetAddress);
|
||||
if (targetEntry && targetEntry->local) {
|
||||
_neighbor_advertisement adv;
|
||||
targetEntry->mac.copyTo(adv.option.mac, 6);
|
||||
memcpy(adv.target, solicitation.target, 16);
|
||||
adv.calculateChecksum(localIp, targetAddress);
|
||||
memcpy(response, &adv, sizeof(_neighbor_advertisement));
|
||||
responseLen = sizeof(_neighbor_advertisement);
|
||||
responseDest.setTo(solicitation.option.mac, 6);
|
||||
}
|
||||
} else if (len >= sizeof(_neighbor_advertisement) && nd[0] == 0x88) {
|
||||
_neighbor_advertisement adv;
|
||||
memcpy(&adv, nd, len);
|
||||
InetAddress responseAddress(adv.target, 16, 0);
|
||||
_NDEntry *queryEntry = _cache.get(responseAddress);
|
||||
if(queryEntry && !queryEntry->local && (now - queryEntry->lastQuerySent <= ZT_ND_QUERY_MAX_TTL)) {
|
||||
queryEntry->lastResponseReceived = now;
|
||||
queryEntry->mac.setTo(adv.option.mac, 6);
|
||||
ip = responseAddress;
|
||||
}
|
||||
}
|
||||
|
||||
if ((now - _lastCleaned) >= ZT_ND_EXPIRE) {
|
||||
_lastCleaned = now;
|
||||
Hashtable<InetAddress, _NDEntry>::Iterator i(_cache);
|
||||
InetAddress *k = NULL;
|
||||
_NDEntry *v = NULL;
|
||||
while (i.next(k, v)) {
|
||||
if(!v->local && (now - v->lastResponseReceived) >= ZT_ND_EXPIRE) {
|
||||
_cache.erase(*k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ip;
|
||||
_cache.erase(InetAddress(address));
|
||||
}
|
||||
|
||||
MAC NeighborDiscovery::query(const MAC &localMac, const sockaddr_storage &localIp, const sockaddr_storage &targetIp, uint8_t *query, unsigned int &queryLen, MAC &queryDest)
|
||||
sockaddr_storage NeighborDiscovery::processIncomingND(const uint8_t* nd, unsigned int len, const sockaddr_storage& localIp, uint8_t* response, unsigned int& responseLen, MAC& responseDest)
|
||||
{
|
||||
const uint64_t now = OSUtils::now();
|
||||
assert(sizeof(_neighbor_solicitation) == 28);
|
||||
assert(sizeof(_neighbor_advertisement) == 32);
|
||||
|
||||
InetAddress localAddress(localIp);
|
||||
localAddress.setPort(0);
|
||||
InetAddress targetAddress(targetIp);
|
||||
targetAddress.setPort(0);
|
||||
const uint64_t now = OSUtils::now();
|
||||
sockaddr_storage ip = { 0 };
|
||||
|
||||
_NDEntry &e = _cache[targetAddress];
|
||||
if (len >= sizeof(_neighbor_solicitation) && nd[0] == 0x87) {
|
||||
// respond to Neighbor Solicitation request for local address
|
||||
_neighbor_solicitation solicitation;
|
||||
memcpy(&solicitation, nd, len);
|
||||
InetAddress targetAddress(solicitation.target, 16, 0);
|
||||
_NDEntry* targetEntry = _cache.get(targetAddress);
|
||||
if (targetEntry && targetEntry->local) {
|
||||
_neighbor_advertisement adv;
|
||||
targetEntry->mac.copyTo(adv.option.mac, 6);
|
||||
memcpy(adv.target, solicitation.target, 16);
|
||||
adv.calculateChecksum(localIp, targetAddress);
|
||||
memcpy(response, &adv, sizeof(_neighbor_advertisement));
|
||||
responseLen = sizeof(_neighbor_advertisement);
|
||||
responseDest.setTo(solicitation.option.mac, 6);
|
||||
}
|
||||
}
|
||||
else if (len >= sizeof(_neighbor_advertisement) && nd[0] == 0x88) {
|
||||
_neighbor_advertisement adv;
|
||||
memcpy(&adv, nd, len);
|
||||
InetAddress responseAddress(adv.target, 16, 0);
|
||||
_NDEntry* queryEntry = _cache.get(responseAddress);
|
||||
if (queryEntry && ! queryEntry->local && (now - queryEntry->lastQuerySent <= ZT_ND_QUERY_MAX_TTL)) {
|
||||
queryEntry->lastResponseReceived = now;
|
||||
queryEntry->mac.setTo(adv.option.mac, 6);
|
||||
ip = responseAddress;
|
||||
}
|
||||
}
|
||||
|
||||
if ( (e.mac && ((now - e.lastResponseReceived) >= (ZT_ND_EXPIRE / 3))) ||
|
||||
(!e.mac && ((now - e.lastQuerySent) >= ZT_ND_QUERY_INTERVAL))) {
|
||||
e.lastQuerySent = now;
|
||||
if ((now - _lastCleaned) >= ZT_ND_EXPIRE) {
|
||||
_lastCleaned = now;
|
||||
Hashtable<InetAddress, _NDEntry>::Iterator i(_cache);
|
||||
InetAddress* k = NULL;
|
||||
_NDEntry* v = NULL;
|
||||
while (i.next(k, v)) {
|
||||
if (! v->local && (now - v->lastResponseReceived) >= ZT_ND_EXPIRE) {
|
||||
_cache.erase(*k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_neighbor_solicitation ns;
|
||||
memcpy(ns.target, targetAddress.rawIpData(), 16);
|
||||
localMac.copyTo(ns.option.mac, 6);
|
||||
ns.calculateChecksum(localIp, targetIp);
|
||||
if (e.mac) {
|
||||
queryDest = e.mac;
|
||||
} else {
|
||||
queryDest = (uint64_t)0xffffffffffffULL;
|
||||
}
|
||||
} else {
|
||||
queryLen = 0;
|
||||
queryDest.zero();
|
||||
}
|
||||
|
||||
return e.mac;
|
||||
return ip;
|
||||
}
|
||||
|
||||
MAC NeighborDiscovery::query(const MAC& localMac, const sockaddr_storage& localIp, const sockaddr_storage& targetIp, uint8_t* query, unsigned int& queryLen, MAC& queryDest)
|
||||
{
|
||||
const uint64_t now = OSUtils::now();
|
||||
|
||||
InetAddress localAddress(localIp);
|
||||
localAddress.setPort(0);
|
||||
InetAddress targetAddress(targetIp);
|
||||
targetAddress.setPort(0);
|
||||
|
||||
_NDEntry& e = _cache[targetAddress];
|
||||
|
||||
if ((e.mac && ((now - e.lastResponseReceived) >= (ZT_ND_EXPIRE / 3))) || (! e.mac && ((now - e.lastQuerySent) >= ZT_ND_QUERY_INTERVAL))) {
|
||||
e.lastQuerySent = now;
|
||||
|
||||
_neighbor_solicitation ns;
|
||||
memcpy(ns.target, targetAddress.rawIpData(), 16);
|
||||
localMac.copyTo(ns.option.mac, 6);
|
||||
ns.calculateChecksum(localIp, targetIp);
|
||||
if (e.mac) {
|
||||
queryDest = e.mac;
|
||||
}
|
||||
else {
|
||||
queryDest = (uint64_t)0xffffffffffffULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
queryLen = 0;
|
||||
queryDest.zero();
|
||||
}
|
||||
|
||||
return e.mac;
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -15,9 +15,8 @@
|
|||
#define ZT_NEIGHBORDISCOVERY_HPP
|
||||
|
||||
#include "../node/Hashtable.hpp"
|
||||
#include "../node/MAC.hpp"
|
||||
#include "../node/InetAddress.hpp"
|
||||
|
||||
#include "../node/MAC.hpp"
|
||||
|
||||
#define ZT_ND_QUERY_INTERVAL 2000
|
||||
|
||||
|
@ -25,47 +24,46 @@
|
|||
|
||||
#define ZT_ND_EXPIRE 600000
|
||||
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class NeighborDiscovery
|
||||
{
|
||||
public:
|
||||
NeighborDiscovery();
|
||||
class NeighborDiscovery {
|
||||
public:
|
||||
NeighborDiscovery();
|
||||
|
||||
/**
|
||||
* Set a local IP entry that we should respond to Neighbor Requests withPrefix64k
|
||||
*
|
||||
* @param mac Our local MAC address
|
||||
* @param ip Our IPv6 address
|
||||
*/
|
||||
void addLocal(const sockaddr_storage &address, const MAC &mac);
|
||||
/**
|
||||
* Set a local IP entry that we should respond to Neighbor Requests withPrefix64k
|
||||
*
|
||||
* @param mac Our local MAC address
|
||||
* @param ip Our IPv6 address
|
||||
*/
|
||||
void addLocal(const sockaddr_storage& address, const MAC& mac);
|
||||
|
||||
/**
|
||||
* Delete a local IP entry or cached Neighbor entry
|
||||
*
|
||||
* @param address IPv6 address to remove
|
||||
*/
|
||||
void remove(const sockaddr_storage &address);
|
||||
/**
|
||||
* Delete a local IP entry or cached Neighbor entry
|
||||
*
|
||||
* @param address IPv6 address to remove
|
||||
*/
|
||||
void remove(const sockaddr_storage& address);
|
||||
|
||||
sockaddr_storage processIncomingND(const uint8_t *nd, unsigned int len, const sockaddr_storage &localIp, uint8_t *response, unsigned int &responseLen, MAC &responseDest);
|
||||
sockaddr_storage processIncomingND(const uint8_t* nd, unsigned int len, const sockaddr_storage& localIp, uint8_t* response, unsigned int& responseLen, MAC& responseDest);
|
||||
|
||||
MAC query(const MAC &localMac, const sockaddr_storage &localIp, const sockaddr_storage &targetIp, uint8_t *query, unsigned int &queryLen, MAC &queryDest);
|
||||
MAC query(const MAC& localMac, const sockaddr_storage& localIp, const sockaddr_storage& targetIp, uint8_t* query, unsigned int& queryLen, MAC& queryDest);
|
||||
|
||||
private:
|
||||
struct _NDEntry
|
||||
{
|
||||
_NDEntry() : lastQuerySent(0), lastResponseReceived(0), mac(), local(false) {}
|
||||
uint64_t lastQuerySent;
|
||||
uint64_t lastResponseReceived;
|
||||
MAC mac;
|
||||
bool local;
|
||||
};
|
||||
private:
|
||||
struct _NDEntry {
|
||||
_NDEntry() : lastQuerySent(0), lastResponseReceived(0), mac(), local(false)
|
||||
{
|
||||
}
|
||||
uint64_t lastQuerySent;
|
||||
uint64_t lastResponseReceived;
|
||||
MAC mac;
|
||||
bool local;
|
||||
};
|
||||
|
||||
Hashtable<InetAddress, _NDEntry> _cache;
|
||||
uint64_t _lastCleaned;
|
||||
Hashtable<InetAddress, _NDEntry> _cache;
|
||||
uint64_t _lastCleaned;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,79 +11,73 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "NetBSDEthernetTap.hpp"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/Mutex.hpp"
|
||||
#include "../node/Utils.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
#include "freebsd_getifmaddrs.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/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <algorithm>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include "freebsd_getifmaddrs.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <netinet/in.h>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <utility>
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/Utils.hpp"
|
||||
#include "../node/Mutex.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
#include "NetBSDEthernetTap.hpp"
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
#define ZT_BASE32_CHARS "0123456789abcdefghijklmnopqrstuv"
|
||||
|
||||
// ff:ff:ff:ff:ff:ff with no ADI
|
||||
static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff),0);
|
||||
static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff), 0);
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
NetBSDEthernetTap::NetBSDEthernetTap(
|
||||
const char *homePath,
|
||||
const MAC &mac,
|
||||
const char* homePath,
|
||||
const MAC& mac,
|
||||
unsigned int mtu,
|
||||
unsigned int metric,
|
||||
uint64_t nwid,
|
||||
const char *friendlyName,
|
||||
void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
|
||||
void *arg) :
|
||||
_handler(handler),
|
||||
_arg(arg),
|
||||
_nwid(nwid),
|
||||
_mtu(mtu),
|
||||
_metric(metric),
|
||||
_fd(0),
|
||||
_enabled(true)
|
||||
const char* friendlyName,
|
||||
void (*handler)(void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
|
||||
void* arg)
|
||||
: _handler(handler)
|
||||
, _arg(arg)
|
||||
, _nwid(nwid)
|
||||
, _mtu(mtu)
|
||||
, _metric(metric)
|
||||
, _fd(0)
|
||||
, _enabled(true)
|
||||
{
|
||||
static Mutex globalTapCreateLock;
|
||||
char devpath[64],ethaddr[64],mtustr[32],metstr[32],tmpdevname[32];
|
||||
char devpath[64], ethaddr[64], mtustr[32], metstr[32], tmpdevname[32];
|
||||
struct stat stattmp;
|
||||
|
||||
Mutex::Lock _gl(globalTapCreateLock);
|
||||
|
@ -93,43 +87,50 @@ NetBSDEthernetTap::NetBSDEthernetTap(
|
|||
|
||||
// we can create /dev/tap*
|
||||
std::vector<std::string> devFiles(OSUtils::listDirectory("/dev"));
|
||||
for(int i=9993;i<(9993+128);++i) {
|
||||
Utils::snprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i);
|
||||
Utils::snprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname);
|
||||
if (std::find(devFiles.begin(),devFiles.end(),std::string(tmpdevname)) == devFiles.end()) {
|
||||
for (int i = 9993; i < (9993 + 128); ++i) {
|
||||
Utils::snprintf(tmpdevname, sizeof(tmpdevname), "tap%d", i);
|
||||
Utils::snprintf(devpath, sizeof(devpath), "/dev/%s", tmpdevname);
|
||||
if (std::find(devFiles.begin(), devFiles.end(), std::string(tmpdevname)) == devFiles.end()) {
|
||||
long cpid = (long)vfork();
|
||||
if (cpid == 0) {
|
||||
::execl("/sbin/ifconfig","/sbin/ifconfig",tmpdevname,"create",(const char *)0);
|
||||
::execl("/sbin/ifconfig", "/sbin/ifconfig", tmpdevname, "create", (const char*)0);
|
||||
::_exit(-1);
|
||||
} else if (cpid > 0) {
|
||||
}
|
||||
else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
::waitpid(cpid,&exitcode,0);
|
||||
} else throw std::runtime_error("fork() failed");
|
||||
::waitpid(cpid, &exitcode, 0);
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("fork() failed");
|
||||
|
||||
cpid = (long)vfork();
|
||||
if (cpid == 0) {
|
||||
string tmp;
|
||||
sprintf((char*)tmp.c_str(), "%d", i);
|
||||
string minor = tmp.c_str();
|
||||
::execl("/sbin/mknod","/sbin/mknod",devpath,"c","169",minor.c_str(),(const char *)0);
|
||||
::execl("/sbin/mknod", "/sbin/mknod", devpath, "c", "169", minor.c_str(), (const char*)0);
|
||||
// http://ftp.netbsd.org/pub/NetBSD/NetBSD-current/src/sys/conf/majors
|
||||
// major 169 => tap
|
||||
::_exit(-1);
|
||||
} else if (cpid > 0) {
|
||||
}
|
||||
else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
::waitpid(cpid,&exitcode,0);
|
||||
} else throw std::runtime_error("fork() failed");
|
||||
::waitpid(cpid, &exitcode, 0);
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("fork() failed");
|
||||
|
||||
cerr<<"created device "<<devpath<<endl;
|
||||
cerr << "created device " << devpath << endl;
|
||||
|
||||
_dev = tmpdevname;
|
||||
_fd = ::open( devpath,O_RDWR);
|
||||
if (!stat(devpath,&stattmp)) {
|
||||
_fd = ::open(devpath, O_RDWR);
|
||||
if (! stat(devpath, &stattmp)) {
|
||||
if (_fd > 0)
|
||||
break;
|
||||
else
|
||||
throw std::runtime_error("unable to open created tap device ");
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error("cannot find /dev node for newly created tap device");
|
||||
}
|
||||
}
|
||||
|
@ -138,22 +139,23 @@ NetBSDEthernetTap::NetBSDEthernetTap(
|
|||
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) {
|
||||
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);
|
||||
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(),"link",ethaddr,"mtu",mtustr,"metric",metstr,"up",(const char *)0);
|
||||
::execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "link", ethaddr, "mtu", mtustr, "metric", metstr, "up", (const char*)0);
|
||||
::_exit(-1);
|
||||
} else if (cpid > 0) {
|
||||
}
|
||||
else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
::waitpid(cpid,&exitcode,0);
|
||||
::waitpid(cpid, &exitcode, 0);
|
||||
if (exitcode) {
|
||||
::close(_fd);
|
||||
throw std::runtime_error("ifconfig failure setting link-layer address and activating tap interface");
|
||||
|
@ -164,13 +166,14 @@ NetBSDEthernetTap::NetBSDEthernetTap(
|
|||
// https://wiki.netbsd.org/tutorials/faking_a_mac_address/
|
||||
cpid = (long)vfork();
|
||||
if (cpid == 0) {
|
||||
string cmdline = "net.link.tap."+string(_dev);
|
||||
cmdline += "="+string(ethaddr);
|
||||
::execl("/sbin/sysctl","/sbin/sysctl","-w",cmdline.c_str(),(const char *)0);
|
||||
string cmdline = "net.link.tap." + string(_dev);
|
||||
cmdline += "=" + string(ethaddr);
|
||||
::execl("/sbin/sysctl", "/sbin/sysctl", "-w", cmdline.c_str(), (const char*)0);
|
||||
::_exit(-1);
|
||||
} else if (cpid > 0) {
|
||||
}
|
||||
else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
::waitpid(cpid,&exitcode,0);
|
||||
::waitpid(cpid, &exitcode, 0);
|
||||
if (exitcode) {
|
||||
::close(_fd);
|
||||
throw std::runtime_error("sysctl failure setting link-layer address and activating tap interface");
|
||||
|
@ -178,17 +181,16 @@ NetBSDEthernetTap::NetBSDEthernetTap(
|
|||
}
|
||||
|
||||
// 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);
|
||||
fcntl(_fd, F_SETFD, fcntl(_fd, F_GETFD) | FD_CLOEXEC);
|
||||
|
||||
::pipe(_shutdownSignalPipe);
|
||||
|
||||
_thread = Thread::start(this);
|
||||
|
||||
}
|
||||
|
||||
NetBSDEthernetTap::~NetBSDEthernetTap()
|
||||
{
|
||||
::write(_shutdownSignalPipe[1],"\0",1); // causes thread to exit
|
||||
::write(_shutdownSignalPipe[1], "\0", 1); // causes thread to exit
|
||||
Thread::join(_thread);
|
||||
::close(_fd);
|
||||
::close(_shutdownSignalPipe[0]);
|
||||
|
@ -196,23 +198,27 @@ NetBSDEthernetTap::~NetBSDEthernetTap()
|
|||
|
||||
long cpid = (long)vfork();
|
||||
if (cpid == 0) {
|
||||
::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"destroy",(const char *)0);
|
||||
::execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "destroy", (const char*)0);
|
||||
::_exit(-1);
|
||||
} else if (cpid > 0) {
|
||||
}
|
||||
else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
::waitpid(cpid,&exitcode,0);
|
||||
::waitpid(cpid, &exitcode, 0);
|
||||
}
|
||||
|
||||
cpid = (long)vfork();
|
||||
if (cpid == 0) {
|
||||
string tmp="/dev/";
|
||||
tmp+=_dev.c_str();
|
||||
::execl("/bin/rm","/bin/rm",tmp.c_str(),(const char *)0);
|
||||
string tmp = "/dev/";
|
||||
tmp += _dev.c_str();
|
||||
::execl("/bin/rm", "/bin/rm", tmp.c_str(), (const char*)0);
|
||||
::_exit(-1);
|
||||
} else if (cpid > 0) {
|
||||
}
|
||||
else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
::waitpid(cpid,&exitcode,0);
|
||||
} else throw std::runtime_error("fork() failed");
|
||||
::waitpid(cpid, &exitcode, 0);
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("fork() failed");
|
||||
}
|
||||
|
||||
void NetBSDEthernetTap::setEnabled(bool en)
|
||||
|
@ -225,56 +231,58 @@ bool NetBSDEthernetTap::enabled() const
|
|||
return _enabled;
|
||||
}
|
||||
|
||||
static bool ___removeIp(const std::string &_dev,const InetAddress &ip)
|
||||
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);
|
||||
execl("/sbin/ifconfig", "/sbin/ifconfig", _dev.c_str(), "inet", ip.toIpString().c_str(), "-alias", (const char*)0);
|
||||
_exit(-1);
|
||||
} else if (cpid > 0) {
|
||||
}
|
||||
else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
waitpid(cpid,&exitcode,0);
|
||||
waitpid(cpid, &exitcode, 0);
|
||||
return (exitcode == 0);
|
||||
}
|
||||
return false; // never reached, make compiler shut up about return value
|
||||
return false; // never reached, make compiler shut up about return value
|
||||
}
|
||||
|
||||
bool NetBSDEthernetTap::addIp(const InetAddress &ip)
|
||||
bool NetBSDEthernetTap::addIp(const InetAddress& ip)
|
||||
{
|
||||
if (!ip)
|
||||
if (! ip)
|
||||
return false;
|
||||
|
||||
std::vector<InetAddress> allIps(ips());
|
||||
if (std::find(allIps.begin(),allIps.end(),ip) != allIps.end())
|
||||
return true; // IP/netmask already assigned
|
||||
if (std::find(allIps.begin(), allIps.end(), ip) != allIps.end())
|
||||
return true; // IP/netmask already assigned
|
||||
|
||||
// Remove and reconfigure if address is the same but netmask is different
|
||||
for(std::vector<InetAddress>::iterator i(allIps.begin());i!=allIps.end();++i) {
|
||||
if ((i->ipsEqual(ip))&&(i->netmaskBits() != ip.netmaskBits())) {
|
||||
if (___removeIp(_dev,*i))
|
||||
for (std::vector<InetAddress>::iterator i(allIps.begin()); i != allIps.end(); ++i) {
|
||||
if ((i->ipsEqual(ip)) && (i->netmaskBits() != ip.netmaskBits())) {
|
||||
if (___removeIp(_dev, *i))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
::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) {
|
||||
}
|
||||
else if (cpid > 0) {
|
||||
int exitcode = -1;
|
||||
::waitpid(cpid,&exitcode,0);
|
||||
::waitpid(cpid, &exitcode, 0);
|
||||
return (exitcode == 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetBSDEthernetTap::removeIp(const InetAddress &ip)
|
||||
bool NetBSDEthernetTap::removeIp(const InetAddress& ip)
|
||||
{
|
||||
if (!ip)
|
||||
if (! ip)
|
||||
return false;
|
||||
std::vector<InetAddress> allIps(ips());
|
||||
if (std::find(allIps.begin(),allIps.end(),ip) != allIps.end()) {
|
||||
if (___removeIp(_dev,ip))
|
||||
if (std::find(allIps.begin(), allIps.end(), ip) != allIps.end()) {
|
||||
if (___removeIp(_dev, ip))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -282,28 +290,28 @@ bool NetBSDEthernetTap::removeIp(const InetAddress &ip)
|
|||
|
||||
std::vector<InetAddress> NetBSDEthernetTap::ips() const
|
||||
{
|
||||
struct ifaddrs *ifa = (struct ifaddrs *)0;
|
||||
struct ifaddrs* ifa = (struct ifaddrs*)0;
|
||||
if (getifaddrs(&ifa))
|
||||
return std::vector<InetAddress>();
|
||||
|
||||
std::vector<InetAddress> r;
|
||||
|
||||
struct ifaddrs *p = ifa;
|
||||
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) {
|
||||
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.push_back(InetAddress(&(sin->sin_addr.s_addr),4,Utils::countBits((uint32_t)nm->sin_addr.s_addr)));
|
||||
} break;
|
||||
struct sockaddr_in* sin = (struct sockaddr_in*)p->ifa_addr;
|
||||
struct sockaddr_in* nm = (struct sockaddr_in*)p->ifa_netmask;
|
||||
r.push_back(InetAddress(&(sin->sin_addr.s_addr), 4, Utils::countBits((uint32_t)nm->sin_addr.s_addr)));
|
||||
} break;
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *sin = (struct sockaddr_in6 *)p->ifa_addr;
|
||||
struct sockaddr_in6 *nm = (struct sockaddr_in6 *)p->ifa_netmask;
|
||||
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.push_back(InetAddress(sin->sin6_addr.s6_addr,16,Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3])));
|
||||
} break;
|
||||
memcpy(b, nm->sin6_addr.s6_addr, sizeof(b));
|
||||
r.push_back(InetAddress(sin->sin6_addr.s6_addr, 16, Utils::countBits(b[0]) + Utils::countBits(b[1]) + Utils::countBits(b[2]) + Utils::countBits(b[3])));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
p = p->ifa_next;
|
||||
|
@ -312,22 +320,22 @@ std::vector<InetAddress> NetBSDEthernetTap::ips() const
|
|||
if (ifa)
|
||||
freeifaddrs(ifa);
|
||||
|
||||
std::sort(r.begin(),r.end());
|
||||
std::unique(r.begin(),r.end());
|
||||
std::sort(r.begin(), r.end());
|
||||
std::unique(r.begin(), r.end());
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void NetBSDEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
|
||||
void NetBSDEthernetTap::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);
|
||||
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);
|
||||
::write(_fd, putBuf, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -336,23 +344,23 @@ std::string NetBSDEthernetTap::deviceName() const
|
|||
return _dev;
|
||||
}
|
||||
|
||||
void NetBSDEthernetTap::setFriendlyName(const char *friendlyName)
|
||||
void NetBSDEthernetTap::setFriendlyName(const char* friendlyName)
|
||||
{
|
||||
}
|
||||
|
||||
void NetBSDEthernetTap::scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed)
|
||||
void NetBSDEthernetTap::scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed)
|
||||
{
|
||||
std::vector<MulticastGroup> newGroups;
|
||||
|
||||
struct ifmaddrs *ifmap = (struct ifmaddrs *)0;
|
||||
if (!getifmaddrs(&ifmap)) {
|
||||
struct ifmaddrs *p = ifmap;
|
||||
struct ifmaddrs* ifmap = (struct ifmaddrs*)0;
|
||||
if (! getifmaddrs(&ifmap)) {
|
||||
struct 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.push_back(MulticastGroup(MAC(la->sdl_data + la->sdl_nlen,6),0));
|
||||
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.push_back(MulticastGroup(MAC(la->sdl_data + la->sdl_nlen, 6), 0));
|
||||
}
|
||||
p = p->ifma_next;
|
||||
}
|
||||
|
@ -360,18 +368,18 @@ void NetBSDEthernetTap::scanMulticastGroups(std::vector<MulticastGroup> &added,s
|
|||
}
|
||||
|
||||
std::vector<InetAddress> allIps(ips());
|
||||
for(std::vector<InetAddress>::iterator ip(allIps.begin());ip!=allIps.end();++ip)
|
||||
for (std::vector<InetAddress>::iterator ip(allIps.begin()); ip != allIps.end(); ++ip)
|
||||
newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip));
|
||||
|
||||
std::sort(newGroups.begin(),newGroups.end());
|
||||
std::unique(newGroups.begin(),newGroups.end());
|
||||
std::sort(newGroups.begin(), newGroups.end());
|
||||
std::unique(newGroups.begin(), newGroups.end());
|
||||
|
||||
for(std::vector<MulticastGroup>::iterator m(newGroups.begin());m!=newGroups.end();++m) {
|
||||
if (!std::binary_search(_multicastGroups.begin(),_multicastGroups.end(),*m))
|
||||
for (std::vector<MulticastGroup>::iterator m(newGroups.begin()); m != newGroups.end(); ++m) {
|
||||
if (! std::binary_search(_multicastGroups.begin(), _multicastGroups.end(), *m))
|
||||
added.push_back(*m);
|
||||
}
|
||||
for(std::vector<MulticastGroup>::iterator m(_multicastGroups.begin());m!=_multicastGroups.end();++m) {
|
||||
if (!std::binary_search(newGroups.begin(),newGroups.end(),*m))
|
||||
for (std::vector<MulticastGroup>::iterator m(_multicastGroups.begin()); m != _multicastGroups.end(); ++m) {
|
||||
if (! std::binary_search(newGroups.begin(), newGroups.end(), *m))
|
||||
removed.push_back(*m);
|
||||
}
|
||||
|
||||
|
@ -422,12 +430,11 @@ bool NetBSDEthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups)
|
|||
}
|
||||
*/
|
||||
|
||||
void NetBSDEthernetTap::threadMain()
|
||||
throw()
|
||||
void NetBSDEthernetTap::threadMain() throw()
|
||||
{
|
||||
fd_set readfds,nullfds;
|
||||
MAC to,from;
|
||||
int n,nfds,r;
|
||||
fd_set readfds, nullfds;
|
||||
MAC to, from;
|
||||
int n, nfds, r;
|
||||
char getBuf[8194];
|
||||
|
||||
// Wait for a moment after startup -- wait for Network to finish
|
||||
|
@ -436,37 +443,38 @@ void NetBSDEthernetTap::threadMain()
|
|||
|
||||
FD_ZERO(&readfds);
|
||||
FD_ZERO(&nullfds);
|
||||
nfds = (int)std::max(_shutdownSignalPipe[0],_fd) + 1;
|
||||
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);
|
||||
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
|
||||
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 (FD_ISSET(_fd, &readfds)) {
|
||||
n = (int)::read(_fd, getBuf + r, sizeof(getBuf) - r);
|
||||
if (n < 0) {
|
||||
if ((errno != EINTR)&&(errno != ETIMEDOUT))
|
||||
if ((errno != EINTR) && (errno != ETIMEDOUT))
|
||||
break;
|
||||
} else {
|
||||
}
|
||||
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
|
||||
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]);
|
||||
to.setTo(getBuf, 6);
|
||||
from.setTo(getBuf + 6, 6);
|
||||
unsigned int etherType = ntohs(((const uint16_t*)getBuf)[6]);
|
||||
// TODO: VLAN support
|
||||
_handler(_arg,_nwid,from,to,etherType,0,(const void *)(getBuf + 14),r - 14);
|
||||
_handler(_arg, _nwid, from, to, etherType, 0, (const void*)(getBuf + 14), r - 14);
|
||||
}
|
||||
|
||||
r = 0;
|
||||
|
@ -476,4 +484,4 @@ void NetBSDEthernetTap::threadMain()
|
|||
}
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -14,53 +14,52 @@
|
|||
#ifndef ZT_NetBSDEthernetTap_HPP
|
||||
#define ZT_NetBSDEthernetTap_HPP
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/MAC.hpp"
|
||||
#include "../node/MulticastGroup.hpp"
|
||||
#include "EthernetTap.hpp"
|
||||
#include "Thread.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/MulticastGroup.hpp"
|
||||
#include "../node/MAC.hpp"
|
||||
#include "Thread.hpp"
|
||||
#include "EthernetTap.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class NetBSDEthernetTap : public EthernetTap
|
||||
{
|
||||
public:
|
||||
class NetBSDEthernetTap : public EthernetTap {
|
||||
public:
|
||||
NetBSDEthernetTap(
|
||||
const char *homePath,
|
||||
const MAC &mac,
|
||||
const char* homePath,
|
||||
const MAC& mac,
|
||||
unsigned int mtu,
|
||||
unsigned int metric,
|
||||
uint64_t nwid,
|
||||
const char *friendlyName,
|
||||
void (*handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
|
||||
void *arg);
|
||||
const char* friendlyName,
|
||||
void (*handler)(void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
|
||||
void* arg);
|
||||
|
||||
virtual ~NetBSDEthernetTap();
|
||||
|
||||
virtual void setEnabled(bool en);
|
||||
virtual bool enabled() const;
|
||||
virtual bool addIp(const InetAddress &ip);
|
||||
virtual bool removeIp(const InetAddress &ip);
|
||||
virtual bool addIp(const InetAddress& ip);
|
||||
virtual bool removeIp(const InetAddress& ip);
|
||||
virtual std::vector<InetAddress> ips() const;
|
||||
virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len);
|
||||
virtual void put(const MAC& from, const MAC& to, unsigned int etherType, const void* data, unsigned int len);
|
||||
virtual std::string deviceName() const;
|
||||
virtual void setFriendlyName(const char *friendlyName);
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
|
||||
virtual void setDns(const char *domain, const std::vector<InetAddress> &servers) {}
|
||||
virtual void setFriendlyName(const char* friendlyName);
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed);
|
||||
virtual void setDns(const char* domain, const std::vector<InetAddress>& servers)
|
||||
{
|
||||
}
|
||||
|
||||
void threadMain()
|
||||
throw();
|
||||
void threadMain() throw();
|
||||
|
||||
private:
|
||||
void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
|
||||
void *_arg;
|
||||
private:
|
||||
void (*_handler)(void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int);
|
||||
void* _arg;
|
||||
uint64_t _nwid;
|
||||
Thread _thread;
|
||||
std::string _dev;
|
||||
|
@ -72,6 +71,6 @@ private:
|
|||
volatile bool _enabled;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,35 +11,34 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/Utils.hpp"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef __UNIX_LIKE__
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <dirent.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
#include <shlobj.h>
|
||||
#include <netioapi.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <netioapi.h>
|
||||
#include <shlobj.h>
|
||||
#include <wincrypt.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "OSUtils.hpp"
|
||||
|
@ -50,15 +49,15 @@
|
|||
|
||||
namespace ZeroTier {
|
||||
|
||||
unsigned int OSUtils::ztsnprintf(char *buf,unsigned int len,const char *fmt,...)
|
||||
unsigned int OSUtils::ztsnprintf(char* buf, unsigned int len, const char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap,fmt);
|
||||
int n = (int)vsnprintf(buf,len,fmt,ap);
|
||||
va_start(ap, fmt);
|
||||
int n = (int)vsnprintf(buf, len, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if ((n >= (int)len)||(n < 0)) {
|
||||
if ((n >= (int)len) || (n < 0)) {
|
||||
if (len)
|
||||
buf[len - 1] = (char)0;
|
||||
throw std::length_error("buf[] overflow");
|
||||
|
@ -67,70 +66,75 @@ unsigned int OSUtils::ztsnprintf(char *buf,unsigned int len,const char *fmt,...)
|
|||
return (unsigned int)n;
|
||||
}
|
||||
|
||||
std::string OSUtils::networkIDStr(const uint64_t nwid) {
|
||||
std::string OSUtils::networkIDStr(const uint64_t nwid)
|
||||
{
|
||||
char tmp[32] = {};
|
||||
ztsnprintf(tmp, sizeof(tmp), "%.16" PRIx64, nwid);
|
||||
return std::string(tmp);
|
||||
}
|
||||
|
||||
std::string OSUtils::nodeIDStr(const uint64_t nid) {
|
||||
std::string OSUtils::nodeIDStr(const uint64_t nid)
|
||||
{
|
||||
char tmp[32] = {};
|
||||
ztsnprintf(tmp, sizeof(tmp), "%.10" PRIx64, nid);
|
||||
return std::string(tmp);
|
||||
}
|
||||
|
||||
#ifdef __UNIX_LIKE__
|
||||
bool OSUtils::redirectUnixOutputs(const char *stdoutPath,const char *stderrPath)
|
||||
throw()
|
||||
bool OSUtils::redirectUnixOutputs(const char* stdoutPath, const char* stderrPath) throw()
|
||||
{
|
||||
int fdout = ::open(stdoutPath,O_WRONLY|O_CREAT,0600);
|
||||
int fdout = ::open(stdoutPath, O_WRONLY | O_CREAT, 0600);
|
||||
if (fdout > 0) {
|
||||
int fderr;
|
||||
if (stderrPath) {
|
||||
fderr = ::open(stderrPath,O_WRONLY|O_CREAT,0600);
|
||||
fderr = ::open(stderrPath, O_WRONLY | O_CREAT, 0600);
|
||||
if (fderr <= 0) {
|
||||
::close(fdout);
|
||||
return false;
|
||||
}
|
||||
} else fderr = fdout;
|
||||
}
|
||||
else
|
||||
fderr = fdout;
|
||||
::close(STDOUT_FILENO);
|
||||
::close(STDERR_FILENO);
|
||||
::dup2(fdout,STDOUT_FILENO);
|
||||
::dup2(fderr,STDERR_FILENO);
|
||||
::dup2(fdout, STDOUT_FILENO);
|
||||
::dup2(fderr, STDERR_FILENO);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif // __UNIX_LIKE__
|
||||
#endif // __UNIX_LIKE__
|
||||
|
||||
std::vector<std::string> OSUtils::listDirectory(const char *path,bool includeDirectories)
|
||||
std::vector<std::string> OSUtils::listDirectory(const char* path, bool includeDirectories)
|
||||
{
|
||||
std::vector<std::string> r;
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
HANDLE hFind;
|
||||
WIN32_FIND_DATAA ffd;
|
||||
if ((hFind = FindFirstFileA((std::string(path) + "\\*").c_str(),&ffd)) != INVALID_HANDLE_VALUE) {
|
||||
if ((hFind = FindFirstFileA((std::string(path) + "\\*").c_str(), &ffd)) != INVALID_HANDLE_VALUE) {
|
||||
do {
|
||||
if ( (strcmp(ffd.cFileName,".")) && (strcmp(ffd.cFileName,"..")) && (((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)||(((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)&&(includeDirectories))) )
|
||||
if ((strcmp(ffd.cFileName, ".")) && (strcmp(ffd.cFileName, "..")) && (((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) || (((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) && (includeDirectories))))
|
||||
r.push_back(std::string(ffd.cFileName));
|
||||
} while (FindNextFileA(hFind,&ffd));
|
||||
} while (FindNextFileA(hFind, &ffd));
|
||||
FindClose(hFind);
|
||||
}
|
||||
#else
|
||||
struct dirent de;
|
||||
struct dirent *dptr;
|
||||
DIR *d = opendir(path);
|
||||
if (!d)
|
||||
struct dirent* dptr;
|
||||
DIR* d = opendir(path);
|
||||
if (! d)
|
||||
return r;
|
||||
dptr = (struct dirent *)0;
|
||||
for(;;) {
|
||||
if (readdir_r(d,&de,&dptr))
|
||||
dptr = (struct dirent*)0;
|
||||
for (;;) {
|
||||
if (readdir_r(d, &de, &dptr))
|
||||
break;
|
||||
if (dptr) {
|
||||
if ((strcmp(dptr->d_name,"."))&&(strcmp(dptr->d_name,".."))&&((dptr->d_type != DT_DIR)||(includeDirectories)))
|
||||
if ((strcmp(dptr->d_name, ".")) && (strcmp(dptr->d_name, "..")) && ((dptr->d_type != DT_DIR) || (includeDirectories)))
|
||||
r.push_back(std::string(dptr->d_name));
|
||||
} else break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
closedir(d);
|
||||
#endif
|
||||
|
@ -138,57 +142,59 @@ std::vector<std::string> OSUtils::listDirectory(const char *path,bool includeDir
|
|||
return r;
|
||||
}
|
||||
|
||||
long OSUtils::cleanDirectory(const char *path,const int64_t olderThan)
|
||||
long OSUtils::cleanDirectory(const char* path, const int64_t olderThan)
|
||||
{
|
||||
long cleaned = 0;
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
HANDLE hFind;
|
||||
WIN32_FIND_DATAA ffd;
|
||||
LARGE_INTEGER date,adjust;
|
||||
LARGE_INTEGER date, adjust;
|
||||
adjust.QuadPart = 11644473600000 * 10000;
|
||||
char tmp[4096];
|
||||
if ((hFind = FindFirstFileA((std::string(path) + "\\*").c_str(),&ffd)) != INVALID_HANDLE_VALUE) {
|
||||
if ((hFind = FindFirstFileA((std::string(path) + "\\*").c_str(), &ffd)) != INVALID_HANDLE_VALUE) {
|
||||
do {
|
||||
if ((strcmp(ffd.cFileName,"."))&&(strcmp(ffd.cFileName,".."))&&((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)) {
|
||||
date.HighPart = ffd.ftLastWriteTime.dwHighDateTime;
|
||||
date.LowPart = ffd.ftLastWriteTime.dwLowDateTime;
|
||||
if (date.QuadPart > 0) {
|
||||
date.QuadPart -= adjust.QuadPart;
|
||||
if ((int64_t)((date.QuadPart / 10000000) * 1000) < olderThan) {
|
||||
ztsnprintf(tmp, sizeof(tmp), "%s\\%s", path, ffd.cFileName);
|
||||
if (DeleteFileA(tmp))
|
||||
++cleaned;
|
||||
}
|
||||
if ((strcmp(ffd.cFileName, ".")) && (strcmp(ffd.cFileName, "..")) && ((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)) {
|
||||
date.HighPart = ffd.ftLastWriteTime.dwHighDateTime;
|
||||
date.LowPart = ffd.ftLastWriteTime.dwLowDateTime;
|
||||
if (date.QuadPart > 0) {
|
||||
date.QuadPart -= adjust.QuadPart;
|
||||
if ((int64_t)((date.QuadPart / 10000000) * 1000) < olderThan) {
|
||||
ztsnprintf(tmp, sizeof(tmp), "%s\\%s", path, ffd.cFileName);
|
||||
if (DeleteFileA(tmp))
|
||||
++cleaned;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (FindNextFileA(hFind,&ffd));
|
||||
} while (FindNextFileA(hFind, &ffd));
|
||||
FindClose(hFind);
|
||||
}
|
||||
#else
|
||||
struct dirent de;
|
||||
struct dirent *dptr;
|
||||
struct dirent* dptr;
|
||||
struct stat st;
|
||||
char tmp[4096];
|
||||
DIR *d = opendir(path);
|
||||
if (!d)
|
||||
DIR* d = opendir(path);
|
||||
if (! d)
|
||||
return -1;
|
||||
dptr = (struct dirent *)0;
|
||||
for(;;) {
|
||||
if (readdir_r(d,&de,&dptr))
|
||||
dptr = (struct dirent*)0;
|
||||
for (;;) {
|
||||
if (readdir_r(d, &de, &dptr))
|
||||
break;
|
||||
if (dptr) {
|
||||
if ((strcmp(dptr->d_name,"."))&&(strcmp(dptr->d_name,".."))&&(dptr->d_type == DT_REG)) {
|
||||
ztsnprintf(tmp,sizeof(tmp),"%s/%s",path,dptr->d_name);
|
||||
if (stat(tmp,&st) == 0) {
|
||||
if ((strcmp(dptr->d_name, ".")) && (strcmp(dptr->d_name, "..")) && (dptr->d_type == DT_REG)) {
|
||||
ztsnprintf(tmp, sizeof(tmp), "%s/%s", path, dptr->d_name);
|
||||
if (stat(tmp, &st) == 0) {
|
||||
int64_t mt = (int64_t)(st.st_mtime);
|
||||
if ((mt > 0)&&((mt * 1000) < olderThan)) {
|
||||
if ((mt > 0) && ((mt * 1000) < olderThan)) {
|
||||
if (unlink(tmp) == 0)
|
||||
++cleaned;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
closedir(d);
|
||||
#endif
|
||||
|
@ -196,44 +202,45 @@ long OSUtils::cleanDirectory(const char *path,const int64_t olderThan)
|
|||
return cleaned;
|
||||
}
|
||||
|
||||
bool OSUtils::rmDashRf(const char *path)
|
||||
bool OSUtils::rmDashRf(const char* path)
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
HANDLE hFind;
|
||||
WIN32_FIND_DATAA ffd;
|
||||
if ((hFind = FindFirstFileA((std::string(path) + "\\*").c_str(),&ffd)) != INVALID_HANDLE_VALUE) {
|
||||
if ((hFind = FindFirstFileA((std::string(path) + "\\*").c_str(), &ffd)) != INVALID_HANDLE_VALUE) {
|
||||
do {
|
||||
if ((strcmp(ffd.cFileName,".") != 0)&&(strcmp(ffd.cFileName,"..") != 0)) {
|
||||
if ((strcmp(ffd.cFileName, ".") != 0) && (strcmp(ffd.cFileName, "..") != 0)) {
|
||||
if ((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
|
||||
if (DeleteFileA((std::string(path) + ZT_PATH_SEPARATOR_S + ffd.cFileName).c_str()) == FALSE)
|
||||
return false;
|
||||
} else {
|
||||
if (!rmDashRf((std::string(path) + ZT_PATH_SEPARATOR_S + ffd.cFileName).c_str()))
|
||||
}
|
||||
else {
|
||||
if (! rmDashRf((std::string(path) + ZT_PATH_SEPARATOR_S + ffd.cFileName).c_str()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} while (FindNextFileA(hFind,&ffd));
|
||||
} while (FindNextFileA(hFind, &ffd));
|
||||
FindClose(hFind);
|
||||
}
|
||||
return (RemoveDirectoryA(path) != FALSE);
|
||||
#else
|
||||
struct dirent de;
|
||||
struct dirent *dptr;
|
||||
DIR *d = opendir(path);
|
||||
if (!d)
|
||||
struct dirent* dptr;
|
||||
DIR* d = opendir(path);
|
||||
if (! d)
|
||||
return true;
|
||||
dptr = (struct dirent *)0;
|
||||
for(;;) {
|
||||
if (readdir_r(d,&de,&dptr) != 0)
|
||||
dptr = (struct dirent*)0;
|
||||
for (;;) {
|
||||
if (readdir_r(d, &de, &dptr) != 0)
|
||||
break;
|
||||
if (!dptr)
|
||||
if (! dptr)
|
||||
break;
|
||||
if ((strcmp(dptr->d_name,".") != 0)&&(strcmp(dptr->d_name,"..") != 0)&&(strlen(dptr->d_name) > 0)) {
|
||||
if ((strcmp(dptr->d_name, ".") != 0) && (strcmp(dptr->d_name, "..") != 0) && (strlen(dptr->d_name) > 0)) {
|
||||
std::string p(path);
|
||||
p.push_back(ZT_PATH_SEPARATOR);
|
||||
p.append(dptr->d_name);
|
||||
if (unlink(p.c_str()) != 0) { // unlink first will remove symlinks instead of recursing them
|
||||
if (!rmDashRf(p.c_str()))
|
||||
if (unlink(p.c_str()) != 0) { // unlink first will remove symlinks instead of recursing them
|
||||
if (! rmDashRf(p.c_str()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -243,10 +250,10 @@ bool OSUtils::rmDashRf(const char *path)
|
|||
#endif
|
||||
}
|
||||
|
||||
void OSUtils::lockDownFile(const char *path,bool isDir)
|
||||
void OSUtils::lockDownFile(const char* path, bool isDir)
|
||||
{
|
||||
#ifdef __UNIX_LIKE__
|
||||
chmod(path,isDir ? 0700 : 0600);
|
||||
chmod(path, isDir ? 0700 : 0600);
|
||||
#else
|
||||
#ifdef __WINDOWS__
|
||||
{
|
||||
|
@ -254,19 +261,19 @@ void OSUtils::lockDownFile(const char *path,bool isDir)
|
|||
PROCESS_INFORMATION processInfo;
|
||||
|
||||
startupInfo.cb = sizeof(startupInfo);
|
||||
memset(&startupInfo,0,sizeof(STARTUPINFOA));
|
||||
memset(&processInfo,0,sizeof(PROCESS_INFORMATION));
|
||||
if (CreateProcessA(NULL,(LPSTR)(std::string("C:\\Windows\\System32\\icacls.exe \"") + path + "\" /inheritance:d /Q").c_str(),NULL,NULL,FALSE,CREATE_NO_WINDOW,NULL,NULL,&startupInfo,&processInfo)) {
|
||||
WaitForSingleObject(processInfo.hProcess,INFINITE);
|
||||
memset(&startupInfo, 0, sizeof(STARTUPINFOA));
|
||||
memset(&processInfo, 0, sizeof(PROCESS_INFORMATION));
|
||||
if (CreateProcessA(NULL, (LPSTR)(std::string("C:\\Windows\\System32\\icacls.exe \"") + path + "\" /inheritance:d /Q").c_str(), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &startupInfo, &processInfo)) {
|
||||
WaitForSingleObject(processInfo.hProcess, INFINITE);
|
||||
CloseHandle(processInfo.hProcess);
|
||||
CloseHandle(processInfo.hThread);
|
||||
}
|
||||
|
||||
startupInfo.cb = sizeof(startupInfo);
|
||||
memset(&startupInfo,0,sizeof(STARTUPINFOA));
|
||||
memset(&processInfo,0,sizeof(PROCESS_INFORMATION));
|
||||
if (CreateProcessA(NULL,(LPSTR)(std::string("C:\\Windows\\System32\\icacls.exe \"") + path + "\" /remove *S-1-5-32-545 /Q").c_str(),NULL,NULL,FALSE,CREATE_NO_WINDOW,NULL,NULL,&startupInfo,&processInfo)) {
|
||||
WaitForSingleObject(processInfo.hProcess,INFINITE);
|
||||
memset(&startupInfo, 0, sizeof(STARTUPINFOA));
|
||||
memset(&processInfo, 0, sizeof(PROCESS_INFORMATION));
|
||||
if (CreateProcessA(NULL, (LPSTR)(std::string("C:\\Windows\\System32\\icacls.exe \"") + path + "\" /remove *S-1-5-32-545 /Q").c_str(), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &startupInfo, &processInfo)) {
|
||||
WaitForSingleObject(processInfo.hProcess, INFINITE);
|
||||
CloseHandle(processInfo.hProcess);
|
||||
CloseHandle(processInfo.hThread);
|
||||
}
|
||||
|
@ -285,28 +292,28 @@ void OSUtils::lockDownFile(const char *path,bool isDir)
|
|||
#endif
|
||||
}
|
||||
|
||||
uint64_t OSUtils::getLastModified(const char *path)
|
||||
uint64_t OSUtils::getLastModified(const char* path)
|
||||
{
|
||||
struct stat s;
|
||||
if (stat(path,&s))
|
||||
if (stat(path, &s))
|
||||
return 0;
|
||||
return (((uint64_t)s.st_mtime) * 1000ULL);
|
||||
}
|
||||
|
||||
bool OSUtils::fileExists(const char *path,bool followLinks)
|
||||
bool OSUtils::fileExists(const char* path, bool followLinks)
|
||||
{
|
||||
struct stat s;
|
||||
#ifdef __UNIX_LIKE__
|
||||
if (!followLinks)
|
||||
return (lstat(path,&s) == 0);
|
||||
if (! followLinks)
|
||||
return (lstat(path, &s) == 0);
|
||||
#endif
|
||||
return (stat(path,&s) == 0);
|
||||
return (stat(path, &s) == 0);
|
||||
}
|
||||
|
||||
int64_t OSUtils::getFileSize(const char *path)
|
||||
int64_t OSUtils::getFileSize(const char* path)
|
||||
{
|
||||
struct stat s;
|
||||
if (stat(path,&s))
|
||||
if (stat(path, &s))
|
||||
return -1;
|
||||
#ifdef __WINDOWS__
|
||||
return s.st_size;
|
||||
|
@ -317,16 +324,17 @@ int64_t OSUtils::getFileSize(const char *path)
|
|||
return -1;
|
||||
}
|
||||
|
||||
bool OSUtils::readFile(const char *path,std::string &buf)
|
||||
bool OSUtils::readFile(const char* path, std::string& buf)
|
||||
{
|
||||
char tmp[16384];
|
||||
FILE *f = fopen(path,"rb");
|
||||
FILE* f = fopen(path, "rb");
|
||||
if (f) {
|
||||
for(;;) {
|
||||
long n = (long)fread(tmp,1,sizeof(tmp),f);
|
||||
for (;;) {
|
||||
long n = (long)fread(tmp, 1, sizeof(tmp), f);
|
||||
if (n > 0)
|
||||
buf.append(tmp,n);
|
||||
else break;
|
||||
buf.append(tmp, n);
|
||||
else
|
||||
break;
|
||||
}
|
||||
fclose(f);
|
||||
return true;
|
||||
|
@ -334,14 +342,15 @@ bool OSUtils::readFile(const char *path,std::string &buf)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool OSUtils::writeFile(const char *path,const void *buf,unsigned int len)
|
||||
bool OSUtils::writeFile(const char* path, const void* buf, unsigned int len)
|
||||
{
|
||||
FILE *f = fopen(path,"wb");
|
||||
FILE* f = fopen(path, "wb");
|
||||
if (f) {
|
||||
if ((long)fwrite(buf,1,len,f) != (long)len) {
|
||||
if ((long)fwrite(buf, 1, len, f) != (long)len) {
|
||||
fclose(f);
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
|
@ -349,14 +358,14 @@ bool OSUtils::writeFile(const char *path,const void *buf,unsigned int len)
|
|||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> OSUtils::split(const char *s,const char *const sep,const char *esc,const char *quot)
|
||||
std::vector<std::string> OSUtils::split(const char* s, const char* const sep, const char* esc, const char* quot)
|
||||
{
|
||||
std::vector<std::string> fields;
|
||||
std::string buf;
|
||||
|
||||
if (!esc)
|
||||
if (! esc)
|
||||
esc = "";
|
||||
if (!quot)
|
||||
if (! quot)
|
||||
quot = "";
|
||||
|
||||
bool escapeState = false;
|
||||
|
@ -365,24 +374,30 @@ std::vector<std::string> OSUtils::split(const char *s,const char *const sep,cons
|
|||
if (escapeState) {
|
||||
escapeState = false;
|
||||
buf.push_back(*s);
|
||||
} else if (quoteState) {
|
||||
}
|
||||
else if (quoteState) {
|
||||
if (*s == quoteState) {
|
||||
quoteState = 0;
|
||||
fields.push_back(buf);
|
||||
buf.clear();
|
||||
} else buf.push_back(*s);
|
||||
} else {
|
||||
const char *quotTmp;
|
||||
if (strchr(esc,*s))
|
||||
}
|
||||
else
|
||||
buf.push_back(*s);
|
||||
}
|
||||
else {
|
||||
const char* quotTmp;
|
||||
if (strchr(esc, *s))
|
||||
escapeState = true;
|
||||
else if ((buf.size() <= 0)&&((quotTmp = strchr(quot,*s))))
|
||||
else if ((buf.size() <= 0) && ((quotTmp = strchr(quot, *s))))
|
||||
quoteState = *quotTmp;
|
||||
else if (strchr(sep,*s)) {
|
||||
if (!buf.empty()) {
|
||||
else if (strchr(sep, *s)) {
|
||||
if (! buf.empty()) {
|
||||
fields.push_back(buf);
|
||||
buf.clear();
|
||||
} // else skip runs of separators
|
||||
} else buf.push_back(*s);
|
||||
} // else skip runs of separators
|
||||
}
|
||||
else
|
||||
buf.push_back(*s);
|
||||
}
|
||||
++s;
|
||||
}
|
||||
|
@ -396,28 +411,28 @@ std::vector<std::string> OSUtils::split(const char *s,const char *const sep,cons
|
|||
std::string OSUtils::platformDefaultHomePath()
|
||||
{
|
||||
#ifdef __QNAP__
|
||||
char *cmd = "/sbin/getcfg zerotier Install_Path -f /etc/config/qpkg.conf";
|
||||
char buf[128];
|
||||
FILE *fp;
|
||||
if ((fp = popen(cmd, "r")) == NULL) {
|
||||
printf("Error opening pipe!\n");
|
||||
return NULL;
|
||||
}
|
||||
while (fgets(buf, 128, fp) != NULL) { }
|
||||
if(pclose(fp)) {
|
||||
printf("Command not found or exited with error status\n");
|
||||
return NULL;
|
||||
}
|
||||
std::string homeDir = std::string(buf);
|
||||
homeDir.erase(std::remove(homeDir.begin(), homeDir.end(), '\n'), homeDir.end());
|
||||
return homeDir;
|
||||
char* cmd = "/sbin/getcfg zerotier Install_Path -f /etc/config/qpkg.conf";
|
||||
char buf[128];
|
||||
FILE* fp;
|
||||
if ((fp = popen(cmd, "r")) == NULL) {
|
||||
printf("Error opening pipe!\n");
|
||||
return NULL;
|
||||
}
|
||||
while (fgets(buf, 128, fp) != NULL) {}
|
||||
if (pclose(fp)) {
|
||||
printf("Command not found or exited with error status\n");
|
||||
return NULL;
|
||||
}
|
||||
std::string homeDir = std::string(buf);
|
||||
homeDir.erase(std::remove(homeDir.begin(), homeDir.end(), '\n'), homeDir.end());
|
||||
return homeDir;
|
||||
#endif
|
||||
#ifdef __UBIQUITI__
|
||||
// Only persistent location after firmware upgrades
|
||||
return std::string("/config/zerotier-one");
|
||||
#endif
|
||||
|
||||
// Check for user-defined environment variable before using defaults
|
||||
// Check for user-defined environment variable before using defaults
|
||||
#ifdef __WINDOWS__
|
||||
DWORD bufferSize = 65535;
|
||||
std::string userDefinedPath;
|
||||
|
@ -426,7 +441,7 @@ std::string OSUtils::platformDefaultHomePath()
|
|||
return userDefinedPath;
|
||||
}
|
||||
#else
|
||||
if(const char* userDefinedPath = getenv("ZEROTIER_HOME")) {
|
||||
if (const char* userDefinedPath = getenv("ZEROTIER_HOME")) {
|
||||
return std::string(userDefinedPath);
|
||||
}
|
||||
#endif
|
||||
|
@ -449,44 +464,55 @@ std::string OSUtils::platformDefaultHomePath()
|
|||
|
||||
#endif
|
||||
|
||||
#else // not __UNIX_LIKE__
|
||||
#else // not __UNIX_LIKE__
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
// Look up app data folder on Windows, e.g. C:\ProgramData\...
|
||||
char buf[16384];
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL,CSIDL_COMMON_APPDATA,NULL,0,buf)))
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_COMMON_APPDATA, NULL, 0, buf)))
|
||||
return (std::string(buf) + "\\ZeroTier\\One");
|
||||
else return std::string("C:\\ZeroTier\\One");
|
||||
else
|
||||
return std::string("C:\\ZeroTier\\One");
|
||||
#else
|
||||
|
||||
return (std::string(ZT_PATH_SEPARATOR_S) + "ZeroTier" + ZT_PATH_SEPARATOR_S + "One"); // UNKNOWN PLATFORM
|
||||
return (std::string(ZT_PATH_SEPARATOR_S) + "ZeroTier" + ZT_PATH_SEPARATOR_S + "One"); // UNKNOWN PLATFORM
|
||||
|
||||
#endif
|
||||
|
||||
#endif // __UNIX_LIKE__ or not...
|
||||
#endif // __UNIX_LIKE__ or not...
|
||||
}
|
||||
|
||||
#ifndef OMIT_JSON_SUPPORT
|
||||
// Inline these massive JSON operations in one place only to reduce binary footprint and compile time
|
||||
nlohmann::json OSUtils::jsonParse(const std::string &buf) { return nlohmann::json::parse(buf.c_str()); }
|
||||
std::string OSUtils::jsonDump(const nlohmann::json &j,int indentation) { return j.dump(indentation); }
|
||||
nlohmann::json OSUtils::jsonParse(const std::string& buf)
|
||||
{
|
||||
return nlohmann::json::parse(buf.c_str());
|
||||
}
|
||||
std::string OSUtils::jsonDump(const nlohmann::json& j, int indentation)
|
||||
{
|
||||
return j.dump(indentation);
|
||||
}
|
||||
|
||||
uint64_t OSUtils::jsonInt(const nlohmann::json &jv,const uint64_t dfl)
|
||||
uint64_t OSUtils::jsonInt(const nlohmann::json& jv, const uint64_t dfl)
|
||||
{
|
||||
try {
|
||||
if (jv.is_number()) {
|
||||
return (uint64_t)jv;
|
||||
} else if (jv.is_string()) {
|
||||
}
|
||||
else if (jv.is_string()) {
|
||||
std::string s = jv;
|
||||
return Utils::strToU64(s.c_str());
|
||||
} else if (jv.is_boolean()) {
|
||||
}
|
||||
else if (jv.is_boolean()) {
|
||||
return ((bool)jv ? 1ULL : 0ULL);
|
||||
}
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return dfl;
|
||||
}
|
||||
|
||||
double OSUtils::jsonDouble(const nlohmann::json &jv,const double dfl)
|
||||
double OSUtils::jsonDouble(const nlohmann::json& jv, const double dfl)
|
||||
{
|
||||
try {
|
||||
if (jv.is_number()) {
|
||||
|
@ -495,39 +521,48 @@ double OSUtils::jsonDouble(const nlohmann::json &jv,const double dfl)
|
|||
else if (jv.is_string()) {
|
||||
std::string s = jv;
|
||||
return Utils::strToDouble(s.c_str());
|
||||
} else if (jv.is_boolean()) {
|
||||
}
|
||||
else if (jv.is_boolean()) {
|
||||
return (double)jv;
|
||||
}
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return dfl;
|
||||
}
|
||||
|
||||
uint64_t OSUtils::jsonIntHex(const nlohmann::json &jv,const uint64_t dfl)
|
||||
uint64_t OSUtils::jsonIntHex(const nlohmann::json& jv, const uint64_t dfl)
|
||||
{
|
||||
try {
|
||||
if (jv.is_number()) {
|
||||
return (uint64_t)jv;
|
||||
} else if (jv.is_string()) {
|
||||
}
|
||||
else if (jv.is_string()) {
|
||||
std::string s = jv;
|
||||
return Utils::hexStrToU64(s.c_str());
|
||||
} else if (jv.is_boolean()) {
|
||||
}
|
||||
else if (jv.is_boolean()) {
|
||||
return ((bool)jv ? 1ULL : 0ULL);
|
||||
}
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return dfl;
|
||||
}
|
||||
|
||||
bool OSUtils::jsonBool(const nlohmann::json &jv,const bool dfl)
|
||||
bool OSUtils::jsonBool(const nlohmann::json& jv, const bool dfl)
|
||||
{
|
||||
try {
|
||||
if (jv.is_boolean()) {
|
||||
return (bool)jv;
|
||||
} else if (jv.is_number()) {
|
||||
}
|
||||
else if (jv.is_number()) {
|
||||
return ((uint64_t)jv > 0ULL);
|
||||
} else if (jv.is_string()) {
|
||||
}
|
||||
else if (jv.is_string()) {
|
||||
std::string s = jv;
|
||||
if (s.length() > 0) {
|
||||
switch(s[0]) {
|
||||
switch (s[0]) {
|
||||
case 't':
|
||||
case 'T':
|
||||
case '1':
|
||||
|
@ -536,47 +571,62 @@ bool OSUtils::jsonBool(const nlohmann::json &jv,const bool dfl)
|
|||
}
|
||||
return false;
|
||||
}
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return dfl;
|
||||
}
|
||||
|
||||
std::string OSUtils::jsonString(const nlohmann::json &jv,const char *dfl)
|
||||
std::string OSUtils::jsonString(const nlohmann::json& jv, const char* dfl)
|
||||
{
|
||||
try {
|
||||
if (jv.is_string()) {
|
||||
return jv;
|
||||
} else if (jv.is_number()) {
|
||||
}
|
||||
else if (jv.is_number()) {
|
||||
char tmp[64];
|
||||
ztsnprintf(tmp,sizeof(tmp),"%llu",(uint64_t)jv);
|
||||
ztsnprintf(tmp, sizeof(tmp), "%llu", (uint64_t)jv);
|
||||
return tmp;
|
||||
} else if (jv.is_boolean()) {
|
||||
}
|
||||
else if (jv.is_boolean()) {
|
||||
return ((bool)jv ? std::string("1") : std::string("0"));
|
||||
}
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return std::string((dfl) ? dfl : "");
|
||||
}
|
||||
|
||||
std::string OSUtils::jsonBinFromHex(const nlohmann::json &jv)
|
||||
std::string OSUtils::jsonBinFromHex(const nlohmann::json& jv)
|
||||
{
|
||||
std::string s(jsonString(jv,""));
|
||||
std::string s(jsonString(jv, ""));
|
||||
if (s.length() > 0) {
|
||||
unsigned int buflen = (unsigned int)((s.length() / 2) + 1);
|
||||
char *buf = new char[buflen];
|
||||
char* buf = new char[buflen];
|
||||
try {
|
||||
unsigned int l = Utils::unhex(s.c_str(),buf,buflen);
|
||||
std::string b(buf,l);
|
||||
delete [] buf;
|
||||
unsigned int l = Utils::unhex(s.c_str(), buf, buflen);
|
||||
std::string b(buf, l);
|
||||
delete[] buf;
|
||||
return b;
|
||||
} catch ( ... ) {
|
||||
delete [] buf;
|
||||
}
|
||||
catch (...) {
|
||||
delete[] buf;
|
||||
}
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
#endif // OMIT_JSON_SUPPORT
|
||||
#endif // OMIT_JSON_SUPPORT
|
||||
|
||||
// Used to convert HTTP header names to ASCII lower case
|
||||
const unsigned char OSUtils::TOLOWER_TABLE[256] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };
|
||||
const unsigned char OSUtils::TOLOWER_TABLE[256] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
|
||||
0x1d, 0x1e, 0x1f, ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
':', ';', '<', '=', '>', '?', '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||
'w', 'x', 'y', 'z', '{', '|', '}', '~', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
|
||||
't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
|
||||
0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad,
|
||||
0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca,
|
||||
0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
||||
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -14,29 +14,28 @@
|
|||
#ifndef ZT_OSUTILS_HPP
|
||||
#define ZT_OSUTILS_HPP
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/InetAddress.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <vector>
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <shlwapi.h>
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#ifdef __LINUX__
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
|
@ -51,9 +50,8 @@ namespace ZeroTier {
|
|||
/**
|
||||
* Miscellaneous utility functions and global constants
|
||||
*/
|
||||
class OSUtils
|
||||
{
|
||||
public:
|
||||
class OSUtils {
|
||||
public:
|
||||
/**
|
||||
* Variant of snprintf that is portable and throws an exception
|
||||
*
|
||||
|
@ -66,11 +64,11 @@ public:
|
|||
* @param ... Format arguments
|
||||
* @throws std::length_error buf[] too short (buf[] will still be left null-terminated)
|
||||
*/
|
||||
static unsigned int ztsnprintf(char *buf,unsigned int len,const char *fmt,...);
|
||||
static unsigned int ztsnprintf(char* buf, unsigned int len, const char* fmt, ...);
|
||||
|
||||
/**
|
||||
* Converts a uint64_t network ID into a string
|
||||
*
|
||||
*
|
||||
* @param nwid network ID
|
||||
* @throws std::length_error buf[] too short (buf[] will still be left null-terminated)
|
||||
*/
|
||||
|
@ -78,7 +76,7 @@ public:
|
|||
|
||||
/**
|
||||
* Converts a uint64_t node ID into a string
|
||||
*
|
||||
*
|
||||
* @param nid node ID
|
||||
* @throws std::length_error buf[] too short (buf[] will still be left null-terminated)
|
||||
*/
|
||||
|
@ -95,9 +93,8 @@ public:
|
|||
* @param stderrPath Path to file to use for stderr, or NULL for same as stdout (default)
|
||||
* @return True on success
|
||||
*/
|
||||
static bool redirectUnixOutputs(const char *stdoutPath,const char *stderrPath = (const char *)0)
|
||||
throw();
|
||||
#endif // __UNIX_LIKE__
|
||||
static bool redirectUnixOutputs(const char* stdoutPath, const char* stderrPath = (const char*)0) throw();
|
||||
#endif // __UNIX_LIKE__
|
||||
|
||||
/**
|
||||
* Delete a file
|
||||
|
@ -105,7 +102,7 @@ public:
|
|||
* @param path Path to delete
|
||||
* @return True if delete was successful
|
||||
*/
|
||||
static inline bool rm(const char *path)
|
||||
static inline bool rm(const char* path)
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
return (DeleteFileA(path) != FALSE);
|
||||
|
@ -113,29 +110,35 @@ public:
|
|||
return (unlink(path) == 0);
|
||||
#endif
|
||||
}
|
||||
static inline bool rm(const std::string &path) { return rm(path.c_str()); }
|
||||
static inline bool rm(const std::string& path)
|
||||
{
|
||||
return rm(path.c_str());
|
||||
}
|
||||
|
||||
static inline bool mkdir(const char *path)
|
||||
static inline bool mkdir(const char* path)
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
if (::PathIsDirectoryA(path))
|
||||
return true;
|
||||
return (::CreateDirectoryA(path,NULL) == TRUE);
|
||||
return (::CreateDirectoryA(path, NULL) == TRUE);
|
||||
#else
|
||||
if (::mkdir(path,0755) != 0)
|
||||
if (::mkdir(path, 0755) != 0)
|
||||
return (errno == EEXIST);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
static inline bool mkdir(const std::string &path) { return OSUtils::mkdir(path.c_str()); }
|
||||
static inline bool mkdir(const std::string& path)
|
||||
{
|
||||
return OSUtils::mkdir(path.c_str());
|
||||
}
|
||||
|
||||
static inline bool rename(const char *o,const char *n)
|
||||
static inline bool rename(const char* o, const char* n)
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
DeleteFileA(n);
|
||||
return (::rename(o,n) == 0);
|
||||
return (::rename(o, n) == 0);
|
||||
#else
|
||||
return (::rename(o,n) == 0);
|
||||
return (::rename(o, n) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -146,7 +149,7 @@ public:
|
|||
* @param includeDirectories If true, include directories as well as files
|
||||
* @return Names of files in directory (without path prepended)
|
||||
*/
|
||||
static std::vector<std::string> listDirectory(const char *path,bool includeDirectories = false);
|
||||
static std::vector<std::string> listDirectory(const char* path, bool includeDirectories = false);
|
||||
|
||||
/**
|
||||
* Clean a directory of files whose last modified time is older than this
|
||||
|
@ -156,7 +159,7 @@ public:
|
|||
* @param olderThan Last modified older than timestamp (ms since epoch)
|
||||
* @return Number of cleaned files or negative on fatal error
|
||||
*/
|
||||
static long cleanDirectory(const char *path,const int64_t olderThan);
|
||||
static long cleanDirectory(const char* path, const int64_t olderThan);
|
||||
|
||||
/**
|
||||
* Delete a directory and all its files and subdirectories recursively
|
||||
|
@ -164,7 +167,7 @@ public:
|
|||
* @param path Path to delete
|
||||
* @return True on success
|
||||
*/
|
||||
static bool rmDashRf(const char *path);
|
||||
static bool rmDashRf(const char* path);
|
||||
|
||||
/**
|
||||
* Set modes on a file to something secure
|
||||
|
@ -175,7 +178,7 @@ public:
|
|||
* @param path Path to lock
|
||||
* @param isDir True if this is a directory
|
||||
*/
|
||||
static void lockDownFile(const char *path,bool isDir);
|
||||
static void lockDownFile(const char* path, bool isDir);
|
||||
|
||||
/**
|
||||
* Get file last modification time
|
||||
|
@ -186,20 +189,20 @@ public:
|
|||
* @param path Path to file to get time
|
||||
* @return Last modification time in ms since epoch or 0 if not found
|
||||
*/
|
||||
static uint64_t getLastModified(const char *path);
|
||||
static uint64_t getLastModified(const char* path);
|
||||
|
||||
/**
|
||||
* @param path Path to check
|
||||
* @param followLinks Follow links (on platforms with that concept)
|
||||
* @return True if file or directory exists at path location
|
||||
*/
|
||||
static bool fileExists(const char *path,bool followLinks = true);
|
||||
static bool fileExists(const char* path, bool followLinks = true);
|
||||
|
||||
/**
|
||||
* @param path Path to file
|
||||
* @return File size or -1 if nonexistent or other failure
|
||||
*/
|
||||
static int64_t getFileSize(const char *path);
|
||||
static int64_t getFileSize(const char* path);
|
||||
|
||||
/**
|
||||
* Get IP (v4 and/or v6) addresses for a given host
|
||||
|
@ -209,7 +212,7 @@ public:
|
|||
* @param name Host name
|
||||
* @return IP addresses in InetAddress sort order or empty vector if not found
|
||||
*/
|
||||
static std::vector<InetAddress> resolve(const char *name);
|
||||
static std::vector<InetAddress> resolve(const char* name);
|
||||
|
||||
/**
|
||||
* @return Current time in milliseconds since epoch
|
||||
|
@ -221,14 +224,14 @@ public:
|
|||
SYSTEMTIME st;
|
||||
ULARGE_INTEGER tmp;
|
||||
GetSystemTime(&st);
|
||||
SystemTimeToFileTime(&st,&ft);
|
||||
SystemTimeToFileTime(&st, &ft);
|
||||
tmp.LowPart = ft.dwLowDateTime;
|
||||
tmp.HighPart = ft.dwHighDateTime;
|
||||
return (int64_t)( ((tmp.QuadPart - 116444736000000000LL) / 10000L) + st.wMilliseconds );
|
||||
return (int64_t)(((tmp.QuadPart - 116444736000000000LL) / 10000L) + st.wMilliseconds);
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv,(struct timezone *)0);
|
||||
return ( (1000LL * (int64_t)tv.tv_sec) + (int64_t)(tv.tv_usec / 1000) );
|
||||
gettimeofday(&tv, (struct timezone*)0);
|
||||
return ((1000LL * (int64_t)tv.tv_sec) + (int64_t)(tv.tv_usec / 1000));
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -242,7 +245,7 @@ public:
|
|||
* @param buf Buffer to fill
|
||||
* @return True if open and read successful
|
||||
*/
|
||||
static bool readFile(const char *path,std::string &buf);
|
||||
static bool readFile(const char* path, std::string& buf);
|
||||
|
||||
/**
|
||||
* Write a block of data to disk, replacing any current file contents
|
||||
|
@ -252,7 +255,7 @@ public:
|
|||
* @param len Length of buffer
|
||||
* @return True if entire file was successfully written
|
||||
*/
|
||||
static bool writeFile(const char *path,const void *buf,unsigned int len);
|
||||
static bool writeFile(const char* path, const void* buf, unsigned int len);
|
||||
|
||||
/**
|
||||
* Split a string by delimiter, with optional escape and quote characters
|
||||
|
@ -263,7 +266,7 @@ public:
|
|||
* @param quot Zero or more quote characters
|
||||
* @return Vector of tokens
|
||||
*/
|
||||
static std::vector<std::string> split(const char *s,const char *const sep,const char *esc,const char *quot);
|
||||
static std::vector<std::string> split(const char* s, const char* const sep, const char* esc, const char* quot);
|
||||
|
||||
/**
|
||||
* Write a block of data to disk, replacing any current file contents
|
||||
|
@ -272,13 +275,19 @@ public:
|
|||
* @param s Data to write
|
||||
* @return True if entire file was successfully written
|
||||
*/
|
||||
static inline bool writeFile(const char *path,const std::string &s) { return writeFile(path,s.data(),(unsigned int)s.length()); }
|
||||
static inline bool writeFile(const char* path, const std::string& s)
|
||||
{
|
||||
return writeFile(path, s.data(), (unsigned int)s.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param c ASCII character to convert
|
||||
* @return Lower case ASCII character or unchanged if not a letter
|
||||
*/
|
||||
static inline char toLower(char c) throw() { return (char)OSUtils::TOLOWER_TABLE[(unsigned long)c]; }
|
||||
static inline char toLower(char c) throw()
|
||||
{
|
||||
return (char)OSUtils::TOLOWER_TABLE[(unsigned long)c];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Platform default ZeroTier One home path
|
||||
|
@ -286,20 +295,20 @@ public:
|
|||
static std::string platformDefaultHomePath();
|
||||
|
||||
#ifndef OMIT_JSON_SUPPORT
|
||||
static nlohmann::json jsonParse(const std::string &buf);
|
||||
static std::string jsonDump(const nlohmann::json &j,int indentation = 1);
|
||||
static uint64_t jsonInt(const nlohmann::json &jv,const uint64_t dfl);
|
||||
static double jsonDouble(const nlohmann::json &jv,const double dfl);
|
||||
static uint64_t jsonIntHex(const nlohmann::json &jv,const uint64_t dfl);
|
||||
static bool jsonBool(const nlohmann::json &jv,const bool dfl);
|
||||
static std::string jsonString(const nlohmann::json &jv,const char *dfl);
|
||||
static std::string jsonBinFromHex(const nlohmann::json &jv);
|
||||
#endif // OMIT_JSON_SUPPORT
|
||||
static nlohmann::json jsonParse(const std::string& buf);
|
||||
static std::string jsonDump(const nlohmann::json& j, int indentation = 1);
|
||||
static uint64_t jsonInt(const nlohmann::json& jv, const uint64_t dfl);
|
||||
static double jsonDouble(const nlohmann::json& jv, const double dfl);
|
||||
static uint64_t jsonIntHex(const nlohmann::json& jv, const uint64_t dfl);
|
||||
static bool jsonBool(const nlohmann::json& jv, const bool dfl);
|
||||
static std::string jsonString(const nlohmann::json& jv, const char* dfl);
|
||||
static std::string jsonBinFromHex(const nlohmann::json& jv);
|
||||
#endif // OMIT_JSON_SUPPORT
|
||||
|
||||
private:
|
||||
private:
|
||||
static const unsigned char TOLOWER_TABLE[256];
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
|
744
osdep/Phy.hpp
744
osdep/Phy.hpp
File diff suppressed because it is too large
Load diff
|
@ -14,7 +14,7 @@
|
|||
#ifdef ZT_USE_MINIUPNPC
|
||||
|
||||
// Uncomment to dump debug messages
|
||||
//#define ZT_PORTMAPPER_TRACE 1
|
||||
// #define ZT_PORTMAPPER_TRACE 1
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/log.h>
|
||||
|
@ -23,16 +23,15 @@
|
|||
#define PM_TRACE(...) fprintf(stderr, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "../node/Utils.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
#include "PortMapper.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
|
||||
// These must be defined to get rid of dynamic export stuff in libminiupnpc and libnatpmp
|
||||
#ifdef __WINDOWS__
|
||||
#ifndef MINIUPNP_STATICLIB
|
||||
|
@ -63,34 +62,30 @@
|
|||
|
||||
namespace ZeroTier {
|
||||
|
||||
class PortMapperImpl
|
||||
{
|
||||
public:
|
||||
PortMapperImpl(int localUdpPortToMap,const char *un) :
|
||||
run(true),
|
||||
localPort(localUdpPortToMap),
|
||||
uniqueName(un)
|
||||
class PortMapperImpl {
|
||||
public:
|
||||
PortMapperImpl(int localUdpPortToMap, const char* un) : run(true), localPort(localUdpPortToMap), uniqueName(un)
|
||||
{
|
||||
}
|
||||
|
||||
~PortMapperImpl() {}
|
||||
|
||||
void threadMain()
|
||||
throw()
|
||||
~PortMapperImpl()
|
||||
{
|
||||
int mode = 0; // 0 == NAT-PMP, 1 == UPnP
|
||||
}
|
||||
|
||||
void threadMain() throw()
|
||||
{
|
||||
int mode = 0; // 0 == NAT-PMP, 1 == UPnP
|
||||
int retrytime = 500;
|
||||
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
fprintf(stderr,"PortMapper: started for UDP port %d" ZT_EOL_S,localPort);
|
||||
fprintf(stderr, "PortMapper: started for UDP port %d" ZT_EOL_S, localPort);
|
||||
#endif
|
||||
|
||||
while (run) {
|
||||
|
||||
{
|
||||
// use initnatpmp to check if we can bind a port at all
|
||||
natpmp_t _natpmp;
|
||||
int result = initnatpmp(&_natpmp,0,0);
|
||||
int result = initnatpmp(&_natpmp, 0, 0);
|
||||
if (result == NATPMP_ERR_CANNOTGETGATEWAY || result == NATPMP_ERR_SOCKETERROR) {
|
||||
closenatpmp(&_natpmp);
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
|
@ -102,7 +97,8 @@ public:
|
|||
retrytime = ZT_PORTMAPPER_REFRESH_DELAY / 10;
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
closenatpmp(&_natpmp);
|
||||
retrytime = 500;
|
||||
}
|
||||
|
@ -111,24 +107,24 @@ public:
|
|||
// NAT-PMP mode (preferred)
|
||||
// ---------------------------------------------------------------------
|
||||
if (mode == 0) {
|
||||
natpmp_t natpmp;
|
||||
natpmpresp_t response;
|
||||
natpmp_t natpmp;
|
||||
natpmpresp_t response;
|
||||
int r = 0;
|
||||
|
||||
bool natPmpSuccess = false;
|
||||
for(int tries=0;tries<60;++tries) {
|
||||
for (int tries = 0; tries < 60; ++tries) {
|
||||
int tryPort = (int)localPort + tries;
|
||||
if (tryPort >= 65535)
|
||||
tryPort = (tryPort - 65535) + 1025;
|
||||
|
||||
memset(&natpmp,0,sizeof(natpmp));
|
||||
memset(&response,0,sizeof(response));
|
||||
memset(&natpmp, 0, sizeof(natpmp));
|
||||
memset(&response, 0, sizeof(response));
|
||||
|
||||
if (initnatpmp(&natpmp,0,0) != 0) {
|
||||
if (initnatpmp(&natpmp, 0, 0) != 0) {
|
||||
mode = 1;
|
||||
closenatpmp(&natpmp);
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: NAT-PMP: init failed, switching to UPnP mode" ZT_EOL_S);
|
||||
PM_TRACE("PortMapper: NAT-PMP: init failed, switching to UPnP mode" ZT_EOL_S);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
@ -148,33 +144,34 @@ public:
|
|||
break;
|
||||
} while (r == NATPMP_TRYAGAIN);
|
||||
if (r == 0) {
|
||||
publicAddress = InetAddress((uint32_t)response.pnu.publicaddress.addr.s_addr,0);
|
||||
} else {
|
||||
publicAddress = InetAddress((uint32_t)response.pnu.publicaddress.addr.s_addr, 0);
|
||||
}
|
||||
else {
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: NAT-PMP: request for external address failed, aborting..." ZT_EOL_S);
|
||||
PM_TRACE("PortMapper: NAT-PMP: request for external address failed, aborting..." ZT_EOL_S);
|
||||
#endif
|
||||
closenatpmp(&natpmp);
|
||||
break;
|
||||
}
|
||||
|
||||
sendnewportmappingrequest(&natpmp,NATPMP_PROTOCOL_UDP,localPort,tryPort,(ZT_PORTMAPPER_REFRESH_DELAY * 2) / 1000);
|
||||
sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_UDP, localPort, tryPort, (ZT_PORTMAPPER_REFRESH_DELAY * 2) / 1000);
|
||||
myTimeout = OSUtils::now() + 10000;
|
||||
do {
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(natpmp.s, &fds);
|
||||
getnatpmprequesttimeout(&natpmp, &timeout);
|
||||
select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
|
||||
r = readnatpmpresponseorretry(&natpmp, &response);
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(natpmp.s, &fds);
|
||||
getnatpmprequesttimeout(&natpmp, &timeout);
|
||||
select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
|
||||
r = readnatpmpresponseorretry(&natpmp, &response);
|
||||
if (OSUtils::now() >= myTimeout)
|
||||
break;
|
||||
} while (r == NATPMP_TRYAGAIN);
|
||||
} while (r == NATPMP_TRYAGAIN);
|
||||
if (r == 0) {
|
||||
publicAddress.setPort(response.pnu.newportmapping.mappedpublicport);
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
char paddr[128];
|
||||
PM_TRACE("PortMapper: NAT-PMP: mapped %u to %s" ZT_EOL_S,(unsigned int)localPort,publicAddress.toString(paddr));
|
||||
char paddr[128];
|
||||
PM_TRACE("PortMapper: NAT-PMP: mapped %u to %s" ZT_EOL_S, (unsigned int)localPort, publicAddress.toString(paddr));
|
||||
#endif
|
||||
Mutex::Lock sl(surface_l);
|
||||
surface.clear();
|
||||
|
@ -182,16 +179,17 @@ public:
|
|||
natPmpSuccess = true;
|
||||
closenatpmp(&natpmp);
|
||||
break;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
closenatpmp(&natpmp);
|
||||
// continue
|
||||
}
|
||||
}
|
||||
|
||||
if (!natPmpSuccess) {
|
||||
if (! natPmpSuccess) {
|
||||
mode = 1;
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: NAT-PMP: request failed, switching to UPnP mode" ZT_EOL_S);
|
||||
PM_TRACE("PortMapper: NAT-PMP: request failed, switching to UPnP mode" ZT_EOL_S);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
@ -203,66 +201,66 @@ public:
|
|||
// ---------------------------------------------------------------------
|
||||
if (mode == 1) {
|
||||
char lanaddr[4096];
|
||||
char externalip[4096]; // no range checking? so make these buffers larger than any UDP packet a uPnP server could send us as a precaution :P
|
||||
char externalip[4096]; // no range checking? so make these buffers larger than any UDP packet a uPnP server could send us as a precaution :P
|
||||
char inport[16];
|
||||
char outport[16];
|
||||
struct UPNPUrls urls;
|
||||
struct IGDdatas data;
|
||||
|
||||
int upnpError = 0;
|
||||
UPNPDev *devlist = upnpDiscoverAll(5000,(const char *)0,(const char *)0,0,0,2,&upnpError);
|
||||
UPNPDev* devlist = upnpDiscoverAll(5000, (const char*)0, (const char*)0, 0, 0, 2, &upnpError);
|
||||
if (devlist) {
|
||||
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
{
|
||||
UPNPDev *dev = devlist;
|
||||
UPNPDev* dev = devlist;
|
||||
while (dev) {
|
||||
PM_TRACE("PortMapper: found UPnP device at URL '%s': %s" ZT_EOL_S,dev->descURL,dev->st);
|
||||
PM_TRACE("PortMapper: found UPnP device at URL '%s': %s" ZT_EOL_S, dev->descURL, dev->st);
|
||||
dev = dev->pNext;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(lanaddr,0,sizeof(lanaddr));
|
||||
memset(externalip,0,sizeof(externalip));
|
||||
memset(&urls,0,sizeof(urls));
|
||||
memset(&data,0,sizeof(data));
|
||||
OSUtils::ztsnprintf(inport,sizeof(inport),"%d",localPort);
|
||||
memset(lanaddr, 0, sizeof(lanaddr));
|
||||
memset(externalip, 0, sizeof(externalip));
|
||||
memset(&urls, 0, sizeof(urls));
|
||||
memset(&data, 0, sizeof(data));
|
||||
OSUtils::ztsnprintf(inport, sizeof(inport), "%d", localPort);
|
||||
|
||||
int foundValidIGD = 0;
|
||||
if ((foundValidIGD = UPNP_GetValidIGD(devlist,&urls,&data,lanaddr,sizeof(lanaddr)))&&(lanaddr[0])) {
|
||||
if ((foundValidIGD = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr))) && (lanaddr[0])) {
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: UPnP: my LAN IP address: %s" ZT_EOL_S,lanaddr);
|
||||
PM_TRACE("PortMapper: UPnP: my LAN IP address: %s" ZT_EOL_S, lanaddr);
|
||||
#endif
|
||||
if ((UPNP_GetExternalIPAddress(urls.controlURL,data.first.servicetype,externalip) == UPNPCOMMAND_SUCCESS)&&(externalip[0])) {
|
||||
if ((UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalip) == UPNPCOMMAND_SUCCESS) && (externalip[0])) {
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: UPnP: my external IP address: %s" ZT_EOL_S,externalip);
|
||||
PM_TRACE("PortMapper: UPnP: my external IP address: %s" ZT_EOL_S, externalip);
|
||||
#endif
|
||||
|
||||
for(int tries=0;tries<60;++tries) {
|
||||
for (int tries = 0; tries < 60; ++tries) {
|
||||
int tryPort = (int)localPort + tries;
|
||||
if (tryPort >= 65535)
|
||||
tryPort = (tryPort - 65535) + 1025;
|
||||
OSUtils::ztsnprintf(outport,sizeof(outport),"%u",tryPort);
|
||||
OSUtils::ztsnprintf(outport, sizeof(outport), "%u", tryPort);
|
||||
|
||||
// First check and see if this port is already mapped to the
|
||||
// same unique name. If so, keep this mapping and don't try
|
||||
// to map again since this can break buggy routers. But don't
|
||||
// fail if this command fails since not all routers support it.
|
||||
{
|
||||
char haveIntClient[128]; // 128 == big enough for all these as per miniupnpc "documentation"
|
||||
char haveIntClient[128]; // 128 == big enough for all these as per miniupnpc "documentation"
|
||||
char haveIntPort[128];
|
||||
char haveDesc[128];
|
||||
char haveEnabled[128];
|
||||
char haveLeaseDuration[128];
|
||||
memset(haveIntClient,0,sizeof(haveIntClient));
|
||||
memset(haveIntPort,0,sizeof(haveIntPort));
|
||||
memset(haveDesc,0,sizeof(haveDesc));
|
||||
memset(haveEnabled,0,sizeof(haveEnabled));
|
||||
memset(haveLeaseDuration,0,sizeof(haveLeaseDuration));
|
||||
if ((UPNP_GetSpecificPortMappingEntry(urls.controlURL,data.first.servicetype,outport,"UDP",(const char *)0,haveIntClient,haveIntPort,haveDesc,haveEnabled,haveLeaseDuration) == UPNPCOMMAND_SUCCESS)&&(uniqueName == haveDesc)) {
|
||||
memset(haveIntClient, 0, sizeof(haveIntClient));
|
||||
memset(haveIntPort, 0, sizeof(haveIntPort));
|
||||
memset(haveDesc, 0, sizeof(haveDesc));
|
||||
memset(haveEnabled, 0, sizeof(haveEnabled));
|
||||
memset(haveLeaseDuration, 0, sizeof(haveLeaseDuration));
|
||||
if ((UPNP_GetSpecificPortMappingEntry(urls.controlURL, data.first.servicetype, outport, "UDP", (const char*)0, haveIntClient, haveIntPort, haveDesc, haveEnabled, haveLeaseDuration) == UPNPCOMMAND_SUCCESS)
|
||||
&& (uniqueName == haveDesc)) {
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: UPnP: reusing previously reserved external port: %s" ZT_EOL_S,outport);
|
||||
PM_TRACE("PortMapper: UPnP: reusing previously reserved external port: %s" ZT_EOL_S, outport);
|
||||
#endif
|
||||
Mutex::Lock sl(surface_l);
|
||||
surface.clear();
|
||||
|
@ -275,9 +273,9 @@ public:
|
|||
|
||||
// Try to map this port
|
||||
int mapResult = 0;
|
||||
if ((mapResult = UPNP_AddPortMapping(urls.controlURL,data.first.servicetype,outport,inport,lanaddr,uniqueName.c_str(),"UDP",(const char *)0,"0")) == UPNPCOMMAND_SUCCESS) {
|
||||
if ((mapResult = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, outport, inport, lanaddr, uniqueName.c_str(), "UDP", (const char*)0, "0")) == UPNPCOMMAND_SUCCESS) {
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: UPnP: reserved external port: %s" ZT_EOL_S,outport);
|
||||
PM_TRACE("PortMapper: UPnP: reserved external port: %s" ZT_EOL_S, outport);
|
||||
#endif
|
||||
Mutex::Lock sl(surface_l);
|
||||
surface.clear();
|
||||
|
@ -285,42 +283,45 @@ public:
|
|||
tmp.setPort(tryPort);
|
||||
surface.push_back(tmp);
|
||||
break;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: UPnP: UPNP_AddPortMapping(%s) failed: %d" ZT_EOL_S,outport,mapResult);
|
||||
PM_TRACE("PortMapper: UPnP: UPNP_AddPortMapping(%s) failed: %d" ZT_EOL_S, outport, mapResult);
|
||||
#endif
|
||||
Thread::sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
mode = 0;
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: UPnP: UPNP_GetExternalIPAddress failed, returning to NAT-PMP mode" ZT_EOL_S);
|
||||
PM_TRACE("PortMapper: UPnP: UPNP_GetExternalIPAddress failed, returning to NAT-PMP mode" ZT_EOL_S);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
mode = 0;
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: UPnP: UPNP_GetValidIGD failed, returning to NAT-PMP mode" ZT_EOL_S);
|
||||
PM_TRACE("PortMapper: UPnP: UPNP_GetValidIGD failed, returning to NAT-PMP mode" ZT_EOL_S);
|
||||
#endif
|
||||
}
|
||||
freeUPNPDevlist(devlist);
|
||||
|
||||
if(foundValidIGD) {
|
||||
if (foundValidIGD) {
|
||||
FreeUPNPUrls(&urls);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
mode = 0;
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("PortMapper: upnpDiscover failed, returning to NAT-PMP mode: %d" ZT_EOL_S,upnpError);
|
||||
PM_TRACE("PortMapper: upnpDiscover failed, returning to NAT-PMP mode: %d" ZT_EOL_S, upnpError);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
#ifdef ZT_PORTMAPPER_TRACE
|
||||
PM_TRACE("UPNPClient: rescanning in %d ms" ZT_EOL_S,ZT_PORTMAPPER_REFRESH_DELAY);
|
||||
PM_TRACE("UPNPClient: rescanning in %d ms" ZT_EOL_S, ZT_PORTMAPPER_REFRESH_DELAY);
|
||||
#endif
|
||||
Thread::sleep(ZT_PORTMAPPER_REFRESH_DELAY);
|
||||
}
|
||||
|
@ -336,9 +337,9 @@ public:
|
|||
std::vector<InetAddress> surface;
|
||||
};
|
||||
|
||||
PortMapper::PortMapper(int localUdpPortToMap,const char *uniqueName)
|
||||
PortMapper::PortMapper(int localUdpPortToMap, const char* uniqueName)
|
||||
{
|
||||
_impl = new PortMapperImpl(localUdpPortToMap,uniqueName);
|
||||
_impl = new PortMapperImpl(localUdpPortToMap, uniqueName);
|
||||
Thread::start(_impl);
|
||||
}
|
||||
|
||||
|
@ -353,6 +354,6 @@ std::vector<InetAddress> PortMapper::get() const
|
|||
return _impl->surface;
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif // ZT_USE_MINIUPNPC
|
||||
#endif // ZT_USE_MINIUPNPC
|
||||
|
|
|
@ -16,13 +16,13 @@
|
|||
#ifndef ZT_PORTMAPPER_HPP
|
||||
#define ZT_PORTMAPPER_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/InetAddress.hpp"
|
||||
#include "../node/Mutex.hpp"
|
||||
#include "Thread.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* How frequently should we refresh our UPNP/NAT-PnP/whatever state?
|
||||
*/
|
||||
|
@ -35,18 +35,17 @@ class PortMapperImpl;
|
|||
/**
|
||||
* UPnP/NAT-PnP port mapping "daemon"
|
||||
*/
|
||||
class PortMapper
|
||||
{
|
||||
class PortMapper {
|
||||
friend class PortMapperImpl;
|
||||
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Create and start port mapper service
|
||||
*
|
||||
* @param localUdpPortToMap Port we want visible to the outside world
|
||||
* @param name Unique name of this endpoint (based on ZeroTier address)
|
||||
*/
|
||||
PortMapper(int localUdpPortToMap,const char *uniqueName);
|
||||
PortMapper(int localUdpPortToMap, const char* uniqueName);
|
||||
|
||||
~PortMapper();
|
||||
|
||||
|
@ -55,12 +54,12 @@ public:
|
|||
*/
|
||||
std::vector<InetAddress> get() const;
|
||||
|
||||
private:
|
||||
PortMapperImpl *_impl;
|
||||
private:
|
||||
PortMapperImpl* _impl;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
||||
#endif // ZT_USE_MINIUPNPC
|
||||
#endif // ZT_USE_MINIUPNPC
|
||||
|
|
113
osdep/Thread.hpp
113
osdep/Thread.hpp
|
@ -14,57 +14,57 @@
|
|||
#ifndef ZT_THREAD_HPP
|
||||
#define ZT_THREAD_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../node/Mutex.hpp"
|
||||
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
template<typename C>
|
||||
static DWORD WINAPI ___zt_threadMain(LPVOID lpParam)
|
||||
template <typename C> static DWORD WINAPI ___zt_threadMain(LPVOID lpParam)
|
||||
{
|
||||
try {
|
||||
((C *)lpParam)->threadMain();
|
||||
} catch ( ... ) {}
|
||||
((C*)lpParam)->threadMain();
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
class Thread
|
||||
{
|
||||
public:
|
||||
class Thread {
|
||||
public:
|
||||
Thread()
|
||||
{
|
||||
_th = NULL;
|
||||
_tid = 0;
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
static inline Thread start(C *instance)
|
||||
template <typename C> static inline Thread start(C* instance)
|
||||
{
|
||||
Thread t;
|
||||
t._th = CreateThread(NULL,0,&___zt_threadMain<C>,(LPVOID)instance,0,&t._tid);
|
||||
t._th = CreateThread(NULL, 0, &___zt_threadMain<C>, (LPVOID)instance, 0, &t._tid);
|
||||
if (t._th == NULL)
|
||||
throw std::runtime_error("CreateThread() failed");
|
||||
return t;
|
||||
}
|
||||
|
||||
static inline void join(const Thread &t)
|
||||
static inline void join(const Thread& t)
|
||||
{
|
||||
if (t._th != NULL) {
|
||||
for(;;) {
|
||||
for (;;) {
|
||||
DWORD ec = STILL_ACTIVE;
|
||||
GetExitCodeThread(t._th,&ec);
|
||||
GetExitCodeThread(t._th, &ec);
|
||||
if (ec == STILL_ACTIVE)
|
||||
WaitForSingleObject(t._th,1000);
|
||||
else break;
|
||||
WaitForSingleObject(t._th, 1000);
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,61 +75,64 @@ public:
|
|||
}
|
||||
|
||||
// Not available on *nix platforms
|
||||
static inline void cancelIO(const Thread &t)
|
||||
static inline void cancelIO(const Thread& t)
|
||||
{
|
||||
#if !defined(__MINGW32__) && !defined(__MINGW64__) // CancelSynchronousIo not available in MSYS2
|
||||
#if ! defined(__MINGW32__) && ! defined(__MINGW64__) // CancelSynchronousIo not available in MSYS2
|
||||
if (t._th != NULL)
|
||||
CancelSynchronousIo(t._th);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline operator bool() const { return (_th != NULL); }
|
||||
inline operator bool() const
|
||||
{
|
||||
return (_th != NULL);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
HANDLE _th;
|
||||
DWORD _tid;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#else
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
template<typename C>
|
||||
static void *___zt_threadMain(void *instance)
|
||||
template <typename C> static void* ___zt_threadMain(void* instance)
|
||||
{
|
||||
try {
|
||||
((C *)instance)->threadMain();
|
||||
} catch ( ... ) {}
|
||||
return (void *)0;
|
||||
((C*)instance)->threadMain();
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
/**
|
||||
* A thread identifier, and static methods to start and join threads
|
||||
*/
|
||||
class Thread
|
||||
{
|
||||
public:
|
||||
class Thread {
|
||||
public:
|
||||
Thread()
|
||||
{
|
||||
memset(this,0,sizeof(Thread));
|
||||
memset(this, 0, sizeof(Thread));
|
||||
}
|
||||
|
||||
Thread(const Thread &t)
|
||||
Thread(const Thread& t)
|
||||
{
|
||||
memcpy(this,&t,sizeof(Thread));
|
||||
memcpy(this, &t, sizeof(Thread));
|
||||
}
|
||||
|
||||
inline Thread &operator=(const Thread &t)
|
||||
inline Thread& operator=(const Thread& t)
|
||||
{
|
||||
memcpy(this,&t,sizeof(Thread));
|
||||
memcpy(this, &t, sizeof(Thread));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -141,19 +144,19 @@ public:
|
|||
* @throws std::runtime_error Unable to create thread
|
||||
* @tparam C Class containing threadMain()
|
||||
*/
|
||||
template<typename C>
|
||||
static inline Thread start(C *instance)
|
||||
template <typename C> static inline Thread start(C* instance)
|
||||
{
|
||||
Thread t;
|
||||
pthread_attr_t tattr;
|
||||
pthread_attr_init(&tattr);
|
||||
// This corrects for systems with abnormally small defaults (musl) and also
|
||||
// shrinks the stack on systems with large defaults to save a bit of memory.
|
||||
pthread_attr_setstacksize(&tattr,ZT_THREAD_MIN_STACK_SIZE);
|
||||
if (pthread_create(&t._tid,&tattr,&___zt_threadMain<C>,instance)) {
|
||||
pthread_attr_setstacksize(&tattr, ZT_THREAD_MIN_STACK_SIZE);
|
||||
if (pthread_create(&t._tid, &tattr, &___zt_threadMain<C>, instance)) {
|
||||
pthread_attr_destroy(&tattr);
|
||||
throw std::runtime_error("pthread_create() failed, unable to create thread");
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
t._started = true;
|
||||
pthread_attr_destroy(&tattr);
|
||||
}
|
||||
|
@ -165,10 +168,10 @@ public:
|
|||
*
|
||||
* @param t Thread to join
|
||||
*/
|
||||
static inline void join(const Thread &t)
|
||||
static inline void join(const Thread& t)
|
||||
{
|
||||
if (t._started)
|
||||
pthread_join(t._tid,(void **)0);
|
||||
pthread_join(t._tid, (void**)0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -176,17 +179,23 @@ public:
|
|||
*
|
||||
* @param ms Number of milliseconds to sleep
|
||||
*/
|
||||
static inline void sleep(unsigned long ms) { usleep(ms * 1000); }
|
||||
static inline void sleep(unsigned long ms)
|
||||
{
|
||||
usleep(ms * 1000);
|
||||
}
|
||||
|
||||
inline operator bool() const { return (_started); }
|
||||
inline operator bool() const
|
||||
{
|
||||
return (_started);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
pthread_t _tid;
|
||||
volatile bool _started;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif // __WINDOWS__ / !__WINDOWS__
|
||||
#endif // __WINDOWS__ / !__WINDOWS__
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
#include "WinDNSHelper.hpp"
|
||||
|
||||
#include <comdef.h>
|
||||
#include <WbemIdl.h>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <comdef.h>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <strsafe.h>
|
||||
#include <vector>
|
||||
|
||||
#define MAX_KEY_LENGTH 255
|
||||
#define MAX_VALUE_NAME 16383
|
||||
|
||||
namespace ZeroTier
|
||||
{
|
||||
namespace ZeroTier {
|
||||
|
||||
BOOL RegDelnodeRecurse(HKEY hKeyRoot, LPTSTR lpSubKey)
|
||||
{
|
||||
|
@ -33,8 +31,7 @@ BOOL RegDelnodeRecurse(HKEY hKeyRoot, LPTSTR lpSubKey)
|
|||
|
||||
lResult = RegOpenKeyEx(hKeyRoot, lpSubKey, 0, KEY_READ, &hKey);
|
||||
|
||||
if (lResult != ERROR_SUCCESS)
|
||||
{
|
||||
if (lResult != ERROR_SUCCESS) {
|
||||
if (lResult == ERROR_FILE_NOT_FOUND) {
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -47,8 +44,7 @@ BOOL RegDelnodeRecurse(HKEY hKeyRoot, LPTSTR lpSubKey)
|
|||
|
||||
lpEnd = lpSubKey + lstrlen(lpSubKey);
|
||||
|
||||
if (*(lpEnd - 1) != TEXT('\\'))
|
||||
{
|
||||
if (*(lpEnd - 1) != TEXT('\\')) {
|
||||
*lpEnd = TEXT('\\');
|
||||
lpEnd++;
|
||||
*lpEnd = TEXT('\0');
|
||||
|
@ -57,24 +53,20 @@ BOOL RegDelnodeRecurse(HKEY hKeyRoot, LPTSTR lpSubKey)
|
|||
// Enumerate the keys
|
||||
|
||||
dwSize = MAX_PATH;
|
||||
lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
|
||||
NULL, NULL, &ftWrite);
|
||||
lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite);
|
||||
|
||||
if (lResult == ERROR_SUCCESS)
|
||||
{
|
||||
if (lResult == ERROR_SUCCESS) {
|
||||
do {
|
||||
|
||||
*lpEnd = TEXT('\0');
|
||||
StringCchCat(lpSubKey, MAX_PATH * 2, szName);
|
||||
|
||||
if (!RegDelnodeRecurse(hKeyRoot, lpSubKey)) {
|
||||
if (! RegDelnodeRecurse(hKeyRoot, lpSubKey)) {
|
||||
break;
|
||||
}
|
||||
|
||||
dwSize = MAX_PATH;
|
||||
|
||||
lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
|
||||
NULL, NULL, &ftWrite);
|
||||
lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite);
|
||||
|
||||
} while (lResult == ERROR_SUCCESS);
|
||||
}
|
||||
|
@ -114,61 +106,47 @@ BOOL RegDelnode(HKEY hKeyRoot, LPCTSTR lpSubKey)
|
|||
|
||||
StringCchCopy(szDelKey, MAX_PATH * 2, lpSubKey);
|
||||
return RegDelnodeRecurse(hKeyRoot, szDelKey);
|
||||
|
||||
}
|
||||
std::vector<std::string> getSubKeys(const char* key)
|
||||
{
|
||||
std::vector<std::string> subkeys;
|
||||
HKEY hKey;
|
||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
||||
key,
|
||||
0,
|
||||
KEY_READ,
|
||||
&hKey) == ERROR_SUCCESS) {
|
||||
|
||||
TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name
|
||||
DWORD cbName; // size of name string
|
||||
TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name
|
||||
DWORD cchClassName = MAX_PATH; // size of class string
|
||||
DWORD cSubKeys = 0; // number of subkeys
|
||||
DWORD cbMaxSubKey; // longest subkey size
|
||||
DWORD cchMaxClass; // longest class string
|
||||
DWORD cValues; // number of values for key
|
||||
DWORD cchMaxValue; // longest value name
|
||||
DWORD cbMaxValueData; // longest value data
|
||||
DWORD cbSecurityDescriptor; // size of security descriptor
|
||||
FILETIME ftLastWriteTime; // last write time
|
||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
|
||||
TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name
|
||||
DWORD cbName; // size of name string
|
||||
TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name
|
||||
DWORD cchClassName = MAX_PATH; // size of class string
|
||||
DWORD cSubKeys = 0; // number of subkeys
|
||||
DWORD cbMaxSubKey; // longest subkey size
|
||||
DWORD cchMaxClass; // longest class string
|
||||
DWORD cValues; // number of values for key
|
||||
DWORD cchMaxValue; // longest value name
|
||||
DWORD cbMaxValueData; // longest value data
|
||||
DWORD cbSecurityDescriptor; // size of security descriptor
|
||||
FILETIME ftLastWriteTime; // last write time
|
||||
|
||||
DWORD i, retCode;
|
||||
|
||||
TCHAR achValue[MAX_VALUE_NAME];
|
||||
TCHAR achValue[MAX_VALUE_NAME];
|
||||
DWORD cchValue = MAX_VALUE_NAME;
|
||||
|
||||
retCode = RegQueryInfoKey(
|
||||
hKey, // key handle
|
||||
achClass, // buffer for class name
|
||||
&cchClassName, // size of class string
|
||||
NULL, // reserved
|
||||
&cSubKeys, // number of subkeys
|
||||
&cbMaxSubKey, // longest subkey size
|
||||
&cchMaxClass, // longest class string
|
||||
&cValues, // number of values for this key
|
||||
&cchMaxValue, // longest value name
|
||||
&cbMaxValueData, // longest value data
|
||||
&cbSecurityDescriptor, // security descriptor
|
||||
&ftLastWriteTime); // last write time
|
||||
hKey, // key handle
|
||||
achClass, // buffer for class name
|
||||
&cchClassName, // size of class string
|
||||
NULL, // reserved
|
||||
&cSubKeys, // number of subkeys
|
||||
&cbMaxSubKey, // longest subkey size
|
||||
&cchMaxClass, // longest class string
|
||||
&cValues, // number of values for this key
|
||||
&cchMaxValue, // longest value name
|
||||
&cbMaxValueData, // longest value data
|
||||
&cbSecurityDescriptor, // security descriptor
|
||||
&ftLastWriteTime); // last write time
|
||||
|
||||
for (i = 0; i < cSubKeys; ++i) {
|
||||
cbName = MAX_KEY_LENGTH;
|
||||
retCode = RegEnumKeyEx(
|
||||
hKey,
|
||||
i,
|
||||
achKey,
|
||||
&cbName,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&ftLastWriteTime);
|
||||
retCode = RegEnumKeyEx(hKey, i, achKey, &cbName, NULL, NULL, NULL, &ftLastWriteTime);
|
||||
if (retCode == ERROR_SUCCESS) {
|
||||
subkeys.push_back(achKey);
|
||||
}
|
||||
|
@ -178,59 +156,47 @@ std::vector<std::string> getSubKeys(const char* key)
|
|||
return subkeys;
|
||||
}
|
||||
|
||||
std::vector<std::string> getValueList(const char* key) {
|
||||
std::vector<std::string> getValueList(const char* key)
|
||||
{
|
||||
std::vector<std::string> values;
|
||||
HKEY hKey;
|
||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
||||
key,
|
||||
0,
|
||||
KEY_READ,
|
||||
&hKey) == ERROR_SUCCESS) {
|
||||
|
||||
TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name
|
||||
DWORD cbName; // size of name string
|
||||
TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name
|
||||
DWORD cchClassName = MAX_PATH; // size of class string
|
||||
DWORD cSubKeys = 0; // number of subkeys
|
||||
DWORD cbMaxSubKey; // longest subkey size
|
||||
DWORD cchMaxClass; // longest class string
|
||||
DWORD cValues; // number of values for key
|
||||
DWORD cchMaxValue; // longest value name
|
||||
DWORD cbMaxValueData; // longest value data
|
||||
DWORD cbSecurityDescriptor; // size of security descriptor
|
||||
FILETIME ftLastWriteTime; // last write time
|
||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
|
||||
TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name
|
||||
DWORD cbName; // size of name string
|
||||
TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name
|
||||
DWORD cchClassName = MAX_PATH; // size of class string
|
||||
DWORD cSubKeys = 0; // number of subkeys
|
||||
DWORD cbMaxSubKey; // longest subkey size
|
||||
DWORD cchMaxClass; // longest class string
|
||||
DWORD cValues; // number of values for key
|
||||
DWORD cchMaxValue; // longest value name
|
||||
DWORD cbMaxValueData; // longest value data
|
||||
DWORD cbSecurityDescriptor; // size of security descriptor
|
||||
FILETIME ftLastWriteTime; // last write time
|
||||
|
||||
DWORD i, retCode;
|
||||
|
||||
TCHAR achValue[MAX_VALUE_NAME];
|
||||
TCHAR achValue[MAX_VALUE_NAME];
|
||||
DWORD cchValue = MAX_VALUE_NAME;
|
||||
|
||||
retCode = RegQueryInfoKey(
|
||||
hKey, // key handle
|
||||
achClass, // buffer for class name
|
||||
&cchClassName, // size of class string
|
||||
NULL, // reserved
|
||||
&cSubKeys, // number of subkeys
|
||||
&cbMaxSubKey, // longest subkey size
|
||||
&cchMaxClass, // longest class string
|
||||
&cValues, // number of values for this key
|
||||
&cchMaxValue, // longest value name
|
||||
&cbMaxValueData, // longest value data
|
||||
&cbSecurityDescriptor, // security descriptor
|
||||
&ftLastWriteTime); // last write time
|
||||
|
||||
hKey, // key handle
|
||||
achClass, // buffer for class name
|
||||
&cchClassName, // size of class string
|
||||
NULL, // reserved
|
||||
&cSubKeys, // number of subkeys
|
||||
&cbMaxSubKey, // longest subkey size
|
||||
&cchMaxClass, // longest class string
|
||||
&cValues, // number of values for this key
|
||||
&cchMaxValue, // longest value name
|
||||
&cbMaxValueData, // longest value data
|
||||
&cbSecurityDescriptor, // security descriptor
|
||||
&ftLastWriteTime); // last write time
|
||||
|
||||
for (i = 0, retCode = ERROR_SUCCESS; i < cValues; ++i) {
|
||||
cchValue = MAX_VALUE_NAME;
|
||||
achValue[0] = '\0';
|
||||
retCode = RegEnumValue(
|
||||
hKey,
|
||||
i,
|
||||
achValue,
|
||||
&cchValue,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
retCode = RegEnumValue(hKey, i, achValue, &cchValue, NULL, NULL, NULL, NULL);
|
||||
if (retCode == ERROR_SUCCESS) {
|
||||
values.push_back(achValue);
|
||||
}
|
||||
|
@ -254,22 +220,10 @@ std::pair<bool, std::string> WinDNSHelper::hasDNSConfig(uint64_t nwid)
|
|||
for (auto it2 = dnsRecords.begin(); it2 != dnsRecords.end(); ++it2) {
|
||||
if ((*it2) == "Comment") {
|
||||
HKEY hKey;
|
||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
||||
sub,
|
||||
0,
|
||||
KEY_READ,
|
||||
&hKey) == ERROR_SUCCESS) {
|
||||
|
||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, sub, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
|
||||
char buf[16384] = { 0 };
|
||||
DWORD size = sizeof(buf);
|
||||
DWORD retCode = RegGetValueA(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
sub,
|
||||
it2->c_str(),
|
||||
RRF_RT_REG_SZ,
|
||||
NULL,
|
||||
&buf,
|
||||
&size);
|
||||
DWORD retCode = RegGetValueA(HKEY_LOCAL_MACHINE, sub, it2->c_str(), RRF_RT_REG_SZ, NULL, &buf, &size);
|
||||
if (retCode == ERROR_SUCCESS) {
|
||||
if (std::string(networkStr) == std::string(buf)) {
|
||||
RegCloseKey(hKey);
|
||||
|
@ -277,11 +231,10 @@ std::pair<bool, std::string> WinDNSHelper::hasDNSConfig(uint64_t nwid)
|
|||
}
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
}
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -311,7 +264,8 @@ void WinDNSHelper::setDNS(uint64_t nwid, const char* domain, const std::vector<I
|
|||
fprintf(stderr, "Error writing dns servers: %d\n", retCode);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// add new config
|
||||
const char* baseKey = "SYSTEM\\CurrentControlSet\\Services\\Dnscache\\Parameters\\DnsPolicyConfig";
|
||||
GUID guid;
|
||||
|
@ -350,4 +304,4 @@ void WinDNSHelper::removeDNS(uint64_t nwid)
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace ZeroTier
|
|
@ -1,24 +1,22 @@
|
|||
#ifndef WIN_DNS_HELPER_H_
|
||||
#define WIN_DNS_HELPER_H_
|
||||
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include "../node/InetAddress.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace ZeroTier
|
||||
{
|
||||
namespace ZeroTier {
|
||||
|
||||
class WinDNSHelper
|
||||
{
|
||||
public:
|
||||
class WinDNSHelper {
|
||||
public:
|
||||
static void setDNS(uint64_t nwid, const char* domain, const std::vector<InetAddress>& servers);
|
||||
static void removeDNS(uint64_t nwid);
|
||||
|
||||
private:
|
||||
private:
|
||||
static std::pair<bool, std::string> hasDNSConfig(uint64_t nwid);
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
|
@ -1,10 +1,7 @@
|
|||
#include "WinFWHelper.hpp"
|
||||
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
||||
|
||||
void ZeroTier::WinFWHelper::newICMPRule(const InetAddress& ip, uint64_t nwid)
|
||||
{
|
||||
char nwString[32] = { 0 };
|
||||
|
@ -12,7 +9,7 @@ void ZeroTier::WinFWHelper::newICMPRule(const InetAddress& ip, uint64_t nwid)
|
|||
|
||||
sprintf(nwString, "%.16llx", nwid);
|
||||
std::string nwString2 = { nwString };
|
||||
|
||||
|
||||
ip.toString(ipbuf);
|
||||
|
||||
if (ip.isV4()) {
|
||||
|
@ -41,7 +38,6 @@ void ZeroTier::WinFWHelper::removeICMPRule(const InetAddress& ip, uint64_t nwid)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void WinFWHelper::newICMPv4Rule(std::string address, uint64_t nwid)
|
||||
{
|
||||
// allows icmp, scoped to a specific ip address and interface name
|
||||
|
@ -50,123 +46,112 @@ void WinFWHelper::newICMPv4Rule(std::string address, uint64_t nwid)
|
|||
sprintf(nwString, "%.16llx", nwid);
|
||||
std::string nwString2 = { nwString };
|
||||
|
||||
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "New-NetFirewallRule -DisplayName zerotier-icmpv4-)" + nwString2 + address +
|
||||
R"( -InterfaceAlias 'ZeroTier One `[)" + nwString2 + R"(`]')" +
|
||||
" -Protocol ICMPv4 -Action Allow" +
|
||||
" -LocalAddress " + address + "\"\r\n";
|
||||
|
||||
_run(cmd);
|
||||
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "New-NetFirewallRule -DisplayName zerotier-icmpv4-)" + nwString2 + address + R"( -InterfaceAlias 'ZeroTier One `[)" + nwString2 + R"(`]')"
|
||||
+ " -Protocol ICMPv4 -Action Allow" + " -LocalAddress " + address + "\"\r\n";
|
||||
|
||||
_run(cmd);
|
||||
}
|
||||
|
||||
void WinFWHelper::newICMPv6Rule(std::string address, uint64_t nwid)
|
||||
{
|
||||
// allows icmp, scoped to a specific ip address and interface name
|
||||
// allows icmp, scoped to a specific ip address and interface name
|
||||
|
||||
char nwString[32] = { 0 };
|
||||
sprintf(nwString, "%.16llx", nwid);
|
||||
std::string nwString2 = { nwString };
|
||||
char nwString[32] = { 0 };
|
||||
sprintf(nwString, "%.16llx", nwid);
|
||||
std::string nwString2 = { nwString };
|
||||
|
||||
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "New-NetFirewallRule -DisplayName zerotier-icmpv6-)" + nwString2 + address +
|
||||
R"( -InterfaceAlias 'ZeroTier One `[)" + nwString2 + R"(`]')" +
|
||||
" -Protocol ICMPv6 -Action Allow" +
|
||||
" -LocalAddress " + address + "\"\r\n";
|
||||
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "New-NetFirewallRule -DisplayName zerotier-icmpv6-)" + nwString2 + address + R"( -InterfaceAlias 'ZeroTier One `[)" + nwString2 + R"(`]')"
|
||||
+ " -Protocol ICMPv6 -Action Allow" + " -LocalAddress " + address + "\"\r\n";
|
||||
|
||||
_run(cmd);
|
||||
_run(cmd);
|
||||
}
|
||||
|
||||
void WinFWHelper::removeICMPv4Rule(std::string addr, uint64_t nwid)
|
||||
{
|
||||
// removes 1 icmp firewall rule
|
||||
// removes 1 icmp firewall rule
|
||||
|
||||
char nwString[32] = { 0 };
|
||||
sprintf(nwString, "%.16llx", nwid);
|
||||
std::string nwString2 = { nwString };
|
||||
char nwString[32] = { 0 };
|
||||
sprintf(nwString, "%.16llx", nwid);
|
||||
std::string nwString2 = { nwString };
|
||||
|
||||
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "Remove-NetFirewallRule -DisplayName zerotier-icmpv4-)" + nwString2 + addr +
|
||||
"\"\r\n";
|
||||
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "Remove-NetFirewallRule -DisplayName zerotier-icmpv4-)" + nwString2 + addr + "\"\r\n";
|
||||
|
||||
_run(cmd);
|
||||
_run(cmd);
|
||||
}
|
||||
|
||||
void WinFWHelper::removeICMPv6Rule(std::string addr, uint64_t nwid)
|
||||
{
|
||||
// removes 1 icmp firewall rule
|
||||
// removes 1 icmp firewall rule
|
||||
|
||||
char nwString[32] = { 0 };
|
||||
sprintf(nwString, "%.16llx", nwid);
|
||||
std::string nwString2 = { nwString };
|
||||
char nwString[32] = { 0 };
|
||||
sprintf(nwString, "%.16llx", nwid);
|
||||
std::string nwString2 = { nwString };
|
||||
|
||||
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "Remove-NetFirewallRule -DisplayName zerotier-icmpv6-)" + nwString2 + addr +
|
||||
"\"\r\n";
|
||||
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "Remove-NetFirewallRule -DisplayName zerotier-icmpv6-)" + nwString2 + addr + "\"\r\n";
|
||||
|
||||
_run(cmd);
|
||||
_run(cmd);
|
||||
}
|
||||
|
||||
void WinFWHelper::removeICMPv4Rules(uint64_t nwid)
|
||||
{
|
||||
// removes all icmp firewall rules for this network id
|
||||
// removes all icmp firewall rules for this network id
|
||||
|
||||
char nwString[32] = { 0 };
|
||||
sprintf(nwString, "%.16llx", nwid);
|
||||
std::string nwString2 = { nwString };
|
||||
char nwString[32] = { 0 };
|
||||
sprintf(nwString, "%.16llx", nwid);
|
||||
std::string nwString2 = { nwString };
|
||||
|
||||
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "Remove-NetFirewallRule -DisplayName zerotier-icmpv4-)" + nwString2 + "*\" \r\n";
|
||||
|
||||
_run(cmd);
|
||||
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "Remove-NetFirewallRule -DisplayName zerotier-icmpv4-)" + nwString2 + "*\" \r\n";
|
||||
|
||||
_run(cmd);
|
||||
}
|
||||
|
||||
void WinFWHelper::removeICMPv6Rules(uint64_t nwid)
|
||||
{
|
||||
// removes all icmp firewall rules for this network id
|
||||
// removes all icmp firewall rules for this network id
|
||||
|
||||
char nwString[32] = { 0 };
|
||||
sprintf(nwString, "%.16llx", nwid);
|
||||
std::string nwString2 = { nwString };
|
||||
char nwString[32] = { 0 };
|
||||
sprintf(nwString, "%.16llx", nwid);
|
||||
std::string nwString2 = { nwString };
|
||||
|
||||
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "Remove-NetFirewallRule -DisplayName zerotier-icmpv6-)" + nwString2 + "*\" \r\n";
|
||||
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "Remove-NetFirewallRule -DisplayName zerotier-icmpv6-)" + nwString2 + "*\" \r\n";
|
||||
|
||||
_run(cmd);
|
||||
_run(cmd);
|
||||
}
|
||||
|
||||
void WinFWHelper::removeICMPRules()
|
||||
{
|
||||
// removes all icmp firewall rules for all networks
|
||||
// removes all icmp firewall rules for all networks
|
||||
|
||||
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "Remove-NetFirewallRule -DisplayName zerotier-icmp*)" + std::string("\r\n");
|
||||
std::string cmd = R"(C:\Windows\System32\WindowsPowershell\v1.0\powershell.exe "Remove-NetFirewallRule -DisplayName zerotier-icmp*)" + std::string("\r\n");
|
||||
|
||||
_run(cmd);
|
||||
_run(cmd);
|
||||
}
|
||||
|
||||
void WinFWHelper::removeICMPRules(uint64_t nwid)
|
||||
{
|
||||
// removes all icmp firewall rules for this network
|
||||
WinFWHelper::removeICMPv4Rules(nwid);
|
||||
WinFWHelper::removeICMPv6Rules(nwid);
|
||||
// removes all icmp firewall rules for this network
|
||||
WinFWHelper::removeICMPv4Rules(nwid);
|
||||
WinFWHelper::removeICMPv6Rules(nwid);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void WinFWHelper::_run(std::string cmd)
|
||||
{
|
||||
|
||||
#ifdef ZT_DEBUG
|
||||
fprintf(stderr, cmd.c_str());
|
||||
#endif
|
||||
#ifdef ZT_DEBUG
|
||||
fprintf(stderr, cmd.c_str());
|
||||
#endif
|
||||
|
||||
STARTUPINFOA startupInfo;
|
||||
PROCESS_INFORMATION processInfo;
|
||||
startupInfo.cb = sizeof(startupInfo);
|
||||
memset(&startupInfo, 0, sizeof(STARTUPINFOA));
|
||||
memset(&processInfo, 0, sizeof(PROCESS_INFORMATION));
|
||||
STARTUPINFOA startupInfo;
|
||||
PROCESS_INFORMATION processInfo;
|
||||
startupInfo.cb = sizeof(startupInfo);
|
||||
memset(&startupInfo, 0, sizeof(STARTUPINFOA));
|
||||
memset(&processInfo, 0, sizeof(PROCESS_INFORMATION));
|
||||
|
||||
if (CreateProcessA(NULL, (LPSTR)cmd.c_str(), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &startupInfo, &processInfo)) {
|
||||
WaitForSingleObject(processInfo.hProcess, INFINITE);
|
||||
if (CreateProcessA(NULL, (LPSTR)cmd.c_str(), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &startupInfo, &processInfo)) {
|
||||
WaitForSingleObject(processInfo.hProcess, INFINITE);
|
||||
|
||||
CloseHandle(processInfo.hProcess);
|
||||
CloseHandle(processInfo.hThread);
|
||||
}
|
||||
CloseHandle(processInfo.hProcess);
|
||||
CloseHandle(processInfo.hThread);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace ZeroTier
|
|
@ -15,7 +15,6 @@ class WinFWHelper {
|
|||
static void removeICMPRules(uint64_t nwid);
|
||||
static void removeICMPRules();
|
||||
|
||||
|
||||
private:
|
||||
static void _run(std::string cmd);
|
||||
static void newICMPv4Rule(std::string address, uint64_t nwid);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -14,27 +14,24 @@
|
|||
#ifndef ZT_WINDOWSETHERNETTAP_HPP
|
||||
#define ZT_WINDOWSETHERNETTAP_HPP
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <ifdef.h>
|
||||
|
||||
#include <string>
|
||||
#include <queue>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/Mutex.hpp"
|
||||
#include "../node/MulticastGroup.hpp"
|
||||
#include "../node/InetAddress.hpp"
|
||||
#include "../node/MulticastGroup.hpp"
|
||||
#include "../node/Mutex.hpp"
|
||||
#include "../osdep/Thread.hpp"
|
||||
#include "EthernetTap.hpp"
|
||||
|
||||
#include <ifdef.h>
|
||||
#include <queue>
|
||||
#include <stdexcept>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class WindowsEthernetTap : public EthernetTap
|
||||
{
|
||||
public:
|
||||
class WindowsEthernetTap : public EthernetTap {
|
||||
public:
|
||||
/**
|
||||
* Installs a new instance of the ZT tap driver
|
||||
*
|
||||
|
@ -42,7 +39,7 @@ public:
|
|||
* @param deviceInstanceId Buffer to fill with device instance ID on success (and if SetupDiGetDeviceInstanceIdA succeeds, which it should)
|
||||
* @return Empty string on success, otherwise an error message
|
||||
*/
|
||||
static std::string addNewPersistentTapDevice(const char *pathToInf,std::string &deviceInstanceId);
|
||||
static std::string addNewPersistentTapDevice(const char* pathToInf, std::string& deviceInstanceId);
|
||||
|
||||
/**
|
||||
* Uninstalls all persistent tap devices that have legacy drivers
|
||||
|
@ -64,7 +61,7 @@ public:
|
|||
* @param instanceId Device instance ID
|
||||
* @return Empty string on success, otherwise an error message
|
||||
*/
|
||||
static std::string deletePersistentTapDevice(const char *instanceId);
|
||||
static std::string deletePersistentTapDevice(const char* instanceId);
|
||||
|
||||
/**
|
||||
* Disable a persistent tap device by instance ID
|
||||
|
@ -73,51 +70,62 @@ public:
|
|||
* @param enabled Enable device?
|
||||
* @return True if device was found and disabled
|
||||
*/
|
||||
static bool setPersistentTapDeviceState(const char *instanceId,bool enabled);
|
||||
static bool setPersistentTapDeviceState(const char* instanceId, bool enabled);
|
||||
|
||||
WindowsEthernetTap(
|
||||
const char *hp,
|
||||
const MAC &mac,
|
||||
const char* hp,
|
||||
const MAC& mac,
|
||||
unsigned int mtu,
|
||||
unsigned int metric,
|
||||
uint64_t nwid,
|
||||
const char *friendlyName,
|
||||
void (*handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
|
||||
void *arg);
|
||||
const char* friendlyName,
|
||||
void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
|
||||
void* arg);
|
||||
|
||||
virtual ~WindowsEthernetTap();
|
||||
|
||||
virtual void setEnabled(bool en);
|
||||
virtual bool enabled() const;
|
||||
virtual bool addIp(const InetAddress &ip);
|
||||
virtual bool removeIp(const InetAddress &ip);
|
||||
virtual bool addIp(const InetAddress& ip);
|
||||
virtual bool removeIp(const InetAddress& ip);
|
||||
virtual std::vector<InetAddress> ips() const;
|
||||
virtual void put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len);
|
||||
virtual void put(const MAC& from, const MAC& to, unsigned int etherType, const void* data, unsigned int len);
|
||||
virtual std::string deviceName() const;
|
||||
virtual void setFriendlyName(const char *friendlyName);
|
||||
virtual void setFriendlyName(const char* friendlyName);
|
||||
virtual std::string friendlyName() const;
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed);
|
||||
virtual void setMtu(unsigned int mtu);
|
||||
virtual void setDns(const char* domain, const std::vector<InetAddress> &servers);
|
||||
virtual void setDns(const char* domain, const std::vector<InetAddress>& servers);
|
||||
|
||||
inline const NET_LUID &luid() const { return _deviceLuid; }
|
||||
inline const GUID &guid() const { return _deviceGuid; }
|
||||
inline const std::string &instanceId() const { return _deviceInstanceId; }
|
||||
inline const NET_LUID& luid() const
|
||||
{
|
||||
return _deviceLuid;
|
||||
}
|
||||
inline const GUID& guid() const
|
||||
{
|
||||
return _deviceGuid;
|
||||
}
|
||||
inline const std::string& instanceId() const
|
||||
{
|
||||
return _deviceInstanceId;
|
||||
}
|
||||
NET_IFINDEX interfaceIndex() const;
|
||||
|
||||
void threadMain()
|
||||
throw();
|
||||
void threadMain() throw();
|
||||
|
||||
bool isInitialized() const { return _initialized; };
|
||||
bool isInitialized() const
|
||||
{
|
||||
return _initialized;
|
||||
};
|
||||
|
||||
private:
|
||||
NET_IFINDEX _getDeviceIndex(); // throws on failure
|
||||
std::vector<std::string> _getRegistryIPv4Value(const char *regKey);
|
||||
void _setRegistryIPv4Value(const char *regKey,const std::vector<std::string> &value);
|
||||
private:
|
||||
NET_IFINDEX _getDeviceIndex(); // throws on failure
|
||||
std::vector<std::string> _getRegistryIPv4Value(const char* regKey);
|
||||
void _setRegistryIPv4Value(const char* regKey, const std::vector<std::string>& value);
|
||||
void _syncIps();
|
||||
|
||||
void (*_handler)(void *,void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
|
||||
void *_arg;
|
||||
void (*_handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int);
|
||||
void* _arg;
|
||||
MAC _mac;
|
||||
uint64_t _nwid;
|
||||
volatile unsigned int _mtu;
|
||||
|
@ -134,13 +142,12 @@ private:
|
|||
std::string _friendlyName;
|
||||
Mutex _friendlyName_m;
|
||||
|
||||
std::vector<InetAddress> _assignedIps; // IPs assigned with addIp
|
||||
std::vector<InetAddress> _assignedIps; // IPs assigned with addIp
|
||||
Mutex _assignedIps_m;
|
||||
|
||||
std::vector<MulticastGroup> _multicastGroups;
|
||||
|
||||
struct _InjectPending
|
||||
{
|
||||
struct _InjectPending {
|
||||
unsigned int len;
|
||||
char data[ZT_MAX_MTU + 32];
|
||||
};
|
||||
|
@ -157,6 +164,6 @@ private:
|
|||
mutable uint64_t _lastIfAddrsUpdate;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue