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,
int64_t now,
int64_t localSocket,
const struct sockaddr_storage *remoteAddress,
const ZT_InetAddress *remoteAddress,
const void *packetData,
unsigned int packetLength,
int isZtBuffer,
@ -108,7 +108,7 @@ enum ZT_ResultCode ZT_Node_processWirePacket(
{
try {
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) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
} 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"

View file

@ -14,9 +14,13 @@
#ifndef 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"
/**

View file

@ -19,6 +19,10 @@
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::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;
@ -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);
switch (ip >> 24U) {
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:
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:
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 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)
@ -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 0x37: //return IP_SCOPE_PSEUDOPRIVATE; // 55.0.0.0/8 (US DoD)
case 0x38: // 56.0.0.0/8 (US Postal Service)
return IP_SCOPE_PSEUDOPRIVATE;
return ZT_IP_SCOPE_PSEUDOPRIVATE;
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;
case 0x7f:
return IP_SCOPE_LOOPBACK; // 127.0.0.0/8
return ZT_IP_SCOPE_LOOPBACK; // 127.0.0.0/8
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;
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;
case 0xc0:
if ((ip & 0xffff0000) == 0xc0a80000) return IP_SCOPE_PRIVATE; // 192.168.0.0/16
if ((ip & 0xffffff00) == 0xc0000200) return IP_SCOPE_PRIVATE; // 192.0.2.0/24
if ((ip & 0xffff0000) == 0xc0a80000) return ZT_IP_SCOPE_PRIVATE; // 192.168.0.0/16
if ((ip & 0xffffff00) == 0xc0000200) return ZT_IP_SCOPE_PRIVATE; // 192.0.2.0/24
break;
case 0xc6:
if ((ip & 0xfffe0000) == 0xc6120000) return IP_SCOPE_PRIVATE; // 198.18.0.0/15
if ((ip & 0xffffff00) == 0xc6336400) return IP_SCOPE_PRIVATE; // 198.51.100.0/24
if ((ip & 0xfffe0000) == 0xc6120000) return ZT_IP_SCOPE_PRIVATE; // 198.18.0.0/15
if ((ip & 0xffffff00) == 0xc6336400) return ZT_IP_SCOPE_PRIVATE; // 198.51.100.0/24
break;
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;
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) {
case 0xe:
return IP_SCOPE_MULTICAST; // 224.0.0.0/4
return ZT_IP_SCOPE_MULTICAST; // 224.0.0.0/4
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: {
const uint8_t *const ip = as.sa_in6.sin6_addr.s6_addr;
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)) {
unsigned int k = 2;
while ((!ip[k]) && (k < 15)) ++k;
if ((k == 15) && (ip[15] == 0x01))
return IP_SCOPE_LOOPBACK; // fe80::1/128
else return IP_SCOPE_LINK_LOCAL; // fe80::/10
return ZT_IP_SCOPE_LOOPBACK; // fe80::1/128
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;
while ((!ip[k]) && (k < 15)) ++k;
if (k == 15) { // all 0's except last byte
if (ip[15] == 0x01) return IP_SCOPE_LOOPBACK; // ::1/128
if (ip[15] == 0x00) return IP_SCOPE_NONE; // ::/128
if (ip[15] == 0x01) return ZT_IP_SCOPE_LOOPBACK; // ::1/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

View file

@ -59,17 +59,7 @@ public:
* MUST remain that way or Path must be changed to reflect. Also be sure
* to change ZT_INETADDRESS_MAX_SCOPE if the max changes.
*/
enum 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.
};
typedef ZT_InetAddress_IpScope IpScope;
// Hasher for unordered sets and maps in C++11
struct Hasher
@ -130,52 +120,52 @@ public:
ZT_INLINE InetAddress &operator=(const sockaddr_in &sa) noexcept
{
memoryZero(this);
as.sa_in = sa;
return *this;
}
ZT_INLINE InetAddress &operator=(const sockaddr_in *sa) noexcept
{
memoryZero(this);
if (sa)
as.sa_in = *sa;
else memoryZero(this);
return *this;
}
ZT_INLINE InetAddress &operator=(const sockaddr_in6 &sa) noexcept
{
memoryZero(this);
as.sa_in6 = sa;
return *this;
}
ZT_INLINE InetAddress &operator=(const sockaddr_in6 *sa) noexcept
{
memoryZero(this);
if (sa)
as.sa_in6 = *sa;
else memoryZero(this);
return *this;
}
ZT_INLINE InetAddress &operator=(const sockaddr &sa) noexcept
{
memoryZero(this);
if (sa.sa_family == AF_INET)
as.sa_in = *reinterpret_cast<const sockaddr_in *>(&sa);
else if (sa.sa_family == AF_INET6)
as.sa_in6 = *reinterpret_cast<const sockaddr_in6 *>(&sa);
else memoryZero(this);
return *this;
}
ZT_INLINE InetAddress &operator=(const sockaddr *sa) noexcept
{
memoryZero(this);
if (sa) {
if (sa->sa_family == AF_INET)
as.sa_in = *reinterpret_cast<const sockaddr_in *>(sa);
else if (sa->sa_family == AF_INET6)
as.sa_in6 = *reinterpret_cast<const sockaddr_in6 *>(sa);
else memoryZero(this);
} else {
memoryZero(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
{ 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
{ 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
{ 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
{ 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
{ 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
{ 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
{ 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
#endif

View file

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

View file

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

View file

@ -58,6 +58,13 @@
#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 <stdlib.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();
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;
Mutex::Lock l(m_phy_l);

View file

@ -18,19 +18,6 @@
#ifndef 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 <stdlib.h>
@ -281,6 +268,34 @@ typedef void ZT_Identity;
*/
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)
*/
@ -1311,12 +1326,12 @@ typedef struct
/**
* 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)
*/
struct sockaddr_storage via;
ZT_InetAddress via;
/**
* Route flags
@ -1439,7 +1454,7 @@ typedef struct
* This is only used for ZeroTier-managed address assignments sent by the
* 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
@ -1471,7 +1486,7 @@ typedef struct
/**
* 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
@ -1491,6 +1506,15 @@ typedef struct
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
*/
@ -1510,6 +1534,7 @@ typedef struct
* IPv6 address, for all ZT_ENDPOINT_TYPE_IP types if family is AF_INET6
*/
struct sockaddr_in6 sa_in6;
#endif
/**
* 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 *, /* Thread ptr */
int64_t, /* Local socket */
const struct sockaddr_storage *, /* Remote address */
const ZT_InetAddress *, /* Remote address */
const void *, /* Packet data */
unsigned int, /* Packet length */
unsigned int); /* TTL or 0 to use default */
@ -1909,7 +1934,7 @@ typedef int (*ZT_PathCheckFunction)(
uint64_t, /* ZeroTier address */
const ZT_Identity *, /* Full identity of node */
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
@ -1934,7 +1959,7 @@ typedef int (*ZT_PathLookupFunction)(
uint64_t, /* ZeroTier address (40 bits) */
const ZT_Identity *, /* Full identity of node */
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,
int64_t now,
int64_t localSocket,
const struct sockaddr_storage *remoteAddress,
const ZT_InetAddress *remoteAddress,
const void *packetData,
unsigned int packetLength,
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
}
#endif

View file

@ -6,12 +6,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "hex"
version = "0.4.2"
@ -24,12 +18,6 @@ version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
[[package]]
name = "libc"
version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
[[package]]
name = "num-derive"
version = "0.3.3"
@ -77,7 +65,6 @@ dependencies = [
"num-traits",
"serde",
"serde_json",
"socket2",
]
[[package]]
@ -117,17 +104,6 @@ dependencies = [
"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]]
name = "syn"
version = "1.0.54"
@ -144,25 +120,3 @@ name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
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>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
num-traits = "0.2.14"
num-derive = "0.3.3"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
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::os::raw::{c_char, c_int};
use std::os::raw::{c_char, c_int, c_void};
use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::FromPrimitive;
@ -35,9 +35,14 @@ impl Endpoint {
}
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 {
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 {
let epi = cep.assume_init();
return Ok(Endpoint{
@ -48,6 +53,18 @@ impl Endpoint {
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 {

View file

@ -1,7 +1,7 @@
use crate::*;
use crate::bindings::capi as ztcore;
use std::os::raw::{c_char, c_int};
use std::ffi::CStr;
use std::ffi::{CStr, CString};
use std::mem::MaybeUninit;
pub struct Fingerprint {
@ -19,9 +19,14 @@ impl Fingerprint {
}
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 {
let mut cfp: MaybeUninit<ztcore::ZT_Fingerprint> = MaybeUninit::uninit();
if ztcore::ZT_Fingerprint_fromString(cfp.as_mut_ptr(), s.as_ptr() as *const c_char) != 0 {
if ztcore::ZT_Fingerprint_fromString(cfp.as_mut_ptr(), cs.as_ptr()) != 0 {
let fp = cfp.assume_init();
return Ok(Fingerprint{
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() {
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::os::raw::*;
@ -49,7 +49,12 @@ impl Identity {
/// Construct from a string representation of this identity.
pub fn new_from_string(s: &str) -> Result<Identity, ResultCode> {
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() {
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 num_derive::{FromPrimitive, ToPrimitive};
@ -9,6 +11,7 @@ mod fingerprint;
mod endpoint;
mod certificate;
mod networkid;
mod inetaddress;
mod locator;
mod path;
mod peer;
@ -26,6 +29,7 @@ pub use fingerprint::Fingerprint;
pub use endpoint::*;
pub use certificate::*;
pub use networkid::NetworkId;
pub use inetaddress::*;
pub use locator::*;
pub use path::Path;
pub use peer::Peer;

View file

@ -1,7 +1,7 @@
use crate::*;
use crate::bindings::capi as ztcore;
use std::os::raw::{c_char, c_int, c_uint};
use std::ffi::CStr;
use std::ffi::CString;
pub struct Locator {
pub(crate) capi: *const ztcore::ZT_Locator,
@ -19,7 +19,12 @@ impl Locator {
pub fn new_from_string(s: &str) -> Result<Locator, ResultCode> {
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() {
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() {
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::time::Duration;
use serde::{Deserialize, Serialize};
use num_traits::FromPrimitive;
use socket2::SockAddr;
use crate::*;
use crate::bindings::capi as ztcore;
use crate::inetaddress::InetAddress;
const NODE_BACKGROUND_MIN_DELAY: i64 = 250;
#[allow(non_snake_case)]
#[derive(Serialize, Deserialize)]
pub struct NodeStatus {
pub address: Address,
pub identity: Identity,
@ -110,7 +111,7 @@ extern "C" fn zt_wire_packet_send_function(
uptr: *mut c_void,
tptr: *mut c_void,
local_socket: i64,
sock_addr: *const ztcore::sockaddr_storage,
sock_addr: *const ztcore::ZT_InetAddress,
data: *const c_void,
data_size: c_uint,
packet_ttl: c_uint
@ -124,7 +125,7 @@ extern "C" fn zt_path_check_function(
address: u64,
identity: *const ztcore::ZT_Identity,
local_socket: i64,
sock_addr: *const ztcore::sockaddr_storage
sock_addr: *const ztcore::ZT_InetAddress
) {}
#[no_mangle]
@ -135,7 +136,7 @@ extern "C" fn zt_path_lookup_function(
address: u64,
identity: *const ztcore::ZT_Identity,
sock_family: c_int,
sock_addr: *mut ztcore::sockaddr_storage
sock_addr: *mut ztcore::ZT_InetAddress
) {}
impl Node {
@ -248,11 +249,11 @@ impl Node {
}
#[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 mut next_task_deadline: i64 = current_time;
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::os::raw::{c_void, c_char};
use serde::{Deserialize, Serialize};
use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::FromPrimitive;
use socket2::SockAddr;
use crate::*;
use crate::bindings::capi as ztcore;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#[derive(FromPrimitive,ToPrimitive)]
pub enum VirtualNetworkType {
Private = ztcore::ZT_VirtualNetworkType_ZT_NETWORK_TYPE_PRIVATE 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)]
pub enum VirtualNetworkRuleType {
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
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#[derive(FromPrimitive,ToPrimitive)]
pub enum VirtualNetworkConfigOperation {
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
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#[derive(FromPrimitive,ToPrimitive)]
pub enum VirtualNetworkStatus {
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
}
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 target: Option<SockAddr>,
pub via: Option<SockAddr>,
pub target: Option<InetAddress>,
pub via: Option<InetAddress>,
pub flags: u16,
pub metric: u16
}
#[allow(non_snake_case)]
#[derive(Serialize, Deserialize)]
pub struct VirtualNetworkConfig {
pub nwid: NetworkId,
pub mac: MAC,
@ -92,63 +210,45 @@ pub struct VirtualNetworkConfig {
#[serde(rename = "netconfRevision")]
pub netconf_revision: u64,
#[serde(rename = "assignedAddresses")]
pub assigned_addresses: Vec<SockAddr>,
pub assigned_addresses: Vec<InetAddress>,
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 {
pub(crate) fn new_from_capi(vnc: &ztcore::ZT_VirtualNetworkConfig) -> VirtualNetworkConfig {
unsafe {
let mut aa: Vec<SockAddr> = Vec::new();
let saptr = vnc.assignedAddresses.as_ptr();
for i in 0..vnc.assignedAddressCount as isize {
let sa = sockaddr_from_capi(&*saptr.offset(i));
if sa.is_some() {
aa.push(sa.unwrap());
}
let mut aa: Vec<InetAddress> = Vec::new();
let saptr = vnc.assignedAddresses.as_ptr();
for i in 0..vnc.assignedAddressCount as isize {
let a = InetAddress::new_from_capi(unsafe { *saptr.offset(i) });
if a.is_some() {
aa.push(a.unwrap());
}
}
let mut rts: Vec<VirtualNetworkRoute> = Vec::new();
let rtptr = vnc.routes.as_ptr();
for i in 0..vnc.routeCount as isize {
let r = *rtptr.offset(i);
rts.push(VirtualNetworkRoute{
target: sockaddr_from_capi(&r.target),
via: sockaddr_from_capi(&r.via),
flags: r.flags,
metric: r.metric
})
}
let mut rts: Vec<VirtualNetworkRoute> = Vec::new();
let rtptr = vnc.routes.as_ptr();
for i in 0..vnc.routeCount as isize {
let r = unsafe { *rtptr.offset(i) };
rts.push(VirtualNetworkRoute{
target: InetAddress::new_from_capi(r.target),
via: InetAddress::new_from_capi(r.via),
flags: r.flags,
metric: r.metric
})
}
return VirtualNetworkConfig{
nwid: NetworkId(vnc.nwid),
mac: MAC(vnc.mac),
name: String::from(CStr::from_ptr(vnc.name.as_ptr() as *const c_char).to_str().unwrap_or("")),
status: FromPrimitive::from_u32(vnc.status as u32).unwrap(),
type_: FromPrimitive::from_u32(vnc.type_ as u32).unwrap(),
mtu: vnc.mtu as u32,
bridge: vnc.bridge != 0,
broadcast_enabled: vnc.broadcastEnabled != 0,
netconf_revision: vnc.netconfRevision as u64,
assigned_addresses: aa,
routes: rts
}
return VirtualNetworkConfig{
nwid: NetworkId(vnc.nwid),
mac: MAC(vnc.mac),
name: unsafe { cstr_to_string(vnc.name.as_ptr(), vnc.name.len() as isize) },
status: FromPrimitive::from_u32(vnc.status as u32).unwrap(),
type_: FromPrimitive::from_u32(vnc.type_ as u32).unwrap(),
mtu: vnc.mtu as u32,
bridge: vnc.bridge != 0,
broadcast_enabled: vnc.broadcastEnabled != 0,
netconf_revision: vnc.netconfRevision as u64,
assigned_addresses: aa,
routes: rts
}
}
}