Compare commits

...
9 Commits
Author SHA1 Message Date
Adam Ierymenko 7f3dea018c Version 0.2.1 - no incompatible protocol changes, a few bug fixes and the new status file feature 2013-07-06 15:09:59 -04:00
Adam Ierymenko 7c85a638b0 Added creation and periodic update of a file called "status" in the home directory that contains peer link status. Useful for debugging and statistics. Send it SIGHUP to force an update now. Otherwise it updates every 120 seconds. 2013-07-06 14:58:34 -04:00
Adam Ierymenko 68cc5ea523 documentation 2013-07-06 14:11:38 -04:00
Adam Ierymenko 2c0cdc9484 Fix for failure to bind port if IPv6 is not enabled on a system -- it should succeed if it can bind either V4 or V6 or both and only fail if neither binds 2013-07-06 13:43:24 -04:00
Adam Ierymenko cfef114c31 Possible fix for issue #4 - segfault in ___removeIp helper function in EthernetTap on OSX -- I think the problem may have been that I was using set::erase(key) while also using an iterator, so now it uses erase(iterator). See if it happens again, cause I could not duplicate the issue. Possible minor difference in STL version. 2013-07-06 13:34:35 -04:00
Adam Ierymenko 118247e8b5 Merge pull request #3 from bhourigan/master
Minor documentation edit
2013-07-06 02:17:22 -07:00
bhourigan a18162d58b Updated make install-mac-tap for paste worthy correctness 2013-07-05 21:50:14 -07:00
Adam Ierymenko 7640801952 Merge pull request #1 from crazysim/patch-1
Update README.md
2013-07-05 15:09:20 -07:00
Nelson Chen 0b46f2869a Update README.md
s/dslreports/dslreports.com/
2013-07-05 14:30:02 -07:00
16 changed files with 182 additions and 96 deletions

No files matched your search

+2 -2
View File
@@ -1,6 +1,6 @@
This file will track authors and contributors to ZeroTier's code base.
People who contribute code that is accepted into the master (trunk) branch
will be credited here.
People who contribute new code or bug fixes that are accepted into
the master (trunk) branch will be credited here.
--
+4
View File
@@ -2,6 +2,10 @@ Building ZeroTier One on different platforms:
(See RUNNING.txt for what to do next.)
Developers note: there is currently no management of dependencies on *nix
platforms, so you should make clean ; make if you change a header. Will
do this eventually.
-- MacOS
make -f Makefile.mac
+18 -10
View File
@@ -5,7 +5,7 @@ ZeroTier One creates flat virtual Ethernet networks of almost unlimited size. [V
This code is presently in **ALPHA** testing. That means that the protocol spec may change in incompatible ways, and it certainly has bugs. Testers should "git pull," rebuild, and restart fairly often. If things mysteriously stop working, do that.
See BUILDING.txt and RUNNING.txt for instructions. It currently builds on Mac and Linux. A Windows port is coming soon. Nice packages/installers and auto-update is also coming when alpha transitions to beta.
See BUILDING.txt and RUNNING.txt for instructions. It currently builds on Mac and Linux. A Windows port is coming soon. Nice packages/installers and auto-update are also coming when alpha transitions to beta.
Note that this won't work if your firewall does not allow outbound UDP. It must allow UDP conversations on port 8993 at a minimum.
@@ -13,7 +13,7 @@ At present there is only one virtual LAN and you are dumped there by default. It
**Security warning:** You read that right. ZeroTier One places your computer on an absolutely open global Ethernet party line. Please ensure that you are up to date on your OS patches and we recommend turning off unnecessary services. Also be sure that anything else you are sharing is password protected provided you don't want to share it: printers, iPhoto and iTunes shares, etc.
ZeroTier One is licensed under the GNU General Public License version 3. Anyone wishing to embed this in a commercial product or create a derivative product should contact [ZeroTier Networks LLC](https://www.zerotier.com/) to obtain a commercial license.
ZeroTier One is licensed under the GNU General Public License version 3. You are free to use, modify, or redistribute it under the terms of that license. If you would like to embed ZeroTier One in a closed source product or create a closed source derivative product, contact ZeroTier Networks LLC.
Check out the [blog](http://blog.zerotier.com/) for announcements, in-depth articles, and related thoughts. There is also a [Google group](https://groups.google.com/forum/#!forum/zerotier-one-users) for questions and discussion.
@@ -21,16 +21,19 @@ Check out the [blog](http://blog.zerotier.com/) for announcements, in-depth arti
**FAQ**
**Q:** What can I do with this?
**A:** For starters, try opening iTunes if you have it installed. If others are also online and sharing their collections, you might see them. If you have any games that run over a LAN (except those that require IPX), try those. What else can you think of to do on a completely flat, open network? Collaborative software development? Remote debugging? Transferring files using simple drive shares? Sharing your desktop printer to someone on another continent? Use your imagination.
**A:** For starters, try opening iTunes if you have it installed. If others are also online and sharing their collections, you might see them. If you have any games that run over a LAN (except those that require IPX), try those. What else can you think of to do on a completely flat, open network? Games? Collaborative software development? Remote debugging? Transferring files using simple drive shares? Sharing your desktop printer to someone on another continent? Use your imagination.
**Q:** Why do I get an IP address in the 27.0.0.0 or 28.0.0.0 range? And why does a lookup claim these addresses belong to the U.S. Department of Defense?
**A:** Short answer: because IPv4 needs to die. Long answer: the Earth network assigns IPv4 IPs from these ranges. They do in fact belong to the DOD, but they are *not* routed to the open Internet. The DOD owns them but uses them internally for private networks. As a result, there is nothing *technically* wrong with "bogarting" these for our own private network. It's considered bad practice, but if you want a private address space in IPv4 that is unlikely to overlap other private address spaces (like 10/8 and 192.168/16), it's the only way. [Cellular carriers](http://www.androidcentral.com/sprint-internet-dept-defense-and-you) and [cable companies](http://www.dslreports/forum/r25679029-Why-is-my-first-hop-to-a-DoD-assigned-IP-address-) frequently do the same thing.
**A:** Short answer: because IPv4 needs to die. Long answer: the Earth network assigns IPv4 IPs from these ranges. They do in fact belong to the DOD, but they are *not* routed to the open Internet. The DOD owns them but uses them internally for private networks. As a result, there is nothing *technically* wrong with "bogarting" these for our own private network. It's considered bad practice, but if you want a private address space in IPv4 that is unlikely to overlap other private address spaces (like 10/8 and 192.168/16), it's the only way. [Cellular carriers](http://www.androidcentral.com/sprint-internet-dept-defense-and-you) and [cable companies](http://www.dslreports.com/forum/r25679029-Why-is-my-first-hop-to-a-DoD-assigned-IP-address-) frequently do the same thing.
**Q:** Is IPv6 supported?
**A:** Yes. IPv6 link-local addresses (those in the fe80::/10 block) are auto-assigned and should work fine. No other IPv6 addresses are assigned *yet*, but there are plans to do interesting things in this area in the future.
**Q:** I don't want a giant Ethernet party line. Can I leave it and create private LANs instead?
**A:** Yes, soon. A GUI to configure such things is in development. But for now there's only Earth.
**Q:** Are you going to charge for this?
**A:** Public networks will remain free, but we intend to charge for private virtual LANs. ZeroTier has other ideas too, but they're top secret for the moment.
**A:** Public virtual LANs will remain free. We intend to charge for private networks in some way, but the exact model is TBD. Other cloud-supported paid features are also TBD.
**Q:** What's a supernode?
**A:** Supernodes are nodes run by ZeroTier Networks that orindary users use to find one another and communicate until/unless they can perform NAT traversal and connect directly. They run the exact same software as everyone else. The only thing that really makes a supernode special is that it's designated as such.
@@ -38,14 +41,20 @@ Check out the [blog](http://blog.zerotier.com/) for announcements, in-depth arti
**Q:** Can I run a supernode?
**A:** No, not at the moment, and there would be no benefit to doing so.
**Q:** Will my local firewall rules apply to ZeroTier One traffic?
**A:** ZeroTier creates a virtual Ethernet tap device (zt# on Mac and Linux) that emulates a wired Ethernet port. If your firewall applies to *all* network ports, it will filter traffic through this port as well. If it applies only to the primary interface, it may not. See your OS's firewall documentation, as different OSes and flavors thereof have slightly different configurations in this regard.
**Q:** Can you see my traffic? What about other users? Can you sniff the LAN?
**A:** No. All unicast (direct computer to computer) traffic is encrypted end-to-end (even if it's being relayed), and the ZeroTier virtual LAN behaves like a LAN with a secure enterprise-grade switch that does not allow unicast conversations to be sniffed. Multicast and broadcast traffic will of course be seen by many recipients, but that's the idea.
**Q:** You say "almost unlimited size." Isn't multicast and broadcast traffic eventually going to be too much? What happens then?
**A:** ZeroTier One uses an algorithm called *implicit social switching*. The overall maximum number of recipients for a multicast is limited, so if there are too many listeners to a given multicast address then obviously not everyone will receive every message. So who does? Social switching causes multicasts to propagate in the direction of peers to whom you have recently communicated. As a result, multicasts tend to propagate along lines of association. The people most likely to get your service announcements are those with whom you frequently connect.
**Q:** I don't see broadcasts.
**A:** At the moment only Ethernet multicast is propagated, not broadcast (ff:ff:ff:ff:ff:ff). This may change in the future. IPv4 ARP uses broadcast but is handled by special code that subscribes to a multicast group using the broadcast address combined with the IPv4 address to make it address-specific. See comments in MulticastGroup.hpp for deeper technical details.
**Q:** Is this designed to replace IP, BGP, IPv6, routers, etc.?
**A:** No. Its purpose is to act as a collaboration tool, a VPN alternative, a network mobility tool, a testbed for the development of software that takes advantage of fully open networking, a virtual LAN party for gamers, and so on, but it's not intended (or able) to replace the core of the Internet.
**Q:** Can I bridge this to a physical port and plug in an Xbox, PlayStation, etc.?
**A:** Not currently, as foreign Ethernet frames are not forwarded. This may be possible in a future version.
----
**Status**
@@ -62,9 +71,8 @@ Check out the [blog](http://blog.zerotier.com/) for announcements, in-depth arti
* Changes in your local network configuration are generally detected and will cause peers to be re-acquired.
*Known immediate issues:*
* Multiple network support is in but there is no interface to configure it, hence it is useless. But in alpha it'll be nice to shove everyone onto "Earth" in order to stress test that little "almost unlimited size" boast. LAN party!
* Multiple networks would currently all have the same MAC, which some OSes may not like. There is a possible strategy for dealing with this, but it needs to be explored.
* There is no multiple-launch protection yet. If you launch more than one instance on the same working directory everything breaks. Take care that zerotier-one is not running before launching it again. The command "sudo killall zerotier-one" is helpful.
* Multiple network support is in but there is no interface to configure it, hence it is useless. But in alpha it'll be nice to shove everyone onto "Earth" in order to stress test that little "almost unlimited size" boast.
* There is no multiple-launch protection yet and multiple instances on the same system do not work well due to route conflicts. Take care that zerotier-one is not running before launching it again. The command "sudo killall zerotier-one" is helpful.
* Sometimes ZeroTier One doesn't like to terminate when asked nicely. This is related to issues with the tap device closing down properly. If it hangs around after a TERM signal, send it a KILL (9) signal.
* The locally bound UDP port isn't configurable yet. It's 8993 by default.
* Known security issues:
+1 -1
View File
@@ -9,7 +9,7 @@ By convention, ZeroTier One will keep its state here on mac:
ZeroTier ships with a kernel extension for its own tap device, which it
stores in the above directory. To install this from source, type:
sudo make install-mac-tap
sudo make -f Makefile.mac install-mac-tap
This will create the ZeroTier One home above if it does not exist and install
the kext there. Note that the kext must be owned by root:wheel. The make
-32
View File
@@ -1,32 +0,0 @@
#!/bin/bash
#
# This probably won't be useful to anyone outside ZeroTier itself.
#
#
# This bumps the revision in version.h, which triggers a build and deploy
# to the now/ subfolder on update.zerotier.com. This allows nodes tracking
# the bleeding edge to track the bleedingest of the bleeding edge.
#
cur_rev=`grep -F ZEROTIER_ONE_VERSION_REVISION version.h | cut -d ' ' -f 3`
next_rev=`expr $cur_rev + 1`
echo Current revision: $cur_rev
echo Next revision: $next_rev
rm -f version.h.new
cat version.h | sed "s/ZEROTIER_ONE_VERSION_REVISION $cur_rev/ZEROTIER_ONE_VERSION_REVISION $next_rev/g" >>version.h.new
new_cur_rev=`grep -F ZEROTIER_ONE_VERSION_REVISION version.h.new | cut -d ' ' -f 3`
if [ "$new_cur_rev" = "$next_rev" ]; then
mv -f version.h.new version.h
echo Done.
else
echo Error: version.h.new updated incorrectly, leaving in place.
exit 1
fi
exit 0
+7 -1
View File
@@ -70,12 +70,18 @@ static void sighandlerQuit(int sig)
static void sighandlerUsr(int sig)
{
}
static void sighandlerHup(int sig)
{
Node *n = node;
if (n)
n->updateStatusNow();
}
#endif
int main(int argc,char **argv)
{
#ifndef _WIN32
signal(SIGHUP,SIG_IGN);
signal(SIGHUP,&sighandlerHup);
signal(SIGPIPE,SIG_IGN);
signal(SIGUSR1,&sighandlerUsr);
signal(SIGUSR2,&sighandlerUsr);
+5
View File
@@ -253,6 +253,11 @@ error_no_ZT_ARCH
*/
#define ZT_AUTOCONFIGURE_CHECK_DELAY 15000
/**
* Delay between updates of status file in home directory
*/
#define ZT_STATUS_OUTPUT_PERIOD 120000
/**
* Minimum delay in Node service loop
*
+6 -8
View File
@@ -93,9 +93,9 @@ bool Demarc::bindLocalUdp(unsigned int localPort)
uint64_t v4p = ((uint64_t)PORT_TYPE_UDP_SOCKET_V4 << 60) | (uint64_t)localPort;
uint64_t v6p = ((uint64_t)PORT_TYPE_UDP_SOCKET_V6 << 60) | (uint64_t)localPort;
if ((_ports.count((Port)v4p))||(_ports.count((Port)v6p)))
return true;
return true; // port already bound
UdpSocket *v4;
UdpSocket *v4 = (UdpSocket *)0;
try {
DemarcPortObj *v4r = &(_ports[(Port)v4p]);
v4r->port = (Port)v4p;
@@ -104,10 +104,10 @@ bool Demarc::bindLocalUdp(unsigned int localPort)
v4r->type = PORT_TYPE_UDP_SOCKET_V4;
} catch ( ... ) {
_ports.erase((Port)v4p);
return false;
v4 = (UdpSocket *)0;
}
UdpSocket *v6;
UdpSocket *v6 = (UdpSocket *)0;
try {
DemarcPortObj *v6r = &(_ports[(Port)v6p]);
v6r->port = (Port)v6p;
@@ -115,13 +115,11 @@ bool Demarc::bindLocalUdp(unsigned int localPort)
v6r->obj = v6 = new UdpSocket(localPort,true,&Demarc::_CBudpSocketPacketHandler,v6r);
v6r->type = PORT_TYPE_UDP_SOCKET_V6;
} catch ( ... ) {
delete v4;
_ports.erase((Port)v4p);
_ports.erase((Port)v6p);
return false;
v6 = (UdpSocket *)0;
}
return true;
return ((v4)||(v6));
}
Demarc::Port Demarc::pick(const InetAddress &to) const
+18 -11
View File
@@ -478,7 +478,8 @@ EthernetTap::~EthernetTap()
delete [] _putBuf;
}
static bool ___removeIp(const char *_dev,std::set<InetAddress> &_ips,const InetAddress &ip)
// Helper function to actually remove IP from network device, execs ifconfig
static bool ___removeIp(const char *_dev,const InetAddress &ip)
{
int cpid;
if ((cpid = (int)fork()) == 0) {
@@ -487,11 +488,9 @@ static bool ___removeIp(const char *_dev,std::set<InetAddress> &_ips,const InetA
} else {
int exitcode = -1;
waitpid(cpid,&exitcode,0);
if (exitcode == 0) {
_ips.erase(ip);
return true;
} else return false;
return (exitcode == 0);
}
return false; // never reached, make compiler shut up about return value
}
bool EthernetTap::addIP(const InetAddress &ip)
@@ -501,13 +500,17 @@ bool EthernetTap::addIP(const InetAddress &ip)
if (!ip)
return false;
if (_ips.count(ip) > 0)
return true;
return true; // IP/netmask already assigned
// Remove and reconfigure if address is the same but netmask is different
for(std::set<InetAddress>::iterator i(_ips.begin());i!=_ips.end();++i) {
if (i->ipsEqual(ip)) {
___removeIp(_dev,_ips,*i);
break;
if ((i->ipsEqual(ip))&&(i->netmaskBits() != ip.netmaskBits())) {
if (___removeIp(_dev,*i)) {
_ips.erase(i);
break;
} else {
LOG("WARNING: failed to remove old IP/netmask %s to replace with %s",i->toString().c_str(),ip.toString().c_str());
}
}
}
@@ -530,8 +533,12 @@ bool EthernetTap::addIP(const InetAddress &ip)
bool EthernetTap::removeIP(const InetAddress &ip)
{
Mutex::Lock _l(_ips_m);
if (_ips.count(ip) > 0)
return ___removeIp(_dev,_ips,ip);
if (_ips.count(ip) > 0) {
if (___removeIp(_dev,ip)) {
_ips.erase(ip);
return true;
}
}
return false;
}
+1 -1
View File
@@ -36,7 +36,7 @@
namespace ZeroTier {
/**
* A multicast group composed of a multicast MAC and a 64-bit ADI field
* A multicast group composed of a multicast MAC and a 32-bit ADI field
*
* ADI stands for additional distinguishing information. ADI is primarily for
* adding additional information to broadcast (ff:ff:ff:ff:ff:ff) memberships,
+27 -14
View File
@@ -74,8 +74,9 @@ struct _NodeImpl
RuntimeEnvironment renv;
std::string reasonForTerminationStr;
Node::ReasonForTermination reasonForTermination;
bool started;
bool running;
volatile bool started;
volatile bool running;
volatile bool updateStatusNow;
volatile bool terminateNow;
// Helper used to rapidly terminate from run()
@@ -104,6 +105,7 @@ Node::Node(const char *hp,const char *urlPrefix,const char *configAuthorityIdent
impl->reasonForTermination = Node::NODE_RUNNING;
impl->started = false;
impl->running = false;
impl->updateStatusNow = false;
impl->terminateNow = false;
}
@@ -236,6 +238,8 @@ Node::ReasonForTermination Node::run()
}
try {
std::string statusPath(_r->homePath + ZT_PATH_SEPARATOR_S + "status");
uint64_t lastPingCheck = 0;
uint64_t lastTopologyClean = Utils::now(); // don't need to do this immediately
uint64_t lastNetworkFingerprintCheck = 0;
@@ -243,6 +247,7 @@ Node::ReasonForTermination Node::run()
uint64_t networkConfigurationFingerprint = _r->sysEnv->getNetworkConfigurationFingerprint();
uint64_t lastMulticastCheck = 0;
uint64_t lastMulticastAnnounceAll = 0;
uint64_t lastStatusUpdate = 0;
long lastDelayDelta = 0;
LOG("%s starting version %s",_r->identity.address().toString().c_str(),versionString());
@@ -373,6 +378,20 @@ Node::ReasonForTermination Node::run()
_r->topology->clean(); // happens in background
}
if (((now - lastStatusUpdate) >= ZT_STATUS_OUTPUT_PERIOD)||(impl->updateStatusNow)) {
lastStatusUpdate = now;
impl->updateStatusNow = false;
FILE *statusf = ::fopen(statusPath.c_str(),"w");
if (statusf) {
try {
_r->topology->eachPeer(Topology::DumpPeerStatistics(statusf));
} catch ( ... ) {
TRACE("unexpected exception updating status dump");
}
::fclose(statusf);
}
}
try {
unsigned long delay = std::min((unsigned long)ZT_MIN_SERVICE_LOOP_INTERVAL,_r->sw->doTimerTasks());
uint64_t start = Utils::now();
@@ -391,11 +410,6 @@ Node::ReasonForTermination Node::run()
return impl->terminateBecause(Node::NODE_NORMAL_TERMINATION,"normal termination");
}
/**
* Obtain a human-readable reason for node termination
*
* @return Reason for node termination or NULL if run() has not returned
*/
const char *Node::reasonForTermination() const
throw()
{
@@ -404,19 +418,18 @@ const char *Node::reasonForTermination() const
return ((_NodeImpl *)_impl)->reasonForTerminationStr.c_str();
}
/**
* Cause run() to return with NODE_NORMAL_TERMINATION
*
* This can be called from a signal handler or another thread to signal a
* running node to shut down. Shutdown may take a few seconds, so run()
* may not return instantly. Multiple calls are ignored.
*/
void Node::terminate()
throw()
{
((_NodeImpl *)_impl)->terminateNow = true;
}
void Node::updateStatusNow()
throw()
{
((_NodeImpl *)_impl)->updateStatusNow = true;
}
class _VersionStringMaker
{
public:
+6
View File
@@ -98,6 +98,12 @@ public:
void terminate()
throw();
/**
* Update the status file in the home directory on next service loop
*/
void updateStatusNow()
throw();
/**
* Get the ZeroTier version in major.minor.revision string format
*
+15 -15
View File
@@ -333,40 +333,40 @@ public:
VERB_NOP = 0,
/* Announcement of a node's existence:
* <[1] protocol version>
* <[1] protocol version>
* <[1] software major version>
* <[1] software minor version>
* <[2] software revision>
* <[8] timestamp (ms since epoch)>
* <[...] binary serialized identity (see Identity)>
* <[8] timestamp (ms since epoch)>
* <[...] binary serialized identity (see Identity)>
*
* OK payload:
* <[8] timestamp (echoed from original HELLO)>
* <[8] timestamp (echoed from original HELLO)>
*
* ERROR has no payload.
*/
VERB_HELLO = 1,
/* Error response:
* <[1] in-re verb>
* <[8] in-re packet ID>
* <[1] error code>
* <[...] error-dependent payload>
* <[1] in-re verb>
* <[8] in-re packet ID>
* <[1] error code>
* <[...] error-dependent payload>
*/
VERB_ERROR = 2,
/* Success response:
* <[1] in-re verb>
* <[8] in-re packet ID>
* <[...] request-specific payload>
* <[1] in-re verb>
* <[8] in-re packet ID>
* <[...] request-specific payload>
*/
VERB_OK = 3,
/* Query an identity by address:
* <[5] address to look up>
* <[5] address to look up>
*
* OK response payload:
* <[...] binary serialized identity>
* <[...] binary serialized identity>
*
* Error payload will be address queried.
*/
@@ -400,8 +400,8 @@ public:
/* A ZT-to-ZT unicast ethernet frame:
* <[8] 64-bit network ID>
* <[2] 16-bit ethertype>
* <[...] ethernet payload>
* <[2] 16-bit ethertype>
* <[...] ethernet payload>
*
* MAC addresses are derived from the packet's source and destination
* ZeroTier addresses. ZeroTier does not support VLANs or other extensions
+40
View File
@@ -232,6 +232,46 @@ public:
return ((_ipv4p.isActive(now))||(_ipv6p.isActive(now)));
}
/**
* @return IPv4 direct address or null InetAddress if none
*/
inline InetAddress ipv4Path() const
throw()
{
return _ipv4p.addr;
}
/**
* @return IPv6 direct address or null InetAddress if none
*/
inline InetAddress ipv6Path() const
throw()
{
return _ipv4p.addr;
}
/**
* @return IPv4 direct address or null InetAddress if none
*/
inline InetAddress ipv4ActivePath(uint64_t now) const
throw()
{
if (_ipv4p.isActive(now))
return _ipv4p.addr;
return InetAddress();
}
/**
* @return IPv6 direct address or null InetAddress if none
*/
inline InetAddress ipv6ActivePath(uint64_t now) const
throw()
{
if (_ipv6p.isActive(now))
return _ipv6p.addr;
return InetAddress();
}
/**
* @return 256-bit encryption key
*/
+31
View File
@@ -28,6 +28,8 @@
#ifndef _ZT_TOPOLOGY_HPP
#define _ZT_TOPOLOGY_HPP
#include <stdio.h>
#include <string.h>
#include <map>
#include <set>
#include <list>
@@ -292,6 +294,35 @@ public:
std::vector< SharedPtr<Peer> > &_v;
};
/**
* Dump peer I/O statistics to an open FILE (for status reporting and debug)
*/
class DumpPeerStatistics
{
public:
DumpPeerStatistics(FILE *out) :
_out(out),
_now(Utils::now())
{
fprintf(_out,"Peer Direct IPv4 Direct IPv6 Latency(ms)"ZT_EOL_S);
}
inline void operator()(Topology &t,const SharedPtr<Peer> &p)
{
InetAddress v4(p->ipv4ActivePath(_now));
InetAddress v6(p->ipv6ActivePath(_now));
fprintf(_out,"%-10s %-21s %-51s %u"ZT_EOL_S,
p->address().toString().c_str(),
((v4) ? v4.toString().c_str() : "(none)"),
((v6) ? v6.toString().c_str() : "(none)"),
p->latency());
}
private:
FILE *_out;
uint64_t _now;
};
protected:
virtual void main()
throw();
+1 -1
View File
@@ -41,6 +41,6 @@
/**
* Revision: 16-bit (0-65535)
*/
#define ZEROTIER_ONE_VERSION_REVISION 0
#define ZEROTIER_ONE_VERSION_REVISION 1
#endif