summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--node/BSDRoutingTable.cpp41
-rw-r--r--node/BSDRoutingTable.hpp2
-rw-r--r--node/InetAddress.cpp30
-rw-r--r--node/InetAddress.hpp18
-rw-r--r--node/RoutingTable.cpp2
-rw-r--r--node/RoutingTable.hpp9
-rw-r--r--node/Utils.hpp26
7 files changed, 94 insertions, 34 deletions
diff --git a/node/BSDRoutingTable.cpp b/node/BSDRoutingTable.cpp
index d886b60f..d6b5c488 100644
--- a/node/BSDRoutingTable.cpp
+++ b/node/BSDRoutingTable.cpp
@@ -28,6 +28,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/sysctl.h>
@@ -35,7 +36,9 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/route.h>
+#include <net/if.h>
#include <net/if_dl.h>
+#include <ifaddrs.h>
#include <algorithm>
#include <utility>
@@ -55,7 +58,7 @@ BSDRoutingTable::~BSDRoutingTable()
{
}
-std::vector<RoutingTable::Entry> BSDRoutingTable::get() const
+std::vector<RoutingTable::Entry> BSDRoutingTable::get(bool includeLinkLocal,bool includeLoopback) const
{
std::vector<RoutingTable::Entry> entries;
int mib[6];
@@ -82,6 +85,7 @@ std::vector<RoutingTable::Entry> BSDRoutingTable::get() const
if (((rtm->rtm_flags & RTF_LLINFO) == 0)&&((rtm->rtm_flags & RTF_HOST) == 0)&&((rtm->rtm_flags & RTF_UP) != 0)&&((rtm->rtm_flags & RTF_MULTICAST) == 0)) {
RoutingTable::Entry e;
+ e.deviceIndex = -9999; // unset
int which = 0;
while (saptr < saend) {
@@ -120,7 +124,15 @@ std::vector<RoutingTable::Entry> BSDRoutingTable::get() const
break;
case 1:
//printf("RTA_GATEWAY\n");
- e.gateway.set(sa);
+ switch(sa->sa_family) {
+ case AF_LINK:
+ e.deviceIndex = (int)((const struct sockaddr_dl *)sa)->sdl_index;
+ break;
+ case AF_INET:
+ case AF_INET6:
+ e.gateway.set(sa);
+ break;
+ }
break;
case 2: {
if (e.destination.isV6()) {
@@ -148,6 +160,7 @@ std::vector<RoutingTable::Entry> BSDRoutingTable::get() const
}
//printf("RTA_NETMASK\n");
} break;
+ /*
case 3:
//printf("RTA_GENMASK\n");
break;
@@ -160,6 +173,7 @@ std::vector<RoutingTable::Entry> BSDRoutingTable::get() const
case 6:
//printf("RTA_AUTHOR\n");
break;
+ */
}
saptr += salen;
@@ -167,8 +181,8 @@ std::vector<RoutingTable::Entry> BSDRoutingTable::get() const
e.metric = (int)rtm->rtm_rmx.rmx_hopcount;
- entries.push_back(e);
- printf("%s\n",e.toString().c_str());
+ if (((includeLinkLocal)||(!e.destination.isLinkLocal()))&&((includeLoopback)||((!e.destination.isLoopback())&&(!e.gateway.isLoopback()))))
+ entries.push_back(e);
}
next = saend;
@@ -179,7 +193,24 @@ std::vector<RoutingTable::Entry> BSDRoutingTable::get() const
}
}
+ for(std::vector<ZeroTier::RoutingTable::Entry>::iterator e1(entries.begin());e1!=entries.end();++e1) {
+ if ((!e1->device[0])&&(e1->deviceIndex >= 0))
+ if_indextoname(e1->deviceIndex,e1->device);
+ }
+ for(std::vector<ZeroTier::RoutingTable::Entry>::iterator e1(entries.begin());e1!=entries.end();++e1) {
+ if ((!e1->device[0])&&(e1->gateway)) {
+ int bestMetric = 9999999;
+ for(std::vector<ZeroTier::RoutingTable::Entry>::iterator e2(entries.begin());e2!=entries.end();++e2) {
+ if ((e1->gateway.within(e2->destination))&&(e2->metric <= bestMetric)) {
+ bestMetric = e2->metric;
+ Utils::scopy(e1->device,sizeof(e1->device),e2->device);
+ }
+ }
+ }
+ }
+
std::sort(entries.begin(),entries.end());
+
return entries;
}
@@ -196,6 +227,8 @@ int main(int argc,char **argv)
{
ZeroTier::BSDRoutingTable rt;
std::vector<ZeroTier::RoutingTable::Entry> ents(rt.get());
+ for(std::vector<ZeroTier::RoutingTable::Entry>::iterator e(ents.begin());e!=ents.end();++e)
+ printf("%s\n",e->toString().c_str());
return 0;
}
//*/
diff --git a/node/BSDRoutingTable.hpp b/node/BSDRoutingTable.hpp
index 8947bdde..7c4c9dcb 100644
--- a/node/BSDRoutingTable.hpp
+++ b/node/BSDRoutingTable.hpp
@@ -42,7 +42,7 @@ class BSDRoutingTable : public RoutingTable
public:
BSDRoutingTable();
virtual ~BSDRoutingTable();
- virtual std::vector<RoutingTable::Entry> get() const;
+ virtual std::vector<RoutingTable::Entry> get(bool includeLinkLocal = false,bool includeLoopback = false) const;
virtual bool set(const RoutingTable::Entry &re);
};
diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp
index 706d804a..9ff5acea 100644
--- a/node/InetAddress.cpp
+++ b/node/InetAddress.cpp
@@ -215,6 +215,36 @@ bool InetAddress::sameNetworkAs(const InetAddress &ipnet) const
return ((*a >> bits) == (*b >> bits));
}
+bool InetAddress::within(const InetAddress &ipnet) const
+ throw()
+{
+ if (_sa.saddr.sa_family != ipnet._sa.saddr.sa_family)
+ return false;
+
+ unsigned int bits = ipnet.netmaskBits();
+ switch(_sa.saddr.sa_family) {
+ case AF_INET:
+ if (bits > 32) return false;
+ break;
+ case AF_INET6:
+ if (bits > 128) return false;
+ break;
+ default: return false;
+ }
+
+ const uint8_t *a = (const uint8_t *)rawIpData();
+ const uint8_t *b = (const uint8_t *)ipnet.rawIpData();
+ while (bits >= 8) {
+ if (*(a++) != *(b++))
+ return false;
+ bits -= 8;
+ }
+ if (bits) {
+ uint8_t mask = ((0xff << (8 - bits)) & 0xff);
+ return ((*a & mask) == (*b & mask));
+ } else return true;
+}
+
bool InetAddress::operator==(const InetAddress &a) const
throw()
{
diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp
index 325c2de4..74e42670 100644
--- a/node/InetAddress.hpp
+++ b/node/InetAddress.hpp
@@ -148,6 +148,15 @@ public:
throw();
/**
+ * @return True if this is a loopback address
+ */
+ inline bool isLoopback() const
+ throw()
+ {
+ return ((*this == LO4)||(*this == LO6));
+ }
+
+ /**
* @return ASCII IP/port format representation
*/
std::string toString() const;
@@ -287,6 +296,15 @@ public:
throw();
/**
+ * Determine whether this address is within an ip/netmask
+ *
+ * @param ipnet IP/netmask
+ * @return True if this address is within this network
+ */
+ bool within(const InetAddress &ipnet) const
+ throw();
+
+ /**
* Set to null/zero
*/
inline void zero() throw() { memset(&_sa,0,sizeof(_sa)); }
diff --git a/node/RoutingTable.cpp b/node/RoutingTable.cpp
index 1f4c5327..9534b321 100644
--- a/node/RoutingTable.cpp
+++ b/node/RoutingTable.cpp
@@ -39,7 +39,7 @@ namespace ZeroTier {
std::string RoutingTable::Entry::toString() const
{
char tmp[1024];
- Utils::snprintf(tmp,sizeof(tmp),"%s %s %s %d",destination.toString().c_str(),((gateway) ? gateway.toIpString().c_str() : "(link)"),device,metric);
+ Utils::snprintf(tmp,sizeof(tmp),"%s %s %s %d",destination.toString().c_str(),((gateway) ? gateway.toIpString().c_str() : "<link>"),device,metric);
return std::string(tmp);
}
diff --git a/node/RoutingTable.hpp b/node/RoutingTable.hpp
index 8894018d..3a4a3dde 100644
--- a/node/RoutingTable.hpp
+++ b/node/RoutingTable.hpp
@@ -50,7 +50,8 @@ public:
InetAddress destination;
InetAddress gateway; // port/netmaskBits field not used, should be 0 -- null if direct-to-device route
char device[128];
- int metric;
+ int deviceIndex; // may not always be set, depending on OS -- for internal use only
+ int metric; // higher = lower priority -- on some OSes this is "hop count," etc.
std::string toString() const;
@@ -66,9 +67,13 @@ public:
virtual ~RoutingTable();
/**
+ * Get routing table
+ *
+ * @param includeLinkLocal If true, include link-local address routes (default: false)
+ * @param includeLoopback Include loopback (default: false)
* @return Sorted routing table entries
*/
- virtual std::vector<Entry> get() const = 0;
+ virtual std::vector<Entry> get(bool includeLinkLocal = false,bool includeLoopback = false) const = 0;
/**
* Add or update a routing table entry
diff --git a/node/Utils.hpp b/node/Utils.hpp
index 82837286..4298d045 100644
--- a/node/Utils.hpp
+++ b/node/Utils.hpp
@@ -493,32 +493,6 @@ public:
}
/**
- * Match two strings with bits masked netmask-style
- *
- * @param a First string
- * @param abits Number of bits in first string
- * @param b Second string
- * @param bbits Number of bits in second string
- * @return True if min(abits,bbits) match between a and b
- */
- static inline bool matchNetmask(const void *a,unsigned int abits,const void *b,unsigned int bbits)
- throw()
- {
- const unsigned char *aptr = (const unsigned char *)a;
- const unsigned char *bptr = (const unsigned char *)b;
-
- while ((abits >= 8)&&(bbits >= 8)) {
- if (*aptr++ != *bptr++)
- return false;
- abits -= 8;
- bbits -= 8;
- }
-
- unsigned char mask = 0xff << (8 - ((abits > bbits) ? bbits : abits));
- return ((*aptr & mask) == (*aptr & mask));
- }
-
- /**
* Compute SDBM hash of a binary string
*
* See: http://www.cse.yorku.ca/~oz/hash.html