Clean up zerotier.h to by proxy clean up Rust bindings, and implement inetaddress in Rust.

This commit is contained in:
Adam Ierymenko 2021-01-01 22:24:53 -05:00
parent ce40a1df8a
commit 07b99a982d
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
19 changed files with 598 additions and 194 deletions

View file

@ -100,7 +100,7 @@ enum ZT_ResultCode ZT_Node_processWirePacket(
void *tptr, void *tptr,
int64_t now, int64_t now,
int64_t localSocket, int64_t localSocket,
const struct sockaddr_storage *remoteAddress, const ZT_InetAddress *remoteAddress,
const void *packetData, const void *packetData,
unsigned int packetLength, unsigned int packetLength,
int isZtBuffer, int isZtBuffer,
@ -108,7 +108,7 @@ enum ZT_ResultCode ZT_Node_processWirePacket(
{ {
try { try {
ZeroTier::SharedPtr< ZeroTier::Buf > buf((isZtBuffer) ? ZT_PTRTOBUF(packetData) : new ZeroTier::Buf(packetData, packetLength & ZT_BUF_MEM_MASK)); ZeroTier::SharedPtr< ZeroTier::Buf > buf((isZtBuffer) ? ZT_PTRTOBUF(packetData) : new ZeroTier::Buf(packetData, packetLength & ZT_BUF_MEM_MASK));
return reinterpret_cast<ZeroTier::Node *>(node)->processWirePacket(tptr, now, localSocket, remoteAddress, buf, packetLength, nextBackgroundTaskDeadline); return reinterpret_cast<ZeroTier::Node *>(node)->processWirePacket(tptr, now, localSocket, ZT_InetAddress_ptr_cast_const_sockaddr_storage_ptr(remoteAddress), buf, packetLength, nextBackgroundTaskDeadline);
} catch (std::bad_alloc &exc) { } catch (std::bad_alloc &exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} catch (...) { } catch (...) {
@ -755,4 +755,79 @@ int ZT_Fingerprint_fromString(ZT_Fingerprint *fp, const char *s)
/********************************************************************************************************************/ /********************************************************************************************************************/
void ZT_InetAddress_clear(ZT_InetAddress *ia)
{
if (likely(ia != nullptr))
ZeroTier::Utils::zero<sizeof(ZT_InetAddress)>(ia);
}
char *ZT_InetAddress_toString(const ZT_InetAddress *ia, char *buf, unsigned int cap)
{
if (likely((cap > 0)&&(buf != nullptr))) {
if (likely((ia != nullptr)&&(cap >= ZT_INETADDRESS_STRING_SIZE_MAX))) {
reinterpret_cast<const ZeroTier::InetAddress *>(ia)->toString(buf);
} else {
buf[0] = 0;
}
}
return buf;
}
int ZT_InetAddress_fromString(ZT_InetAddress *ia, const char *str)
{
if (likely((ia != nullptr)&&(str != nullptr))) {
return (int)reinterpret_cast<ZeroTier::InetAddress *>(ia)->fromString(str);
}
return 0;
}
void ZT_InetAddress_set(ZT_InetAddress *ia, const void *saddr)
{
if (likely(ia != nullptr))
(*reinterpret_cast<ZeroTier::InetAddress *>(ia)) = reinterpret_cast<const struct sockaddr *>(saddr);
}
void ZT_InetAddress_setIpBytes(ZT_InetAddress *ia, const void *ipBytes, unsigned int ipLen, unsigned int port)
{
if (likely(ia != nullptr))
reinterpret_cast<ZeroTier::InetAddress *>(ia)->set(ipBytes, ipLen, port);
}
void ZT_InetAddress_setPort(ZT_InetAddress *ia, unsigned int port)
{
if (likely(ia != nullptr))
reinterpret_cast<ZeroTier::InetAddress *>(ia)->setPort(port);
}
unsigned int ZT_InetAddress_port(const ZT_InetAddress *ia)
{
if (likely(ia != nullptr))
return reinterpret_cast<const ZeroTier::InetAddress *>(ia)->port();
return 0;
}
int ZT_InetAddress_isNil(const ZT_InetAddress *ia)
{
return (int)( (ia == nullptr) || ((reinterpret_cast<const sockaddr_storage *>(ia))->ss_family == 0) );
}
int ZT_InetAddress_isV4(const ZT_InetAddress *ia)
{
return (int)( (ia != nullptr) && ((reinterpret_cast<const sockaddr_storage *>(ia))->ss_family == AF_INET) );
}
int ZT_InetAddress_isV6(const ZT_InetAddress *ia)
{
return (int)( (ia != nullptr) && ((reinterpret_cast<const sockaddr_storage *>(ia))->ss_family == AF_INET6) );
}
enum ZT_InetAddress_IpScope ZT_InetAddress_ipScope(const ZT_InetAddress *ia)
{
if (likely(ia != nullptr))
return reinterpret_cast<const ZeroTier::InetAddress *>(ia)->ipScope();
return ZT_IP_SCOPE_NONE;
}
/********************************************************************************************************************/
} // extern "C" } // extern "C"

View file

@ -14,9 +14,13 @@
#ifndef ZT_CONSTANTS_HPP #ifndef ZT_CONSTANTS_HPP
#define ZT_CONSTANTS_HPP #define ZT_CONSTANTS_HPP
#include "zerotier.h" /**
#include "OS.hpp" * Indicates to some parts of zerotier.h that we are building the core
*/
#define ZT_CORE 1
#include "OS.hpp"
#include "zerotier.h"
#include "version.h" #include "version.h"
/** /**

View file

@ -19,6 +19,10 @@
namespace ZeroTier { namespace ZeroTier {
static_assert(ZT_SOCKADDR_STORAGE_SIZE == sizeof(sockaddr_storage), "ZT_SOCKADDR_STORAGE_SIZE is incorrect on this platform, must be size of sockaddr_storage");
static_assert(ZT_SOCKADDR_STORAGE_SIZE == sizeof(InetAddress), "ZT_SOCKADDR_STORAGE_SIZE should equal InetAddress, which should equal size of sockaddr_storage");
static_assert(ZT_SOCKADDR_STORAGE_SIZE == sizeof(ZT_InetAddress), "ZT_SOCKADDR_STORAGE_SIZE should equal ZT_InetAddress, which should equal size of sockaddr_storage");
const InetAddress InetAddress::LO4((const void *) ("\x7f\x00\x00\x01"), 4, 0); const InetAddress InetAddress::LO4((const void *) ("\x7f\x00\x00\x01"), 4, 0);
const InetAddress InetAddress::LO6((const void *) ("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"), 16, 0); const InetAddress InetAddress::LO6((const void *) ("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"), 16, 0);
const InetAddress InetAddress::NIL; const InetAddress InetAddress::NIL;
@ -31,11 +35,11 @@ InetAddress::IpScope InetAddress::ipScope() const noexcept
const uint32_t ip = Utils::ntoh((uint32_t)as.sa_in.sin_addr.s_addr); const uint32_t ip = Utils::ntoh((uint32_t)as.sa_in.sin_addr.s_addr);
switch (ip >> 24U) { switch (ip >> 24U) {
case 0x00: case 0x00:
return IP_SCOPE_NONE; // 0.0.0.0/8 (reserved, never used) return ZT_IP_SCOPE_NONE; // 0.0.0.0/8 (reserved, never used)
case 0x06: case 0x06:
return IP_SCOPE_PSEUDOPRIVATE; // 6.0.0.0/8 (US Army) return ZT_IP_SCOPE_PSEUDOPRIVATE; // 6.0.0.0/8 (US Army)
case 0x0a: case 0x0a:
return IP_SCOPE_PRIVATE; // 10.0.0.0/8 return ZT_IP_SCOPE_PRIVATE; // 10.0.0.0/8
case 0x0b: //return IP_SCOPE_PSEUDOPRIVATE; // 11.0.0.0/8 (US DoD) case 0x0b: //return IP_SCOPE_PSEUDOPRIVATE; // 11.0.0.0/8 (US DoD)
case 0x15: //return IP_SCOPE_PSEUDOPRIVATE; // 21.0.0.0/8 (US DDN-RVN) case 0x15: //return IP_SCOPE_PSEUDOPRIVATE; // 21.0.0.0/8 (US DDN-RVN)
case 0x16: //return IP_SCOPE_PSEUDOPRIVATE; // 22.0.0.0/8 (US DISA) case 0x16: //return IP_SCOPE_PSEUDOPRIVATE; // 22.0.0.0/8 (US DISA)
@ -47,65 +51,65 @@ InetAddress::IpScope InetAddress::ipScope() const noexcept
case 0x33: //return IP_SCOPE_PSEUDOPRIVATE; // 51.0.0.0/8 (UK Department of Social Security) case 0x33: //return IP_SCOPE_PSEUDOPRIVATE; // 51.0.0.0/8 (UK Department of Social Security)
case 0x37: //return IP_SCOPE_PSEUDOPRIVATE; // 55.0.0.0/8 (US DoD) case 0x37: //return IP_SCOPE_PSEUDOPRIVATE; // 55.0.0.0/8 (US DoD)
case 0x38: // 56.0.0.0/8 (US Postal Service) case 0x38: // 56.0.0.0/8 (US Postal Service)
return IP_SCOPE_PSEUDOPRIVATE; return ZT_IP_SCOPE_PSEUDOPRIVATE;
case 0x64: case 0x64:
if ((ip & 0xffc00000) == 0x64400000) return IP_SCOPE_PRIVATE; // 100.64.0.0/10 if ((ip & 0xffc00000) == 0x64400000) return ZT_IP_SCOPE_PRIVATE; // 100.64.0.0/10
break; break;
case 0x7f: case 0x7f:
return IP_SCOPE_LOOPBACK; // 127.0.0.0/8 return ZT_IP_SCOPE_LOOPBACK; // 127.0.0.0/8
case 0xa9: case 0xa9:
if ((ip & 0xffff0000) == 0xa9fe0000) return IP_SCOPE_LINK_LOCAL; // 169.254.0.0/16 if ((ip & 0xffff0000) == 0xa9fe0000) return ZT_IP_SCOPE_LINK_LOCAL; // 169.254.0.0/16
break; break;
case 0xac: case 0xac:
if ((ip & 0xfff00000) == 0xac100000) return IP_SCOPE_PRIVATE; // 172.16.0.0/12 if ((ip & 0xfff00000) == 0xac100000) return ZT_IP_SCOPE_PRIVATE; // 172.16.0.0/12
break; break;
case 0xc0: case 0xc0:
if ((ip & 0xffff0000) == 0xc0a80000) return IP_SCOPE_PRIVATE; // 192.168.0.0/16 if ((ip & 0xffff0000) == 0xc0a80000) return ZT_IP_SCOPE_PRIVATE; // 192.168.0.0/16
if ((ip & 0xffffff00) == 0xc0000200) return IP_SCOPE_PRIVATE; // 192.0.2.0/24 if ((ip & 0xffffff00) == 0xc0000200) return ZT_IP_SCOPE_PRIVATE; // 192.0.2.0/24
break; break;
case 0xc6: case 0xc6:
if ((ip & 0xfffe0000) == 0xc6120000) return IP_SCOPE_PRIVATE; // 198.18.0.0/15 if ((ip & 0xfffe0000) == 0xc6120000) return ZT_IP_SCOPE_PRIVATE; // 198.18.0.0/15
if ((ip & 0xffffff00) == 0xc6336400) return IP_SCOPE_PRIVATE; // 198.51.100.0/24 if ((ip & 0xffffff00) == 0xc6336400) return ZT_IP_SCOPE_PRIVATE; // 198.51.100.0/24
break; break;
case 0xcb: case 0xcb:
if ((ip & 0xffffff00) == 0xcb007100) return IP_SCOPE_PRIVATE; // 203.0.113.0/24 if ((ip & 0xffffff00) == 0xcb007100) return ZT_IP_SCOPE_PRIVATE; // 203.0.113.0/24
break; break;
case 0xff: case 0xff:
return IP_SCOPE_NONE; // 255.0.0.0/8 (broadcast, or unused/unusable) return ZT_IP_SCOPE_NONE; // 255.0.0.0/8 (broadcast, or unused/unusable)
} }
switch (ip >> 28U) { switch (ip >> 28U) {
case 0xe: case 0xe:
return IP_SCOPE_MULTICAST; // 224.0.0.0/4 return ZT_IP_SCOPE_MULTICAST; // 224.0.0.0/4
case 0xf: case 0xf:
return IP_SCOPE_PSEUDOPRIVATE; // 240.0.0.0/4 ("reserved," usually unusable) return ZT_IP_SCOPE_PSEUDOPRIVATE; // 240.0.0.0/4 ("reserved," usually unusable)
} }
return IP_SCOPE_GLOBAL; return ZT_IP_SCOPE_GLOBAL;
} }
case AF_INET6: { case AF_INET6: {
const uint8_t *const ip = as.sa_in6.sin6_addr.s6_addr; const uint8_t *const ip = as.sa_in6.sin6_addr.s6_addr;
if ((ip[0] & 0xf0U) == 0xf0) { if ((ip[0] & 0xf0U) == 0xf0) {
if (ip[0] == 0xff) return IP_SCOPE_MULTICAST; // ff00::/8 if (ip[0] == 0xff) return ZT_IP_SCOPE_MULTICAST; // ff00::/8
if ((ip[0] == 0xfe) && ((ip[1] & 0xc0U) == 0x80)) { if ((ip[0] == 0xfe) && ((ip[1] & 0xc0U) == 0x80)) {
unsigned int k = 2; unsigned int k = 2;
while ((!ip[k]) && (k < 15)) ++k; while ((!ip[k]) && (k < 15)) ++k;
if ((k == 15) && (ip[15] == 0x01)) if ((k == 15) && (ip[15] == 0x01))
return IP_SCOPE_LOOPBACK; // fe80::1/128 return ZT_IP_SCOPE_LOOPBACK; // fe80::1/128
else return IP_SCOPE_LINK_LOCAL; // fe80::/10 else return ZT_IP_SCOPE_LINK_LOCAL; // fe80::/10
} }
if ((ip[0] & 0xfeU) == 0xfc) return IP_SCOPE_PRIVATE; // fc00::/7 if ((ip[0] & 0xfeU) == 0xfc) return ZT_IP_SCOPE_PRIVATE; // fc00::/7
} }
unsigned int k = 0; unsigned int k = 0;
while ((!ip[k]) && (k < 15)) ++k; while ((!ip[k]) && (k < 15)) ++k;
if (k == 15) { // all 0's except last byte if (k == 15) { // all 0's except last byte
if (ip[15] == 0x01) return IP_SCOPE_LOOPBACK; // ::1/128 if (ip[15] == 0x01) return ZT_IP_SCOPE_LOOPBACK; // ::1/128
if (ip[15] == 0x00) return IP_SCOPE_NONE; // ::/128 if (ip[15] == 0x00) return ZT_IP_SCOPE_NONE; // ::/128
} }
return IP_SCOPE_GLOBAL; return ZT_IP_SCOPE_GLOBAL;
} }
} }
return IP_SCOPE_NONE; return ZT_IP_SCOPE_NONE;
} }
void InetAddress::set(const void *ipBytes, unsigned int ipLen, unsigned int port) noexcept void InetAddress::set(const void *ipBytes, unsigned int ipLen, unsigned int port) noexcept

View file

@ -59,17 +59,7 @@ public:
* MUST remain that way or Path must be changed to reflect. Also be sure * MUST remain that way or Path must be changed to reflect. Also be sure
* to change ZT_INETADDRESS_MAX_SCOPE if the max changes. * to change ZT_INETADDRESS_MAX_SCOPE if the max changes.
*/ */
enum IpScope typedef ZT_InetAddress_IpScope IpScope;
{
IP_SCOPE_NONE = 0, // NULL or not an IP address
IP_SCOPE_MULTICAST = 1, // 224.0.0.0 and other V4/V6 multicast IPs
IP_SCOPE_LOOPBACK = 2, // 127.0.0.1, ::1, etc.
IP_SCOPE_PSEUDOPRIVATE = 3, // 28.x.x.x, etc. -- unofficially unrouted IPv4 blocks often "bogarted"
IP_SCOPE_GLOBAL = 4, // globally routable IP address (all others)
IP_SCOPE_LINK_LOCAL = 5, // 169.254.x.x, IPv6 LL
IP_SCOPE_SHARED = 6, // currently unused, formerly used for carrier-grade NAT ranges
IP_SCOPE_PRIVATE = 7 // 10.x.x.x, 192.168.x.x, etc.
};
// Hasher for unordered sets and maps in C++11 // Hasher for unordered sets and maps in C++11
struct Hasher struct Hasher
@ -130,52 +120,52 @@ public:
ZT_INLINE InetAddress &operator=(const sockaddr_in &sa) noexcept ZT_INLINE InetAddress &operator=(const sockaddr_in &sa) noexcept
{ {
memoryZero(this);
as.sa_in = sa; as.sa_in = sa;
return *this; return *this;
} }
ZT_INLINE InetAddress &operator=(const sockaddr_in *sa) noexcept ZT_INLINE InetAddress &operator=(const sockaddr_in *sa) noexcept
{ {
memoryZero(this);
if (sa) if (sa)
as.sa_in = *sa; as.sa_in = *sa;
else memoryZero(this);
return *this; return *this;
} }
ZT_INLINE InetAddress &operator=(const sockaddr_in6 &sa) noexcept ZT_INLINE InetAddress &operator=(const sockaddr_in6 &sa) noexcept
{ {
memoryZero(this);
as.sa_in6 = sa; as.sa_in6 = sa;
return *this; return *this;
} }
ZT_INLINE InetAddress &operator=(const sockaddr_in6 *sa) noexcept ZT_INLINE InetAddress &operator=(const sockaddr_in6 *sa) noexcept
{ {
memoryZero(this);
if (sa) if (sa)
as.sa_in6 = *sa; as.sa_in6 = *sa;
else memoryZero(this);
return *this; return *this;
} }
ZT_INLINE InetAddress &operator=(const sockaddr &sa) noexcept ZT_INLINE InetAddress &operator=(const sockaddr &sa) noexcept
{ {
memoryZero(this);
if (sa.sa_family == AF_INET) if (sa.sa_family == AF_INET)
as.sa_in = *reinterpret_cast<const sockaddr_in *>(&sa); as.sa_in = *reinterpret_cast<const sockaddr_in *>(&sa);
else if (sa.sa_family == AF_INET6) else if (sa.sa_family == AF_INET6)
as.sa_in6 = *reinterpret_cast<const sockaddr_in6 *>(&sa); as.sa_in6 = *reinterpret_cast<const sockaddr_in6 *>(&sa);
else memoryZero(this);
return *this; return *this;
} }
ZT_INLINE InetAddress &operator=(const sockaddr *sa) noexcept ZT_INLINE InetAddress &operator=(const sockaddr *sa) noexcept
{ {
memoryZero(this);
if (sa) { if (sa) {
if (sa->sa_family == AF_INET) if (sa->sa_family == AF_INET)
as.sa_in = *reinterpret_cast<const sockaddr_in *>(sa); as.sa_in = *reinterpret_cast<const sockaddr_in *>(sa);
else if (sa->sa_family == AF_INET6) else if (sa->sa_family == AF_INET6)
as.sa_in6 = *reinterpret_cast<const sockaddr_in6 *>(sa); as.sa_in6 = *reinterpret_cast<const sockaddr_in6 *>(sa);
else memoryZero(this);
} else {
memoryZero(this);
} }
return *this; return *this;
} }
@ -625,6 +615,9 @@ static ZT_INLINE InetAddress *asInetAddress(sockaddr *const p) noexcept
static ZT_INLINE InetAddress *asInetAddress(sockaddr_storage *const p) noexcept static ZT_INLINE InetAddress *asInetAddress(sockaddr_storage *const p) noexcept
{ return reinterpret_cast<InetAddress *>(p); } { return reinterpret_cast<InetAddress *>(p); }
static ZT_INLINE InetAddress *asInetAddress(ZT_InetAddress *const p) noexcept
{ return reinterpret_cast<InetAddress *>(p); }
static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_in *const p) noexcept static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_in *const p) noexcept
{ return reinterpret_cast<const InetAddress *>(p); } { return reinterpret_cast<const InetAddress *>(p); }
@ -637,6 +630,9 @@ static ZT_INLINE const InetAddress *asInetAddress(const sockaddr *const p) noexc
static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_storage *const p) noexcept static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_storage *const p) noexcept
{ return reinterpret_cast<const InetAddress *>(p); } { return reinterpret_cast<const InetAddress *>(p); }
static ZT_INLINE const InetAddress *asInetAddress(const ZT_InetAddress *const p) noexcept
{ return reinterpret_cast<const InetAddress *>(p); }
static ZT_INLINE InetAddress &asInetAddress(sockaddr_in &p) noexcept static ZT_INLINE InetAddress &asInetAddress(sockaddr_in &p) noexcept
{ return *reinterpret_cast<InetAddress *>(&p); } { return *reinterpret_cast<InetAddress *>(&p); }
@ -649,6 +645,9 @@ static ZT_INLINE InetAddress &asInetAddress(sockaddr &p) noexcept
static ZT_INLINE InetAddress &asInetAddress(sockaddr_storage &p) noexcept static ZT_INLINE InetAddress &asInetAddress(sockaddr_storage &p) noexcept
{ return *reinterpret_cast<InetAddress *>(&p); } { return *reinterpret_cast<InetAddress *>(&p); }
static ZT_INLINE InetAddress &asInetAddress(ZT_InetAddress &p) noexcept
{ return *reinterpret_cast<InetAddress *>(&p); }
static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_in &p) noexcept static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_in &p) noexcept
{ return *reinterpret_cast<const InetAddress *>(&p); } { return *reinterpret_cast<const InetAddress *>(&p); }
@ -661,6 +660,9 @@ static ZT_INLINE const InetAddress &asInetAddress(const sockaddr &p) noexcept
static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_storage &p) noexcept static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_storage &p) noexcept
{ return *reinterpret_cast<const InetAddress *>(&p); } { return *reinterpret_cast<const InetAddress *>(&p); }
static ZT_INLINE const InetAddress &asInetAddress(const ZT_InetAddress &p) noexcept
{ return *reinterpret_cast<const InetAddress *>(&p); }
} // namespace ZeroTier } // namespace ZeroTier
#endif #endif

View file

@ -703,7 +703,7 @@ bool Node::shouldUsePathForZeroTierTraffic(void *tPtr, const Identity &id, const
id.address().toInt(), id.address().toInt(),
(const ZT_Identity *)&id, (const ZT_Identity *)&id,
localSocket, localSocket,
reinterpret_cast<const struct sockaddr_storage *>(&remoteAddress)) != 0); reinterpret_cast<const ZT_InetAddress *>(&remoteAddress)) != 0);
} }
return true; return true;
@ -719,7 +719,7 @@ bool Node::externalPathLookup(void *tPtr, const Identity &id, int family, InetAd
id.address().toInt(), id.address().toInt(),
reinterpret_cast<const ZT_Identity *>(&id), reinterpret_cast<const ZT_Identity *>(&id),
family, family,
reinterpret_cast<sockaddr_storage *>(&addr)) == ZT_RESULT_OK); reinterpret_cast<ZT_InetAddress *>(&addr)) == ZT_RESULT_OK);
} }
return false; return false;
} }

View file

@ -178,7 +178,7 @@ public:
m_uPtr, m_uPtr,
tPtr, tPtr,
localSocket, localSocket,
&addr.as.ss, reinterpret_cast<const ZT_InetAddress *>(&addr.as.ss),
data, data,
len, len,
ttl) == 0); ttl) == 0);

View file

@ -58,6 +58,13 @@
#endif /* Microsoft Windows */ #endif /* Microsoft Windows */
#ifndef __WINDOWS__
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#endif /* NOT Microsoft Windows */
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>

View file

@ -53,7 +53,7 @@ void SelfAwareness::iam(void *tPtr, const Identity &reporter, const int64_t rece
{ {
const InetAddress::IpScope scope = myPhysicalAddress.ipScope(); const InetAddress::IpScope scope = myPhysicalAddress.ipScope();
if ((scope != reporterPhysicalAddress.ipScope()) || (scope == InetAddress::IP_SCOPE_NONE) || (scope == InetAddress::IP_SCOPE_LOOPBACK) || (scope == InetAddress::IP_SCOPE_MULTICAST)) if ((scope != reporterPhysicalAddress.ipScope()) || (scope == ZT_IP_SCOPE_NONE) || (scope == ZT_IP_SCOPE_LOOPBACK) || (scope == ZT_IP_SCOPE_MULTICAST))
return; return;
Mutex::Lock l(m_phy_l); Mutex::Lock l(m_phy_l);

View file

@ -18,19 +18,6 @@
#ifndef ZT_ZEROTIER_API_H #ifndef ZT_ZEROTIER_API_H
#define ZT_ZEROTIER_API_H #define ZT_ZEROTIER_API_H
#if defined(_WIN32) || defined(_WIN64)
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <Windows.h>
#else
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#endif
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
@ -281,6 +268,34 @@ typedef void ZT_Identity;
*/ */
typedef void ZT_Locator; typedef void ZT_Locator;
#define ZT_SOCKADDR_STORAGE_SIZE 128
/**
* InetAddress holds a socket address
*
* This is a sized placeholder for InetAddress in the C++ code or the
* sockaddr_storage structure. Its size is checked at compile time in
* InetAddress.cpp against sizeof(sockaddr_storage) to ensure that it
* is correct for the platform. If it's not correct, a platform ifdef
* will be needed.
*/
typedef struct { uint64_t bits[ZT_SOCKADDR_STORAGE_SIZE / 8]; } ZT_InetAddress;
/**
* IP scope types as identified by InetAddress.
*/
enum ZT_InetAddress_IpScope
{
ZT_IP_SCOPE_NONE = 0, // NULL or not an IP address
ZT_IP_SCOPE_MULTICAST = 1, // 224.0.0.0 and other V4/V6 multicast IPs
ZT_IP_SCOPE_LOOPBACK = 2, // 127.0.0.1, ::1, etc.
ZT_IP_SCOPE_PSEUDOPRIVATE = 3, // 28.x.x.x, etc. -- unofficially unrouted IPv4 blocks often "bogarted"
ZT_IP_SCOPE_GLOBAL = 4, // globally routable IP address (all others)
ZT_IP_SCOPE_LINK_LOCAL = 5, // 169.254.x.x, IPv6 LL
ZT_IP_SCOPE_SHARED = 6, // currently unused, formerly used for carrier-grade NAT ranges
ZT_IP_SCOPE_PRIVATE = 7 // 10.x.x.x, 192.168.x.x, etc.
};
/** /**
* Full identity fingerprint with address and 384-bit hash of public key(s) * Full identity fingerprint with address and 384-bit hash of public key(s)
*/ */
@ -1311,12 +1326,12 @@ typedef struct
/** /**
* Target network / netmask bits (in port field) or NULL or 0.0.0.0/0 for default * Target network / netmask bits (in port field) or NULL or 0.0.0.0/0 for default
*/ */
struct sockaddr_storage target; ZT_InetAddress target;
/** /**
* Gateway IP address (port ignored) or NULL (family == 0) for LAN-local (no gateway) * Gateway IP address (port ignored) or NULL (family == 0) for LAN-local (no gateway)
*/ */
struct sockaddr_storage via; ZT_InetAddress via;
/** /**
* Route flags * Route flags
@ -1439,7 +1454,7 @@ typedef struct
* This is only used for ZeroTier-managed address assignments sent by the * This is only used for ZeroTier-managed address assignments sent by the
* virtual network's configuration master. * virtual network's configuration master.
*/ */
struct sockaddr_storage assignedAddresses[ZT_MAX_ZT_ASSIGNED_ADDRESSES]; ZT_InetAddress assignedAddresses[ZT_MAX_ZT_ASSIGNED_ADDRESSES];
/** /**
* Number of ZT-pushed routes * Number of ZT-pushed routes
@ -1471,7 +1486,7 @@ typedef struct
/** /**
* IP and port as would be reachable by external nodes * IP and port as would be reachable by external nodes
*/ */
struct sockaddr_storage address; ZT_InetAddress address;
/** /**
* If nonzero this address is static and can be incorporated into this node's Locator * If nonzero this address is static and can be incorporated into this node's Locator
@ -1491,6 +1506,15 @@ typedef struct
union union
{ {
/**
* ZT_InetAddress, which is identically sized to sockaddr_storage.
*
* The ZT_InetAddress conversion macros can be used to get this in the
* form of a sockaddr, sockaddr_in, etc.
*/
ZT_InetAddress ia;
#ifdef ZT_CORE
/** /**
* Socket address generic buffer * Socket address generic buffer
*/ */
@ -1510,6 +1534,7 @@ typedef struct
* IPv6 address, for all ZT_ENDPOINT_TYPE_IP types if family is AF_INET6 * IPv6 address, for all ZT_ENDPOINT_TYPE_IP types if family is AF_INET6
*/ */
struct sockaddr_in6 sa_in6; struct sockaddr_in6 sa_in6;
#endif
/** /**
* MAC address (least significant 48 bites) for ZT_ENDPOINT_TYPE_ETHERNET and other MAC addressed types * MAC address (least significant 48 bites) for ZT_ENDPOINT_TYPE_ETHERNET and other MAC addressed types
@ -1875,7 +1900,7 @@ typedef int (*ZT_WirePacketSendFunction)(
void *, /* User ptr */ void *, /* User ptr */
void *, /* Thread ptr */ void *, /* Thread ptr */
int64_t, /* Local socket */ int64_t, /* Local socket */
const struct sockaddr_storage *, /* Remote address */ const ZT_InetAddress *, /* Remote address */
const void *, /* Packet data */ const void *, /* Packet data */
unsigned int, /* Packet length */ unsigned int, /* Packet length */
unsigned int); /* TTL or 0 to use default */ unsigned int); /* TTL or 0 to use default */
@ -1909,7 +1934,7 @@ typedef int (*ZT_PathCheckFunction)(
uint64_t, /* ZeroTier address */ uint64_t, /* ZeroTier address */
const ZT_Identity *, /* Full identity of node */ const ZT_Identity *, /* Full identity of node */
int64_t, /* Local socket or -1 if unknown */ int64_t, /* Local socket or -1 if unknown */
const struct sockaddr_storage *); /* Remote address */ const ZT_InetAddress *); /* Remote address */
/** /**
* Function to get physical addresses for ZeroTier peers * Function to get physical addresses for ZeroTier peers
@ -1934,7 +1959,7 @@ typedef int (*ZT_PathLookupFunction)(
uint64_t, /* ZeroTier address (40 bits) */ uint64_t, /* ZeroTier address (40 bits) */
const ZT_Identity *, /* Full identity of node */ const ZT_Identity *, /* Full identity of node */
int, /* Desired ss_family or -1 for any */ int, /* Desired ss_family or -1 for any */
struct sockaddr_storage *); /* Result buffer */ ZT_InetAddress *); /* Result buffer */
/* ---------------------------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------------------------- */
@ -2071,7 +2096,7 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processWirePacket(
void *tptr, void *tptr,
int64_t now, int64_t now,
int64_t localSocket, int64_t localSocket,
const struct sockaddr_storage *remoteAddress, const ZT_InetAddress *remoteAddress,
const void *packetData, const void *packetData,
unsigned int packetLength, unsigned int packetLength,
int isZtBuffer, int isZtBuffer,
@ -2892,6 +2917,65 @@ ZT_SDK_API int ZT_Fingerprint_fromString(ZT_Fingerprint *fp, const char *s);
/* ---------------------------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------------------------- */
/*
* InetAddress casting macros depend on the relevant struct being defined.
* System headers with sockaddr, sockaddr_in, etc. must have already been
* included.
*/
#define ZT_InetAddress_ptr_cast_sockaddr_ptr(a) ((struct sockaddr *)(a))
#define ZT_InetAddress_ptr_cast_sockaddr_in_ptr(a) ((struct sockaddr_in *)(a))
#define ZT_InetAddress_ptr_cast_sockaddr_in6_ptr(a) ((struct sockaddr_in6 *)(a))
#define ZT_InetAddress_ptr_cast_sockaddr_storage_ptr(a) ((struct sockaddr_storage *)(a))
#define ZT_InetAddress_ptr_cast_const_sockaddr_ptr(a) ((const struct sockaddr *)(a))
#define ZT_InetAddress_ptr_cast_const_sockaddr_in_ptr(a) ((const struct sockaddr_in *)(a))
#define ZT_InetAddress_ptr_cast_const_sockaddr_in6_ptr(a) ((const struct sockaddr_in6 *)(a))
#define ZT_InetAddress_ptr_cast_const_sockaddr_storage_ptr(a) ((const struct sockaddr_storage *)(a))
#define ZT_InetAddress_cast_sockaddr_ptr(a) ((struct sockaddr *)(&(a)))
#define ZT_InetAddress_cast_sockaddr_in_ptr(a) ((struct sockaddr_in *)(&(a)))
#define ZT_InetAddress_cast_sockaddr_in6_ptr(a) ((struct sockaddr_in6 *)(&(a)))
#define ZT_InetAddress_cast_sockaddr_storage_ptr(a) ((struct sockaddr_storage *)(&(a)))
#define ZT_InetAddress_cast_const_sockaddr_ptr(a) ((const struct sockaddr *)(&(a)))
#define ZT_InetAddress_cast_const_sockaddr_in_ptr(a) ((const struct sockaddr_in *)(&(a)))
#define ZT_InetAddress_cast_const_sockaddr_in6_ptr(a) ((const struct sockaddr_in6 *)(&(a)))
#define ZT_InetAddress_cast_const_sockaddr_storage_ptr(a) ((const struct sockaddr_storage *)(&(a)))
ZT_SDK_API void ZT_InetAddress_clear(ZT_InetAddress *ia);
/**
* Convert an IP/port pair to a string
*
* @param ia InetAddress to convert
* @param buf Buffer to store result
* @param cap Size of buffer, must be at least 64 bytes
* @return 'buf' is returned
*/
ZT_SDK_API char *ZT_InetAddress_toString(const ZT_InetAddress *ia, char *buf, unsigned int cap);
ZT_SDK_API int ZT_InetAddress_fromString(ZT_InetAddress *ia, const char *str);
ZT_SDK_API void ZT_InetAddress_set(ZT_InetAddress *ia, const void *saddr);
ZT_SDK_API void ZT_InetAddress_setIpBytes(ZT_InetAddress *ia, const void *ipBytes, unsigned int ipLen, unsigned int port);
ZT_SDK_API void ZT_InetAddress_setPort(ZT_InetAddress *ia, unsigned int port);
ZT_SDK_API unsigned int ZT_InetAddress_port(const ZT_InetAddress *ia);
ZT_SDK_API int ZT_InetAddress_isNil(const ZT_InetAddress *ia);
ZT_SDK_API int ZT_InetAddress_isV4(const ZT_InetAddress *ia);
ZT_SDK_API int ZT_InetAddress_isV6(const ZT_InetAddress *ia);
ZT_SDK_API enum ZT_InetAddress_IpScope ZT_InetAddress_ipScope(const ZT_InetAddress *ia);
/* ---------------------------------------------------------------------------------------------------------------- */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -6,12 +6,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "hex" name = "hex"
version = "0.4.2" version = "0.4.2"
@ -24,12 +18,6 @@ version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
[[package]]
name = "libc"
version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
[[package]] [[package]]
name = "num-derive" name = "num-derive"
version = "0.3.3" version = "0.3.3"
@ -77,7 +65,6 @@ dependencies = [
"num-traits", "num-traits",
"serde", "serde",
"serde_json", "serde_json",
"socket2",
] ]
[[package]] [[package]]
@ -117,17 +104,6 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "socket2"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97e0e9fd577458a4f61fb91fcb559ea2afecc54c934119421f9f5d3d5b1a1057"
dependencies = [
"cfg-if",
"libc",
"winapi",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.54" version = "1.0.54"
@ -144,25 +120,3 @@ name = "unicode-xid"
version = "0.2.1" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View file

@ -4,12 +4,9 @@ version = "0.1.0"
authors = ["Adam Ierymenko <adam.ierymenko@zerotier.com>"] authors = ["Adam Ierymenko <adam.ierymenko@zerotier.com>"]
edition = "2018" edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
num-traits = "0.2.14" num-traits = "0.2.14"
num-derive = "0.3.3" num-derive = "0.3.3"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
serde_json = "1" serde_json = "1"
hex = "0.4.2" hex = "0.4.2"
socket2 = "0.3.18"

View file

@ -1,6 +1,6 @@
use std::ffi::CStr; use std::ffi::{CStr, CString};
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::os::raw::{c_char, c_int}; use std::os::raw::{c_char, c_int, c_void};
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::FromPrimitive; use num_traits::FromPrimitive;
@ -35,9 +35,14 @@ impl Endpoint {
} }
pub fn new_from_string(s: &str) -> Result<Endpoint, ResultCode> { pub fn new_from_string(s: &str) -> Result<Endpoint, ResultCode> {
let cs = CString::new(s);
if cs.is_err() {
return Err(ResultCode::ErrorBadParameter);
}
let cs = cs.unwrap();
unsafe { unsafe {
let mut cep: MaybeUninit<ztcore::ZT_Endpoint> = MaybeUninit::uninit(); let mut cep: MaybeUninit<ztcore::ZT_Endpoint> = MaybeUninit::uninit();
let ec = ztcore::ZT_Endpoint_fromString(cep.as_mut_ptr(), s.as_ptr() as *const c_char) as i32; let ec = ztcore::ZT_Endpoint_fromString(cep.as_mut_ptr(), cs.as_ptr()) as i32;
if ec == 0 { if ec == 0 {
let epi = cep.assume_init(); let epi = cep.assume_init();
return Ok(Endpoint{ return Ok(Endpoint{
@ -48,6 +53,18 @@ impl Endpoint {
return Err(ResultCode::from_i32(ec).unwrap()); return Err(ResultCode::from_i32(ec).unwrap());
} }
} }
/// Get a reference to the InetAddress in this endpoint or None if this is not of a relevant type.
pub fn as_inetaddress(&self) -> Option<&InetAddress> {
match self.type_ {
EndpointType::Ip | EndpointType::IpUdp | EndpointType::IpTcp | EndpointType::IpHttp => {
unsafe {
Some(InetAddress::transmute_capi(&self.capi.value.ia))
}
},
_ => None
}
}
} }
impl ToString for Endpoint { impl ToString for Endpoint {

View file

@ -1,7 +1,7 @@
use crate::*; use crate::*;
use crate::bindings::capi as ztcore; use crate::bindings::capi as ztcore;
use std::os::raw::{c_char, c_int}; use std::os::raw::{c_char, c_int};
use std::ffi::CStr; use std::ffi::{CStr, CString};
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
pub struct Fingerprint { pub struct Fingerprint {
@ -19,9 +19,14 @@ impl Fingerprint {
} }
pub fn new_from_string(s: &str) -> Result<Fingerprint, ResultCode> { pub fn new_from_string(s: &str) -> Result<Fingerprint, ResultCode> {
let cs = CString::new(s);
if cs.is_err() {
return Err(ResultCode::ErrorBadParameter);
}
let cs = cs.unwrap();
let mut cfp: MaybeUninit<ztcore::ZT_Fingerprint> = MaybeUninit::uninit();
unsafe { unsafe {
let mut cfp: MaybeUninit<ztcore::ZT_Fingerprint> = MaybeUninit::uninit(); if ztcore::ZT_Fingerprint_fromString(cfp.as_mut_ptr(), cs.as_ptr()) != 0 {
if ztcore::ZT_Fingerprint_fromString(cfp.as_mut_ptr(), s.as_ptr() as *const c_char) != 0 {
let fp = cfp.assume_init(); let fp = cfp.assume_init();
return Ok(Fingerprint{ return Ok(Fingerprint{
address: Address(fp.address), address: Address(fp.address),
@ -43,7 +48,7 @@ impl ToString for Fingerprint {
}, buf.as_mut_ptr() as *mut c_char, buf.len() as c_int).is_null() { }, buf.as_mut_ptr() as *mut c_char, buf.len() as c_int).is_null() {
return String::from("(invalid)"); return String::from("(invalid)");
} }
return String::from(CStr::from_bytes_with_nul(buf.as_ref()).unwrap().to_str().unwrap()); return cstr_to_string(buf.as_ptr() as *const c_char, 256);
} }
} }
} }

View file

@ -1,4 +1,4 @@
use std::ffi::CStr; use std::ffi::{CStr, CString};
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::os::raw::*; use std::os::raw::*;
@ -49,7 +49,12 @@ impl Identity {
/// Construct from a string representation of this identity. /// Construct from a string representation of this identity.
pub fn new_from_string(s: &str) -> Result<Identity, ResultCode> { pub fn new_from_string(s: &str) -> Result<Identity, ResultCode> {
unsafe { unsafe {
let id = ztcore::ZT_Identity_fromString(s.as_ptr() as *const c_char); let cs = CString::new(s);
if cs.is_err() {
return Err(ResultCode::ErrorBadParameter);
}
let cs = cs.unwrap();
let id = ztcore::ZT_Identity_fromString(cs.as_ptr());
if id.is_null() { if id.is_null() {
return Err(ResultCode::ErrorBadParameter); return Err(ResultCode::ErrorBadParameter);
} }

View file

@ -0,0 +1,140 @@
use std::ffi::CString;
use std::mem::{MaybeUninit, transmute, size_of};
use serde::{Deserialize, Serialize};
use crate::*;
use crate::bindings::capi as ztcore;
/// Opaque structure that can hold an IPv4 or IPv6 address.
pub struct InetAddress {
// This must be the same size as ZT_InetAddress in zerotier.h. This is
// checked in tests.
bits: [u64; (ztcore::ZT_SOCKADDR_STORAGE_SIZE / 8) as usize]
}
impl InetAddress {
#[inline(always)]
pub fn new() -> InetAddress {
InetAddress {
bits: [0; (ztcore::ZT_SOCKADDR_STORAGE_SIZE / 8) as usize]
}
}
pub fn new_from_string(s: &str) -> Option<InetAddress> {
let mut a = InetAddress::new();
let cs = CString::new(s);
if cs.is_ok() {
let cs = cs.unwrap();
unsafe {
if ztcore::ZT_InetAddress_fromString(a.as_mut_ptr(), cs.as_ptr()) == 0 {
return None
}
}
}
Some(a)
}
#[inline(always)]
pub(crate) unsafe fn transmute_capi(a: &ztcore::ZT_InetAddress) -> &InetAddress {
unsafe {
transmute(a)
}
}
pub(crate) fn new_from_capi(a: ztcore::ZT_InetAddress) -> Option<InetAddress> {
if a.bits[0] != 0 {
Some(InetAddress {
bits: a.bits
})
} else {
None
}
}
pub fn clear(&mut self) {
for i in self.bits.iter_mut() {
*i = 0;
}
}
#[inline(always)]
pub fn is_nil(&self) -> bool {
self.bits[0] == 0 // if ss_family != 0, this will not be zero
}
#[inline(always)]
pub(crate) fn as_ptr(&self) -> *const ztcore::ZT_InetAddress {
unsafe {
transmute(self as *const InetAddress)
}
}
#[inline(always)]
pub(crate) fn as_mut_ptr(&mut self) -> *mut ztcore::ZT_InetAddress {
unsafe {
transmute(self as *mut InetAddress)
}
}
}
impl ToString for InetAddress {
fn to_string(&self) -> String {
let mut buf: MaybeUninit<[c_char; 128]> = MaybeUninit::uninit();
unsafe {
return cstr_to_string(ztcore::ZT_InetAddress_toString(self.as_ptr(), (*buf.as_mut_ptr()).as_mut_ptr(), 128), 128);
}
}
}
impl From<&str> for InetAddress {
fn from(s: &str) -> InetAddress {
let a = InetAddress::new_from_string(s);
if a.is_none() {
return InetAddress::new();
}
a.unwrap()
}
}
impl serde::Serialize for InetAddress {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer {
serializer.serialize_str(self.to_string().as_str())
}
}
struct InetAddressVisitor;
impl<'de> serde::de::Visitor<'de> for InetAddressVisitor {
type Value = InetAddress;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("InetAddress value in string form")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> where E: serde::de::Error {
let id = InetAddress::new_from_string(s);
if id.is_none() {
return Err(serde::de::Error::invalid_value(serde::de::Unexpected::Str(s), &self));
}
return Ok(id.unwrap() as Self::Value);
}
}
impl<'de> serde::Deserialize<'de> for InetAddress {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de> {
deserializer.deserialize_str(InetAddressVisitor)
}
}
#[cfg(test)]
mod tests {
use std::mem::{size_of, zeroed};
use crate::*;
#[test]
fn type_sizes() {
assert_eq!(size_of::<ztcore::ZT_InetAddress>(), size_of::<InetAddress>());
}
}

View file

@ -1,3 +1,5 @@
#[link(name = ":../../build/core/libzt_core.a")]
use std::os::raw::{c_char, c_int}; use std::os::raw::{c_char, c_int};
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
@ -9,6 +11,7 @@ mod fingerprint;
mod endpoint; mod endpoint;
mod certificate; mod certificate;
mod networkid; mod networkid;
mod inetaddress;
mod locator; mod locator;
mod path; mod path;
mod peer; mod peer;
@ -26,6 +29,7 @@ pub use fingerprint::Fingerprint;
pub use endpoint::*; pub use endpoint::*;
pub use certificate::*; pub use certificate::*;
pub use networkid::NetworkId; pub use networkid::NetworkId;
pub use inetaddress::*;
pub use locator::*; pub use locator::*;
pub use path::Path; pub use path::Path;
pub use peer::Peer; pub use peer::Peer;

View file

@ -1,7 +1,7 @@
use crate::*; use crate::*;
use crate::bindings::capi as ztcore; use crate::bindings::capi as ztcore;
use std::os::raw::{c_char, c_int, c_uint}; use std::os::raw::{c_char, c_int, c_uint};
use std::ffi::CStr; use std::ffi::CString;
pub struct Locator { pub struct Locator {
pub(crate) capi: *const ztcore::ZT_Locator, pub(crate) capi: *const ztcore::ZT_Locator,
@ -19,7 +19,12 @@ impl Locator {
pub fn new_from_string(s: &str) -> Result<Locator, ResultCode> { pub fn new_from_string(s: &str) -> Result<Locator, ResultCode> {
unsafe { unsafe {
let l = ztcore::ZT_Locator_fromString(s.as_ptr() as *const c_char); let cs = CString::new(s);
if cs.is_err() {
return Err(ResultCode::ErrorBadParameter);
}
let cs = cs.unwrap();
let l = ztcore::ZT_Locator_fromString(cs.as_ptr());
if l.is_null() { if l.is_null() {
return Err(ResultCode::ErrorBadParameter); return Err(ResultCode::ErrorBadParameter);
} }
@ -72,7 +77,7 @@ impl ToString for Locator {
if ztcore::ZT_Locator_toString(self.capi, buf.as_mut_ptr() as *mut c_char, buf.len() as c_int).is_null() { if ztcore::ZT_Locator_toString(self.capi, buf.as_mut_ptr() as *mut c_char, buf.len() as c_int).is_null() {
return String::from("(invalid)"); return String::from("(invalid)");
} }
return String::from(CStr::from_bytes_with_nul(buf.as_ref()).unwrap().to_str().unwrap()); return cstr_to_string(buf.as_ptr() as *const c_char, 4096);
} }
} }
} }

View file

@ -8,15 +8,16 @@ use std::sync::*;
use std::sync::atomic::*; use std::sync::atomic::*;
use std::time::Duration; use std::time::Duration;
use serde::{Deserialize, Serialize};
use num_traits::FromPrimitive; use num_traits::FromPrimitive;
use socket2::SockAddr;
use crate::*; use crate::*;
use crate::bindings::capi as ztcore; use crate::bindings::capi as ztcore;
use crate::inetaddress::InetAddress;
const NODE_BACKGROUND_MIN_DELAY: i64 = 250; const NODE_BACKGROUND_MIN_DELAY: i64 = 250;
#[allow(non_snake_case)] #[derive(Serialize, Deserialize)]
pub struct NodeStatus { pub struct NodeStatus {
pub address: Address, pub address: Address,
pub identity: Identity, pub identity: Identity,
@ -110,7 +111,7 @@ extern "C" fn zt_wire_packet_send_function(
uptr: *mut c_void, uptr: *mut c_void,
tptr: *mut c_void, tptr: *mut c_void,
local_socket: i64, local_socket: i64,
sock_addr: *const ztcore::sockaddr_storage, sock_addr: *const ztcore::ZT_InetAddress,
data: *const c_void, data: *const c_void,
data_size: c_uint, data_size: c_uint,
packet_ttl: c_uint packet_ttl: c_uint
@ -124,7 +125,7 @@ extern "C" fn zt_path_check_function(
address: u64, address: u64,
identity: *const ztcore::ZT_Identity, identity: *const ztcore::ZT_Identity,
local_socket: i64, local_socket: i64,
sock_addr: *const ztcore::sockaddr_storage sock_addr: *const ztcore::ZT_InetAddress
) {} ) {}
#[no_mangle] #[no_mangle]
@ -135,7 +136,7 @@ extern "C" fn zt_path_lookup_function(
address: u64, address: u64,
identity: *const ztcore::ZT_Identity, identity: *const ztcore::ZT_Identity,
sock_family: c_int, sock_family: c_int,
sock_addr: *mut ztcore::sockaddr_storage sock_addr: *mut ztcore::ZT_InetAddress
) {} ) {}
impl Node { impl Node {
@ -248,11 +249,11 @@ impl Node {
} }
#[inline(always)] #[inline(always)]
pub fn process_wire_packet(&self, local_socket: i64, remote_address: &SockAddr, data: &mut Buffer) -> ResultCode { pub fn process_wire_packet<A>(&self, local_socket: i64, remote_address: &InetAddress, data: &mut Buffer) -> ResultCode {
let current_time = self.now.get(); let current_time = self.now.get();
let mut next_task_deadline: i64 = current_time; let mut next_task_deadline: i64 = current_time;
unsafe { unsafe {
return ResultCode::from_u32(ztcore::ZT_Node_processWirePacket(self.capi.get(), null_mut(), current_time, local_socket, remote_address.as_ptr() as *const ztcore::sockaddr_storage, data.zt_core_buf as *const c_void, data.data_size as u32, 1, &mut next_task_deadline as *mut i64) as u32).unwrap_or(ResultCode::ErrorInternalNonFatal); return ResultCode::from_u32(ztcore::ZT_Node_processWirePacket(self.capi.get(), null_mut(), current_time, local_socket, remote_address.as_ptr() as *const ztcore::ZT_InetAddress, data.zt_core_buf as *const c_void, data.data_size as u32, 1, &mut next_task_deadline as *mut i64) as u32).unwrap_or(ResultCode::ErrorInternalNonFatal);
} }
} }

View file

@ -1,20 +1,75 @@
use std::ffi::CStr;
use std::mem::{size_of, transmute, zeroed}; use std::mem::{size_of, transmute, zeroed};
use std::os::raw::{c_void, c_char};
use serde::{Deserialize, Serialize};
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::FromPrimitive; use num_traits::FromPrimitive;
use socket2::SockAddr;
use crate::*; use crate::*;
use crate::bindings::capi as ztcore; use crate::bindings::capi as ztcore;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#[derive(FromPrimitive,ToPrimitive)] #[derive(FromPrimitive,ToPrimitive)]
pub enum VirtualNetworkType { pub enum VirtualNetworkType {
Private = ztcore::ZT_VirtualNetworkType_ZT_NETWORK_TYPE_PRIVATE as isize, Private = ztcore::ZT_VirtualNetworkType_ZT_NETWORK_TYPE_PRIVATE as isize,
Public = ztcore::ZT_VirtualNetworkType_ZT_NETWORK_TYPE_PUBLIC as isize Public = ztcore::ZT_VirtualNetworkType_ZT_NETWORK_TYPE_PUBLIC as isize
} }
impl VirtualNetworkType {
pub fn to_str(&self) -> &str {
match *self {
//VirtualNetworkType::Private => "PRIVATE",
VirtualNetworkType::Public => "PUBLIC",
_ => "PRIVATE"
}
}
}
impl From<&str> for VirtualNetworkType {
fn from(s: &str) -> VirtualNetworkType {
match s.to_ascii_lowercase().as_str() {
//"requesting_configuration" | "requestingconfiguration" => VirtualNetworkStatus::RequestingConfiguration,
"public" => VirtualNetworkType::Public,
_ => VirtualNetworkType::Private
}
}
}
impl ToString for VirtualNetworkType {
#[inline(always)]
fn to_string(&self) -> String {
String::from(self.to_str())
}
}
impl serde::Serialize for VirtualNetworkType {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer {
serializer.serialize_str(self.to_str())
}
}
struct VirtualNetworkTypeVisitor;
impl<'de> serde::de::Visitor<'de> for VirtualNetworkTypeVisitor {
type Value = VirtualNetworkType;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("VirtualNetworkType value in string form")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> where E: serde::de::Error {
Ok(VirtualNetworkType::from(s))
}
}
impl<'de> serde::Deserialize<'de> for VirtualNetworkType {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de> {
deserializer.deserialize_str(VirtualNetworkTypeVisitor)
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#[derive(FromPrimitive,ToPrimitive)] #[derive(FromPrimitive,ToPrimitive)]
pub enum VirtualNetworkRuleType { pub enum VirtualNetworkRuleType {
ActionDrop = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_ACTION_DROP as isize, ActionDrop = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_ACTION_DROP as isize,
@ -54,6 +109,8 @@ pub enum VirtualNetworkRuleType {
MatchIntegerRange = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_INTEGER_RANGE as isize MatchIntegerRange = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_INTEGER_RANGE as isize
} }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#[derive(FromPrimitive,ToPrimitive)] #[derive(FromPrimitive,ToPrimitive)]
pub enum VirtualNetworkConfigOperation { pub enum VirtualNetworkConfigOperation {
Up = ztcore::ZT_VirtualNetworkConfigOperation_ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP as isize, Up = ztcore::ZT_VirtualNetworkConfigOperation_ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP as isize,
@ -62,6 +119,8 @@ pub enum VirtualNetworkConfigOperation {
Destroy = ztcore::ZT_VirtualNetworkConfigOperation_ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY as isize Destroy = ztcore::ZT_VirtualNetworkConfigOperation_ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY as isize
} }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#[derive(FromPrimitive,ToPrimitive)] #[derive(FromPrimitive,ToPrimitive)]
pub enum VirtualNetworkStatus { pub enum VirtualNetworkStatus {
RequestingConfiguration = ztcore::ZT_VirtualNetworkStatus_ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION as isize, RequestingConfiguration = ztcore::ZT_VirtualNetworkStatus_ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION as isize,
@ -70,14 +129,73 @@ pub enum VirtualNetworkStatus {
NotFound = ztcore::ZT_VirtualNetworkStatus_ZT_NETWORK_STATUS_NOT_FOUND as isize NotFound = ztcore::ZT_VirtualNetworkStatus_ZT_NETWORK_STATUS_NOT_FOUND as isize
} }
impl VirtualNetworkStatus {
pub fn to_str(&self) -> &str {
match *self {
VirtualNetworkStatus::RequestingConfiguration => "REQUESTING_CONFIGURATION",
VirtualNetworkStatus::Ok => "OK",
VirtualNetworkStatus::AccessDenied => "ACCESS_DENIED",
VirtualNetworkStatus::NotFound => "NOT_FOUND"
}
}
}
impl From<&str> for VirtualNetworkStatus {
fn from(s: &str) -> VirtualNetworkStatus {
match s.to_ascii_lowercase().as_str() {
//"requesting_configuration" | "requestingconfiguration" => VirtualNetworkStatus::RequestingConfiguration,
"ok" => VirtualNetworkStatus::Ok,
"access_denied" | "accessdenied" => VirtualNetworkStatus::AccessDenied,
"not_found" | "notfound" => VirtualNetworkStatus::NotFound,
_ => VirtualNetworkStatus::RequestingConfiguration
}
}
}
impl ToString for VirtualNetworkStatus {
#[inline(always)]
fn to_string(&self) -> String {
String::from(self.to_str())
}
}
impl serde::Serialize for VirtualNetworkStatus {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer {
serializer.serialize_str(self.to_str())
}
}
struct VirtualNetworkStatusVisitor;
impl<'de> serde::de::Visitor<'de> for VirtualNetworkStatusVisitor {
type Value = VirtualNetworkStatus;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("VirtualNetworkStatus value in string form")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> where E: serde::de::Error {
Ok(VirtualNetworkStatus::from(s))
}
}
impl<'de> serde::Deserialize<'de> for VirtualNetworkStatus {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de> {
deserializer.deserialize_str(VirtualNetworkStatusVisitor)
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#[derive(Serialize, Deserialize)]
pub struct VirtualNetworkRoute { pub struct VirtualNetworkRoute {
pub target: Option<SockAddr>, pub target: Option<InetAddress>,
pub via: Option<SockAddr>, pub via: Option<InetAddress>,
pub flags: u16, pub flags: u16,
pub metric: u16 pub metric: u16
} }
#[allow(non_snake_case)] #[derive(Serialize, Deserialize)]
pub struct VirtualNetworkConfig { pub struct VirtualNetworkConfig {
pub nwid: NetworkId, pub nwid: NetworkId,
pub mac: MAC, pub mac: MAC,
@ -92,63 +210,45 @@ pub struct VirtualNetworkConfig {
#[serde(rename = "netconfRevision")] #[serde(rename = "netconfRevision")]
pub netconf_revision: u64, pub netconf_revision: u64,
#[serde(rename = "assignedAddresses")] #[serde(rename = "assignedAddresses")]
pub assigned_addresses: Vec<SockAddr>, pub assigned_addresses: Vec<InetAddress>,
pub routes: Vec<VirtualNetworkRoute> pub routes: Vec<VirtualNetworkRoute>
} }
const SIZEOF_SOCKADDR_IN: ztcore::socklen_t = size_of::<ztcore::sockaddr_in>() as ztcore::socklen_t;
const SIZEOF_SOCKADDR_IN6: ztcore::socklen_t = size_of::<ztcore::sockaddr_in6>() as ztcore::socklen_t;
/// Obtain a socket2::SockAddr from a C struct sockaddr_storage as used in the ZeroTier core.
pub(crate) fn sockaddr_from_capi(ss: &ztcore::sockaddr_storage) -> Option<SockAddr> {
// The transmute() calls in here are to work around the fact that socket2
// uses sockaddr_storage from the libc crate, while ztcore uses it as
// generated from bindgen from the system headers. It's the same thing but
// Rust's type system doesn't know that.
match ss.ss_family as u32 {
ztcore::AF_INET => { unsafe { Some(SockAddr::from_raw_parts(transmute(ss as *const ztcore::sockaddr_storage), transmute(SIZEOF_SOCKADDR_IN))) } },
ztcore::AF_INET6 => { unsafe { Some(SockAddr::from_raw_parts(transmute(ss as *const ztcore::sockaddr_storage), transmute(SIZEOF_SOCKADDR_IN6))) } },
_ => None
}
}
impl VirtualNetworkConfig { impl VirtualNetworkConfig {
pub(crate) fn new_from_capi(vnc: &ztcore::ZT_VirtualNetworkConfig) -> VirtualNetworkConfig { pub(crate) fn new_from_capi(vnc: &ztcore::ZT_VirtualNetworkConfig) -> VirtualNetworkConfig {
unsafe { let mut aa: Vec<InetAddress> = Vec::new();
let mut aa: Vec<SockAddr> = Vec::new(); let saptr = vnc.assignedAddresses.as_ptr();
let saptr = vnc.assignedAddresses.as_ptr(); for i in 0..vnc.assignedAddressCount as isize {
for i in 0..vnc.assignedAddressCount as isize { let a = InetAddress::new_from_capi(unsafe { *saptr.offset(i) });
let sa = sockaddr_from_capi(&*saptr.offset(i)); if a.is_some() {
if sa.is_some() { aa.push(a.unwrap());
aa.push(sa.unwrap());
}
} }
}
let mut rts: Vec<VirtualNetworkRoute> = Vec::new(); let mut rts: Vec<VirtualNetworkRoute> = Vec::new();
let rtptr = vnc.routes.as_ptr(); let rtptr = vnc.routes.as_ptr();
for i in 0..vnc.routeCount as isize { for i in 0..vnc.routeCount as isize {
let r = *rtptr.offset(i); let r = unsafe { *rtptr.offset(i) };
rts.push(VirtualNetworkRoute{ rts.push(VirtualNetworkRoute{
target: sockaddr_from_capi(&r.target), target: InetAddress::new_from_capi(r.target),
via: sockaddr_from_capi(&r.via), via: InetAddress::new_from_capi(r.via),
flags: r.flags, flags: r.flags,
metric: r.metric metric: r.metric
}) })
} }
return VirtualNetworkConfig{ return VirtualNetworkConfig{
nwid: NetworkId(vnc.nwid), nwid: NetworkId(vnc.nwid),
mac: MAC(vnc.mac), mac: MAC(vnc.mac),
name: String::from(CStr::from_ptr(vnc.name.as_ptr() as *const c_char).to_str().unwrap_or("")), name: unsafe { cstr_to_string(vnc.name.as_ptr(), vnc.name.len() as isize) },
status: FromPrimitive::from_u32(vnc.status as u32).unwrap(), status: FromPrimitive::from_u32(vnc.status as u32).unwrap(),
type_: FromPrimitive::from_u32(vnc.type_ as u32).unwrap(), type_: FromPrimitive::from_u32(vnc.type_ as u32).unwrap(),
mtu: vnc.mtu as u32, mtu: vnc.mtu as u32,
bridge: vnc.bridge != 0, bridge: vnc.bridge != 0,
broadcast_enabled: vnc.broadcastEnabled != 0, broadcast_enabled: vnc.broadcastEnabled != 0,
netconf_revision: vnc.netconfRevision as u64, netconf_revision: vnc.netconfRevision as u64,
assigned_addresses: aa, assigned_addresses: aa,
routes: rts routes: rts
}
} }
} }
} }