More Rust plumbing...

This commit is contained in:
Adam Ierymenko 2020-12-29 22:49:43 -05:00
parent 8d0d479662
commit 927344f197
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
7 changed files with 401 additions and 184 deletions

View file

@ -23,10 +23,12 @@
#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>
@ -266,7 +268,7 @@ extern "C" {
enum ZT_IdentityType
{
ZT_IDENTITY_TYPE_C25519 = 0, /* C25519/Ed25519 */
ZT_IDENTITY_TYPE_P384 = 1 /* Combined C25519/NIST-P-384 key */
ZT_IDENTITY_TYPE_P384 = 1 /* Combined C25519/NIST-P-384 key */
};
/**
@ -651,12 +653,12 @@ typedef struct
*/
enum ZT_CredentialType
{
ZT_CREDENTIAL_TYPE_NULL = 0,
ZT_CREDENTIAL_TYPE_COM = 1,
ZT_CREDENTIAL_TYPE_CAPABILITY = 2,
ZT_CREDENTIAL_TYPE_TAG = 3,
ZT_CREDENTIAL_TYPE_COO = 4,
ZT_CREDENTIAL_TYPE_REVOCATION = 6
ZT_CREDENTIAL_TYPE_NULL = 0,
ZT_CREDENTIAL_TYPE_COM = 1,
ZT_CREDENTIAL_TYPE_CAPABILITY = 2,
ZT_CREDENTIAL_TYPE_TAG = 3,
ZT_CREDENTIAL_TYPE_COO = 4,
ZT_CREDENTIAL_TYPE_REVOCATION = 6
};
/**
@ -667,15 +669,15 @@ enum ZT_CredentialType
*/
enum ZT_EndpointType
{
ZT_ENDPOINT_TYPE_NIL = 0, /* Nil/empty endpoint */
ZT_ENDPOINT_TYPE_ZEROTIER = 1, /* ZeroTier relaying (address+fingerprint) */
ZT_ENDPOINT_TYPE_ETHERNET = 2, /* Ethernet with ethertype 0x9993 */
ZT_ENDPOINT_TYPE_WIFI_DIRECT = 3, /* Ethernet using WiFi direct */
ZT_ENDPOINT_TYPE_BLUETOOTH = 4, /* Bluetooth (same address type as Ethernet) */
ZT_ENDPOINT_TYPE_IP = 5, /* Naked IP (protocol 193) */
ZT_ENDPOINT_TYPE_IP_UDP = 6, /* IP/UDP */
ZT_ENDPOINT_TYPE_IP_TCP = 7, /* IP/TCP */
ZT_ENDPOINT_TYPE_IP_HTTP = 8 /* IP/HTTP encapsulation */
ZT_ENDPOINT_TYPE_NIL = 0, /* Nil/empty endpoint */
ZT_ENDPOINT_TYPE_ZEROTIER = 1, /* ZeroTier relaying (address+fingerprint) */
ZT_ENDPOINT_TYPE_ETHERNET = 2, /* Ethernet with ethertype 0x9993 */
ZT_ENDPOINT_TYPE_WIFI_DIRECT = 3, /* Ethernet using WiFi direct */
ZT_ENDPOINT_TYPE_BLUETOOTH = 4, /* Bluetooth (same address type as Ethernet) */
ZT_ENDPOINT_TYPE_IP = 5, /* Naked IP (protocol 193) */
ZT_ENDPOINT_TYPE_IP_UDP = 6, /* IP/UDP */
ZT_ENDPOINT_TYPE_IP_TCP = 7, /* IP/TCP */
ZT_ENDPOINT_TYPE_IP_HTTP = 8 /* IP/HTTP encapsulation */
};
/**
@ -705,15 +707,15 @@ enum ZT_EndpointType
*/
enum ZT_TraceEventType
{
ZT_TRACE_UNEXPECTED_ERROR = 0,
ZT_TRACE_UNEXPECTED_ERROR = 0,
ZT_TRACE_VL1_RESETTING_PATHS_IN_SCOPE = 1,
ZT_TRACE_VL1_TRYING_NEW_PATH = 2,
ZT_TRACE_VL1_LEARNED_NEW_PATH = 3,
ZT_TRACE_VL1_INCOMING_PACKET_DROPPED = 4,
ZT_TRACE_VL2_OUTGOING_FRAME_DROPPED = 100,
ZT_TRACE_VL2_INCOMING_FRAME_DROPPED = 101,
ZT_TRACE_VL1_TRYING_NEW_PATH = 2,
ZT_TRACE_VL1_LEARNED_NEW_PATH = 3,
ZT_TRACE_VL1_INCOMING_PACKET_DROPPED = 4,
ZT_TRACE_VL2_OUTGOING_FRAME_DROPPED = 100,
ZT_TRACE_VL2_INCOMING_FRAME_DROPPED = 101,
ZT_TRACE_VL2_NETWORK_CONFIG_REQUESTED = 102,
ZT_TRACE_VL2_NETWORK_FILTER = 103
ZT_TRACE_VL2_NETWORK_FILTER = 103
};
/**
@ -721,15 +723,15 @@ enum ZT_TraceEventType
*/
enum ZT_TracePacketDropReason
{
ZT_TRACE_PACKET_DROP_REASON_UNSPECIFIED = 0,
ZT_TRACE_PACKET_DROP_REASON_PEER_TOO_OLD = 1,
ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET = 2,
ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED = 3,
ZT_TRACE_PACKET_DROP_REASON_RATE_LIMIT_EXCEEDED = 4,
ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT = 5,
ZT_TRACE_PACKET_DROP_REASON_UNSPECIFIED = 0,
ZT_TRACE_PACKET_DROP_REASON_PEER_TOO_OLD = 1,
ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET = 2,
ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED = 3,
ZT_TRACE_PACKET_DROP_REASON_RATE_LIMIT_EXCEEDED = 4,
ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT = 5,
ZT_TRACE_PACKET_DROP_REASON_INVALID_COMPRESSED_DATA = 6,
ZT_TRACE_PACKET_DROP_REASON_UNRECOGNIZED_VERB = 7,
ZT_TRACE_PACKET_DROP_REASON_REPLY_NOT_EXPECTED = 8
ZT_TRACE_PACKET_DROP_REASON_UNRECOGNIZED_VERB = 7,
ZT_TRACE_PACKET_DROP_REASON_REPLY_NOT_EXPECTED = 8
};
/**
@ -737,14 +739,14 @@ enum ZT_TracePacketDropReason
*/
enum ZT_TraceFrameDropReason
{
ZT_TRACE_FRAME_DROP_REASON_UNSPECIFIED = 0,
ZT_TRACE_FRAME_DROP_REASON_BRIDGING_NOT_ALLOWED_REMOTE = 1,
ZT_TRACE_FRAME_DROP_REASON_BRIDGING_NOT_ALLOWED_LOCAL = 2,
ZT_TRACE_FRAME_DROP_REASON_MULTICAST_DISABLED = 3,
ZT_TRACE_FRAME_DROP_REASON_BROADCAST_DISABLED = 4,
ZT_TRACE_FRAME_DROP_REASON_FILTER_BLOCKED = 5,
ZT_TRACE_FRAME_DROP_REASON_UNSPECIFIED = 0,
ZT_TRACE_FRAME_DROP_REASON_BRIDGING_NOT_ALLOWED_REMOTE = 1,
ZT_TRACE_FRAME_DROP_REASON_BRIDGING_NOT_ALLOWED_LOCAL = 2,
ZT_TRACE_FRAME_DROP_REASON_MULTICAST_DISABLED = 3,
ZT_TRACE_FRAME_DROP_REASON_BROADCAST_DISABLED = 4,
ZT_TRACE_FRAME_DROP_REASON_FILTER_BLOCKED = 5,
ZT_TRACE_FRAME_DROP_REASON_FILTER_BLOCKED_AT_BRIDGE_REPLICATION = 6,
ZT_TRACE_FRAME_DROP_REASON_PERMISSION_DENIED = 7
ZT_TRACE_FRAME_DROP_REASON_PERMISSION_DENIED = 7
};
/**
@ -753,9 +755,9 @@ enum ZT_TraceFrameDropReason
enum ZT_TraceCredentialRejectionReason
{
ZT_TRACE_CREDENTIAL_REJECTION_REASON_SIGNATURE_VERIFICATION_FAILED = 1,
ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED = 2,
ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST = 3,
ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID = 4
ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED = 2,
ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST = 3,
ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID = 4
};
#define ZT_TRACE_FIELD_TYPE "t"
@ -1176,11 +1178,13 @@ typedef struct
/**
* Union containing the value of this rule -- which field is used depends on 't'
*/
union {
union
{
/**
* IPv6 address in big-endian / network byte order and netmask bits
*/
struct {
struct
{
uint8_t ip[16];
uint8_t mask;
} ipv6;
@ -1188,7 +1192,8 @@ typedef struct
/**
* IPv4 address in big-endian / network byte order
*/
struct {
struct
{
uint32_t ip;
uint8_t mask;
} ipv4;
@ -1200,7 +1205,8 @@ typedef struct
* the range is +/- INT32_MAX. It's packed this way so it fits in 16
* bytes and doesn't enlarge the overall size of this union.
*/
struct {
struct
{
uint64_t start; /* integer range start */
uint32_t end; /* end of integer range (relative to start, inclusive, 0 for equality w/start) */
uint16_t idx; /* index in packet of integer */
@ -1260,7 +1266,8 @@ typedef struct
/**
* IP type of service a.k.a. DSCP field
*/
struct {
struct
{
uint8_t mask;
uint8_t value[2];
} ipTos;
@ -1273,7 +1280,8 @@ typedef struct
/**
* ICMP type and code
*/
struct {
struct
{
uint8_t type; /* ICMP type, always matched */
uint8_t code; /* ICMP code if matched */
uint8_t flags; /* flag 0x01 means also match code, otherwise only match type */
@ -1282,7 +1290,8 @@ typedef struct
/**
* For tag-related rules
*/
struct {
struct
{
uint32_t id;
uint32_t value;
} tag;
@ -1290,7 +1299,8 @@ typedef struct
/**
* Destinations for TEE and REDIRECT
*/
struct {
struct
{
uint64_t address;
uint32_t flags;
uint16_t length;
@ -1458,6 +1468,7 @@ typedef struct
typedef struct
{
void (*freeFunction)(const void *);
ZT_VirtualNetworkConfig *networks;
unsigned long networkCount;
} ZT_VirtualNetworkList;
@ -1488,7 +1499,8 @@ typedef struct
*/
enum ZT_EndpointType type;
union {
union
{
/**
* Socket address generic buffer
*/
@ -1651,6 +1663,7 @@ typedef struct
typedef struct
{
void (*freeFunction)(const void *);
ZT_Peer *peers;
unsigned long peerCount;
} ZT_PeerList;

View file

@ -1,9 +1,13 @@
use std::ffi::CStr;
use std::intrinsics::write_bytes;
use std::mem::{MaybeUninit, zeroed};
use std::os::raw::{c_char, c_void};
use std::ptr::copy_nonoverlapping;
use serde::{Deserialize, Serialize};
use crate::*;
use crate::bindings::capi as ztcore;
use std::ffi::CStr;
use std::ptr::copy_nonoverlapping;
use std::os::raw::{c_char, c_void};
use serde::{Deserialize, Serialize};
/// Maximum length of a string in a certificate (mostly for the certificate name fields).
pub const CERTIFICATE_MAX_STRING_LENGTH: u32 = ztcore::ZT_CERTIFICATE_MAX_STRING_LENGTH;
@ -20,6 +24,76 @@ pub const CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE: u32 = ztcore::ZT_CERTIFICA
/// Length of a private key corresponding to a NIST P-384 unique ID.
pub const CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE: u32 = ztcore::ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
pub struct CertificateSerialNo(pub [u8; 48]);
impl CertificateSerialNo {
pub fn new_from_string(s: &str) -> Result<CertificateSerialNo, ResultCode> {
let b = hex::decode(s);
if b.is_err() {
return Err(ResultCode::ErrorBadParameter);
}
return Ok(CertificateSerialNo::from(b.unwrap()));
}
}
impl From<Vec<u8>> for CertificateSerialNo {
fn from(v: Vec<u8>) -> CertificateSerialNo {
let mut l = v.len();
if l > 48 {
l = 48;
}
unsafe {
let mut r: [u8; 48] = MaybeUninit::uninit().assume_init();
copy_nonoverlapping(v.as_ptr(), r.as_mut_ptr(), l);
while l < 48 {
r[l] = 0;
l += 1;
}
return CertificateSerialNo(r);
}
}
}
impl ToString for CertificateSerialNo {
fn to_string(&self) -> String {
hex::encode(self.0)
}
}
impl serde::Serialize for CertificateSerialNo {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer {
serializer.serialize_str(self.to_string().as_str())
}
}
struct CertificateSerialNoVisitor;
impl<'de> serde::de::Visitor<'de> for CertificateSerialNoVisitor {
type Value = CertificateSerialNo;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("CertificateSerialNoVisitor value in string form")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> where E: serde::de::Error {
let id = CertificateSerialNo::new_from_string(s);
if id.is_err() {
return Err(serde::de::Error::invalid_value(serde::de::Unexpected::Str(s), &self));
}
return Ok(id.ok().unwrap() as Self::Value);
}
}
impl<'de> serde::Deserialize<'de> for CertificateSerialNo {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de> {
deserializer.deserialize_str(CertificateSerialNoVisitor)
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Type of certificate subject unique ID
#[derive(FromPrimitive,ToPrimitive)]
pub enum CertificateUniqueIdType {
@ -73,6 +147,8 @@ impl<'de> serde::Deserialize<'de> for CertificateUniqueIdType {
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Reasons a certificate may be rejected.
#[derive(FromPrimitive,ToPrimitive)]
pub enum CertificateError {
@ -138,8 +214,8 @@ pub struct CertificateIdentity {
#[derive(Serialize, Deserialize)]
pub struct CertificateSubjectUniqueIdSecret {
pub public: Box<[u8]>,
pub private: Box<[u8]>,
pub public: Vec<u8>,
pub private: Vec<u8>,
pub type_: CertificateUniqueIdType
}
@ -147,29 +223,29 @@ pub struct CertificateSubjectUniqueIdSecret {
#[derive(Serialize, Deserialize)]
pub struct CertificateSubject {
pub timestamp: i64,
pub identities: Box<[CertificateIdentity]>,
pub networks: Box<[CertificateNetwork]>,
pub certificates: Box<[Box<[u8]>]>,
pub updateURLs: Box<[String]>,
pub identities: Vec<CertificateIdentity>,
pub networks: Vec<CertificateNetwork>,
pub certificates: Vec<CertificateSerialNo>,
pub updateURLs: Vec<String>,
pub name: CertificateName,
pub uniqueId: Box<[u8]>,
pub uniqueIdProofSignature: Box<[u8]>
pub uniqueId: Vec<u8>,
pub uniqueIdProofSignature: Vec<u8>
}
#[allow(non_snake_case)]
#[derive(Serialize, Deserialize)]
pub struct Certificate {
pub serialNo: Box<[u8]>,
pub serialNo: CertificateSerialNo,
pub flags: u64,
pub timestamp: i64,
pub validity: [i64; 2],
pub subject: CertificateSubject,
pub issuer: Identity,
pub issuerName: CertificateName,
pub extendedAttributes: Box<[u8]>,
pub extendedAttributes: Vec<u8>,
pub maxPathLength: u32,
pub crl: Box<[Box<[u8]>]>,
pub signature: Box<[u8]>
pub crl: Vec<CertificateSerialNo>,
pub signature: Vec<u8>
}
impl CertificateName {
@ -208,8 +284,8 @@ impl CertificateNetwork {
impl CertificateIdentity {
pub(crate) fn new_from_capi(ci: &ztcore::ZT_Certificate_Identity) -> CertificateIdentity {
CertificateIdentity{
identity: Identity::new_from_capi(ci.identity, false),
locator: Locator::new_from_capi(ci.locator, false)
identity: Identity::new_from_capi(ci.identity, false).clone(),
locator: Locator::new_from_capi(ci.locator, false).clone()
}
}
}
@ -230,11 +306,11 @@ impl CertificateSubject {
}
let ccertificates: &[*const u8] = std::slice::from_raw_parts(cs.certificates, cs.certificateCount as usize);
let mut certificates: Vec<Box<[u8]>> = Vec::new();
let mut certificates: Vec<CertificateSerialNo> = Vec::new();
let mut ctmp: [u8; 48] = [0; 48];
for i in ccertificates.iter() {
copy_nonoverlapping(*i, ctmp.as_mut_ptr(), 48);
certificates.push(Box::from(ctmp));
certificates.push(CertificateSerialNo(ctmp));
}
let cupdate_urls: &[*const c_char] = std::slice::from_raw_parts(cs.updateURLs, cs.updateURLCount as usize);
@ -245,13 +321,13 @@ impl CertificateSubject {
return CertificateSubject{
timestamp: cs.timestamp,
identities: identities.into_boxed_slice(),
networks: networks.into_boxed_slice(),
certificates: certificates.into_boxed_slice(),
updateURLs: update_urls.into_boxed_slice(),
identities: identities,
networks: networks,
certificates: certificates,
updateURLs: update_urls,
name: CertificateName::new_from_capi(&cs.name),
uniqueId: Box::from(std::slice::from_raw_parts(cs.uniqueId, cs.uniqueIdSize as usize).clone()),
uniqueIdProofSignature: Box::from(std::slice::from_raw_parts(cs.uniqueIdProofSignature, cs.uniqueIdProofSignatureSize as usize).clone())
uniqueId: Vec::from(std::slice::from_raw_parts(cs.uniqueId, cs.uniqueIdSize as usize)),
uniqueIdProofSignature: Vec::from(std::slice::from_raw_parts(cs.uniqueIdProofSignature, cs.uniqueIdProofSignatureSize as usize))
}
}
}
@ -260,34 +336,26 @@ impl CertificateSubject {
impl Certificate {
pub(crate) fn new_from_capi(c: &ztcore::ZT_Certificate) -> Certificate {
unsafe {
let cextended_attributes: &[u8] = std::slice::from_raw_parts(c.extendedAttributes, c.extendedAttributesSize as usize);
let mut extended_attributes: Vec<u8> = Vec::new();
extended_attributes.extend(cextended_attributes.iter());
let ccrl: &[*const u8] = std::slice::from_raw_parts(c.crl, c.crlCount as usize);
let mut crl: Vec<Box<[u8]>> = Vec::new();
let mut crl: Vec<CertificateSerialNo> = Vec::new();
let mut ctmp: [u8; 48] = [0; 48];
for i in ccrl.iter() {
copy_nonoverlapping(*i, ctmp.as_mut_ptr(), 48);
crl.push(Box::from(ctmp));
crl.push(CertificateSerialNo(ctmp));
}
let csignature: &[u8] = std::slice::from_raw_parts(c.signature, c.signatureSize as usize);
let mut signature: Vec<u8> = Vec::new();
signature.extend(csignature.iter());
return Certificate{
serialNo: Box::from(c.serialNo),
serialNo: CertificateSerialNo(c.serialNo),
flags: c.flags,
timestamp: c.timestamp,
validity: c.validity,
subject: CertificateSubject::new_from_capi(&c.subject),
issuer: Identity::new_from_capi(c.issuer, false),
issuerName: CertificateName::new_from_capi(&c.issuerName),
extendedAttributes: extended_attributes.into_boxed_slice(),
extendedAttributes: Vec::from(std::slice::from_raw_parts(c.extendedAttributes, c.extendedAttributesSize as usize)),
maxPathLength: c.maxPathLength as u32,
crl: crl.into_boxed_slice(),
signature: signature.into_boxed_slice()
crl: crl,
signature: Vec::from(std::slice::from_raw_parts(c.signature, c.signatureSize as usize))
}
}
}
@ -296,31 +364,26 @@ impl Certificate {
impl CertificateSubjectUniqueIdSecret {
pub fn new(t: CertificateUniqueIdType) -> Self {
unsafe {
let mut unique_id: Vec<u8> = Vec::new();
let mut unique_id_private: Vec<u8> = Vec::new();
unique_id.resize(128, 0);
unique_id_private.resize(128, 0);
let mut unique_id_size: c_int = 128;
let mut unique_id_private_size: c_int = 128;
let mut unique_id: [u8; 128] = zeroed();
let mut unique_id_private: [u8; 128] = zeroed();
let mut unique_id_size: c_int = unique_id.len() as c_int;
let mut unique_id_private_size: c_int = unique_id_private.len() as c_int;
let ct: ztcore::ZT_CertificateUniqueIdType = num_traits::ToPrimitive::to_u32(&t).unwrap();
if ztcore::ZT_Certificate_newSubjectUniqueId(ct, unique_id.as_mut_ptr() as *mut c_void, &mut unique_id_size as *mut c_int, unique_id_private.as_mut_ptr() as *mut c_void, &mut unique_id_private_size as *mut c_int) != 0 {
panic!("fatal internal error: ZT_Certificate_newSubjectUniqueId failed.");
}
unique_id.resize(unique_id_size as usize, 0);
unique_id_private.resize(unique_id_private_size as usize, 0);
return CertificateSubjectUniqueIdSecret{
public: unique_id.into_boxed_slice(),
private: unique_id_private.into_boxed_slice(),
public: Vec::from(&unique_id[0..unique_id_size as usize]),
private: Vec::from(&unique_id_private[0..unique_id_private_size as usize]),
type_: num_traits::FromPrimitive::from_u32(ct as u32).unwrap()
};
}
}
}
implement_json_serializable!(CertificateName);
implement_json_serializable!(CertificateNetwork);
implement_json_serializable!(CertificateIdentity);
implement_json_serializable!(CertificateSubject);
implement_json_serializable!(Certificate);
implement_json_serializable!(CertificateSubjectUniqueIdSecret);
implement_to_from_json!(CertificateName);
implement_to_from_json!(CertificateNetwork);
implement_to_from_json!(CertificateIdentity);
implement_to_from_json!(CertificateSubject);
implement_to_from_json!(Certificate);
implement_to_from_json!(CertificateSubjectUniqueIdSecret);

View file

@ -12,6 +12,7 @@ mod node;
mod mac;
mod buffer;
mod portableatomici64;
mod virtualnetworkconfig;
pub use identity::{Identity, IdentityType};
pub use address::Address;
@ -26,6 +27,7 @@ pub use node::Node;
pub use mac::MAC;
pub use buffer::Buffer;
pub use portableatomici64::PortableAtomicI64;
pub use virtualnetworkconfig::*;
use bindings::capi as ztcore;
use num_derive::{FromPrimitive, ToPrimitive};
@ -151,67 +153,6 @@ pub enum Event {
UserMessage = ztcore::ZT_Event_ZT_EVENT_USER_MESSAGE as isize,
}
#[derive(FromPrimitive,ToPrimitive)]
pub enum VirtualNetworkStatus {
RequestingConfiguration = ztcore::ZT_VirtualNetworkStatus_ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION as isize,
Ok = ztcore::ZT_VirtualNetworkStatus_ZT_NETWORK_STATUS_OK as isize,
AccessDenied = ztcore::ZT_VirtualNetworkStatus_ZT_NETWORK_STATUS_ACCESS_DENIED as isize,
NotFound = ztcore::ZT_VirtualNetworkStatus_ZT_NETWORK_STATUS_NOT_FOUND as isize,
}
#[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,
}
#[derive(FromPrimitive,ToPrimitive)]
pub enum VirtualNetworkRuleType {
ActionDrop = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_ACTION_DROP as isize,
ActionAccept = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_ACTION_ACCEPT as isize,
ActionTee = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_ACTION_TEE as isize,
ActionWatch = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_ACTION_WATCH as isize,
ActionRedirect = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_ACTION_REDIRECT as isize,
ActionBreak = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_ACTION_BREAK as isize,
ActionPriority = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_ACTION_PRIORITY as isize,
MatchSourceZeroTierAddress = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS as isize,
MatchDestinationZeroTierAddress = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS as isize,
MatchVlanId = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_VLAN_ID as isize,
MatchVlanPcp = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_VLAN_PCP as isize,
MatchVlanDei = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_VLAN_DEI as isize,
MatchMacSource = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_MAC_SOURCE as isize,
MatchMacDestination = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_MAC_DEST as isize,
MatchIpv4Source = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IPV4_SOURCE as isize,
MatchIpv4Destination = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IPV4_DEST as isize,
MatchIpv6Source = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IPV6_SOURCE as isize,
MatchIpv6Destination = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IPV6_DEST as isize,
MatchIpTos = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IP_TOS as isize,
MatchIpProtocol = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IP_PROTOCOL as isize,
MatchEtherType = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_ETHERTYPE as isize,
MatchIcmp = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_ICMP as isize,
MatchIpSourcePortRange = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE as isize,
MatchIpDestinationSourceRange = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE as isize,
MatchCharacteristics = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_CHARACTERISTICS as isize,
MatchFrameSizeRange = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE as isize,
MatchRandom = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_RANDOM as isize,
MatchTagsDifference = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE as isize,
MatchTagsBitwiseAnd = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND as isize,
MatchTagsBitwiseOr = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR as isize,
MatchTagsBitwiseXor = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR as isize,
MatchTagsEqual = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_TAGS_EQUAL as isize,
MatchTagSender = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_TAG_SENDER as isize,
MatchTagReceiver = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_TAG_RECEIVER as isize,
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,
ConfigUpdate = ztcore::ZT_VirtualNetworkConfigOperation_ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE as isize,
Down = ztcore::ZT_VirtualNetworkConfigOperation_ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN as isize,
Destroy = ztcore::ZT_VirtualNetworkConfigOperation_ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY as isize
}
#[derive(FromPrimitive,ToPrimitive)]
pub enum StateObjectType {
IdentityPublic = ztcore::ZT_StateObjectType_ZT_STATE_OBJECT_IDENTITY_PUBLIC as isize,
@ -242,7 +183,7 @@ pub fn now() -> i64 {
}
#[macro_export(crate)]
macro_rules! implement_json_serializable {
macro_rules! implement_to_from_json {
($struct_name:ident) => {
impl $struct_name {
pub fn new_from_json(json: &str) -> Result<$struct_name, String> {

View file

@ -59,6 +59,12 @@ impl Drop for Locator {
}
}
impl Clone for Locator {
fn clone(&self) -> Locator {
Locator::new_from_string(self.to_string().as_str()).ok().unwrap()
}
}
impl ToString for Locator {
fn to_string(&self) -> String {
let mut buf: [u8; 4096] = [0; 4096];

View file

@ -1,19 +1,33 @@
pub struct NetworkId(pub u64);
impl NetworkId {
#[inline]
#[inline(always)]
pub fn new_from_string(s: &str) -> NetworkId {
return NetworkId(u64::from_str_radix(s, 16).unwrap_or(0));
}
}
impl ToString for NetworkId {
#[inline]
#[inline(always)]
fn to_string(&self) -> String {
format!("{:0>16x}", self.0)
}
}
impl From<u64> for NetworkId {
#[inline(always)]
fn from(n: u64) -> Self {
NetworkId(n)
}
}
impl From<&str> for NetworkId {
#[inline(always)]
fn from(s: &str) -> Self {
NetworkId::new_from_string(s)
}
}
impl serde::Serialize for NetworkId {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer {
serializer.serialize_str(self.to_string().as_str())

View file

@ -1,13 +1,12 @@
use std::cell::Cell;
use std::ffi::CStr;
use std::mem::MaybeUninit;
use std::mem::transmute;
use std::os::raw::{c_int, c_uint, c_ulong, c_void};
use std::ptr::null_mut;
use std::sync::*;
use std::sync::atomic::*;
use std::time::Duration;
use std::mem::transmute;
use std::intrinsics::arith_offset;
use std::ffi::CStr;
use num_traits::FromPrimitive;
use socket2::SockAddr;
@ -15,6 +14,8 @@ use socket2::SockAddr;
use crate::*;
use crate::bindings::capi as ztcore;
const NODE_BACKGROUND_MIN_DELAY: i64 = 250;
#[allow(non_snake_case)]
pub struct NodeStatus {
pub address: Address,
@ -206,10 +207,10 @@ impl Node {
}
let mut next_delay = next_task_deadline - current_time;
if next_delay < 50 {
next_delay = 50;
} else if next_delay > 500 {
next_delay = 500;
if next_delay < 5 {
next_delay = 5;
} else if next_delay > NODE_BACKGROUND_MIN_DELAY {
next_delay = NODE_BACKGROUND_MIN_DELAY;
}
next_delay
}
@ -292,8 +293,8 @@ impl Node {
return NodeStatus {
address: Address(ns.address),
identity: Identity::new_from_capi(&*ns.identity, false).clone(),
publicIdentity: String::from(CStr::from_ptr(ns.publicIdentity)),
secretIdentity: String::from(CStr::from_ptr(ns.secretIdentity)),
publicIdentity: String::from(CStr::from_ptr(ns.publicIdentity).to_str().unwrap()),
secretIdentity: String::from(CStr::from_ptr(ns.secretIdentity).to_str().unwrap()),
online: ns.online != 0
}
}
@ -304,14 +305,47 @@ impl Node {
unsafe {
let pl = ztcore::ZT_Node_peers(self.capi.get());
if !pl.is_null() {
p.reserve(pl.peerCount as usize);
for i in 0..(pl.peerCount as isize) {
p.push(Peer::new_from_capi(&*arith_offset(pl.peers, i)));
let peer_count = (*pl).peerCount as usize;
p.reserve(peer_count);
for i in 0..peer_count as isize {
p.push(Peer::new_from_capi(&*(*pl).peers.offset(i)));
}
ztcore::ZT_freeQueryResult(pl as *const c_void);
}
}
return p;
p
}
pub fn networks(&self) -> Vec<VirtualNetworkConfig> {
let mut n: Vec<VirtualNetworkConfig> = Vec::new();
unsafe {
let nl = ztcore::ZT_Node_networks(self.capi.get());
if !nl.is_null() {
let net_count = (*nl).networkCount as usize;
n.reserve(net_count);
for i in 0..net_count as isize {
n.push(VirtualNetworkConfig::new_from_capi(&*(*nl).networks.offset(i)));
}
ztcore::ZT_freeQueryResult(nl as *const c_void);
}
}
n
}
pub fn certificates(&self) -> Vec<(Certificate, u32)> {
let mut c: Vec<(Certificate, u32)> = Vec::new();
unsafe {
let cl = ztcore::ZT_Node_listCertificates(self.capi.get());
if !cl.is_null() {
let cert_count = (*cl).certCount as usize;
c.reserve(cert_count);
for i in 0..cert_count as isize {
c.push((Certificate::new_from_capi(&**(*cl).certs.offset(i)), *(*cl).localTrust.offset(i)));
}
ztcore::ZT_freeQueryResult(cl as *const c_void);
}
}
c
}
}

View file

@ -0,0 +1,146 @@
use std::ffi::CStr;
use std::mem::{size_of, transmute, zeroed};
use std::os::raw::{c_void, c_char};
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
}
#[derive(FromPrimitive,ToPrimitive)]
pub enum VirtualNetworkRuleType {
ActionDrop = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_ACTION_DROP as isize,
ActionAccept = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_ACTION_ACCEPT as isize,
ActionTee = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_ACTION_TEE as isize,
ActionWatch = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_ACTION_WATCH as isize,
ActionRedirect = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_ACTION_REDIRECT as isize,
ActionBreak = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_ACTION_BREAK as isize,
ActionPriority = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_ACTION_PRIORITY as isize,
MatchSourceZeroTierAddress = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS as isize,
MatchDestinationZeroTierAddress = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS as isize,
MatchVlanId = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_VLAN_ID as isize,
MatchVlanPcp = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_VLAN_PCP as isize,
MatchVlanDei = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_VLAN_DEI as isize,
MatchMacSource = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_MAC_SOURCE as isize,
MatchMacDestination = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_MAC_DEST as isize,
MatchIpv4Source = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IPV4_SOURCE as isize,
MatchIpv4Destination = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IPV4_DEST as isize,
MatchIpv6Source = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IPV6_SOURCE as isize,
MatchIpv6Destination = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IPV6_DEST as isize,
MatchIpTos = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IP_TOS as isize,
MatchIpProtocol = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IP_PROTOCOL as isize,
MatchEtherType = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_ETHERTYPE as isize,
MatchIcmp = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_ICMP as isize,
MatchIpSourcePortRange = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE as isize,
MatchIpDestinationSourceRange = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE as isize,
MatchCharacteristics = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_CHARACTERISTICS as isize,
MatchFrameSizeRange = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE as isize,
MatchRandom = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_RANDOM as isize,
MatchTagsDifference = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE as isize,
MatchTagsBitwiseAnd = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND as isize,
MatchTagsBitwiseOr = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR as isize,
MatchTagsBitwiseXor = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR as isize,
MatchTagsEqual = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_TAGS_EQUAL as isize,
MatchTagSender = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_TAG_SENDER as isize,
MatchTagReceiver = ztcore::ZT_VirtualNetworkRuleType_ZT_NETWORK_RULE_MATCH_TAG_RECEIVER as isize,
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,
ConfigUpdate = ztcore::ZT_VirtualNetworkConfigOperation_ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE as isize,
Down = ztcore::ZT_VirtualNetworkConfigOperation_ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN as isize,
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,
Ok = ztcore::ZT_VirtualNetworkStatus_ZT_NETWORK_STATUS_OK as isize,
AccessDenied = ztcore::ZT_VirtualNetworkStatus_ZT_NETWORK_STATUS_ACCESS_DENIED as isize,
NotFound = ztcore::ZT_VirtualNetworkStatus_ZT_NETWORK_STATUS_NOT_FOUND as isize
}
pub struct VirtualNetworkRoute {
pub target: Option<SockAddr>,
pub via: Option<SockAddr>,
pub flags: u16,
pub metric: u16
}
#[allow(non_snake_case)]
pub struct VirtualNetworkConfig {
pub nwid: NetworkId,
pub mac: MAC,
pub name: String,
pub status: VirtualNetworkStatus,
pub type_: VirtualNetworkType,
pub mtu: u32,
pub bridge: bool,
pub broadcastEnabled: bool,
pub netconfRevision: u64,
pub assignedAddresses: Vec<SockAddr>,
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> {
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 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
})
}
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,
broadcastEnabled: vnc.broadcastEnabled != 0,
netconfRevision: vnc.netconfRevision as u64,
assignedAddresses: aa,
routes: rts
}
}
}
}