493 lines
15 KiB
C#
493 lines
15 KiB
C#
|
|
/*
|
|||
|
|
* Copyright (c)2013-2020 ZeroTier, Inc.
|
|||
|
|
*
|
|||
|
|
* Use of this software is governed by the Business Source License included
|
|||
|
|
* in the LICENSE.TXT file in the project's root directory.
|
|||
|
|
*
|
|||
|
|
* Change Date: 2024-01-01
|
|||
|
|
*
|
|||
|
|
* On the date above, in accordance with the Business Source License, use
|
|||
|
|
* of this software will be governed by version 2.0 of the Apache License.
|
|||
|
|
*/
|
|||
|
|
/****/
|
|||
|
|
|
|||
|
|
using System.Runtime.InteropServices;
|
|||
|
|
using System;
|
|||
|
|
|
|||
|
|
// Prototype of callback used by ZeroTier to signal events to C# application
|
|||
|
|
public delegate void CSharpCallbackWithStruct(IntPtr msgPtr);
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// ZeroTier SDK
|
|||
|
|
/// </summary>
|
|||
|
|
namespace ZeroTier
|
|||
|
|
{
|
|||
|
|
public delegate void ZeroTierManagedEventCallback(ZeroTier.Event nodeEvent);
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// ZeroTier Node - Virtual network subsystem
|
|||
|
|
/// </summary>
|
|||
|
|
public class Node
|
|||
|
|
{
|
|||
|
|
static ulong _nodeId = 0x0;
|
|||
|
|
static bool _isOnline = false;
|
|||
|
|
static bool _joinedAtLeastOneNetwork = false;
|
|||
|
|
static bool _hasBeenFreed = false;
|
|||
|
|
string _configFilePath;
|
|||
|
|
ushort _servicePort;
|
|||
|
|
static ZeroTierManagedEventCallback _managedCallback;
|
|||
|
|
|
|||
|
|
// Callback used internally to ferry events from the C++ layer
|
|||
|
|
static void myZeroTierEventCallback(IntPtr msgPtr)
|
|||
|
|
{
|
|||
|
|
// Marshal the callback message pointer to a structure that we can inspect
|
|||
|
|
zts_callback_msg msg =
|
|||
|
|
(zts_callback_msg)Marshal.PtrToStructure(msgPtr, typeof(zts_callback_msg));
|
|||
|
|
|
|||
|
|
ZeroTier.Event newEvent = null;
|
|||
|
|
|
|||
|
|
// Node events
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NODE_UP) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NODE_UP");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NODE_ONLINE) {
|
|||
|
|
_isOnline = true;
|
|||
|
|
// Marshal the node details pointer to a structure
|
|||
|
|
zts_node_details details =
|
|||
|
|
(zts_node_details)Marshal.PtrToStructure(msg.node, typeof(zts_node_details));
|
|||
|
|
_nodeId = details.address;
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode, "EVENT_NODE_ONLINE");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NODE_OFFLINE) {
|
|||
|
|
_isOnline = false;
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NODE_OFFLINE");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NODE_NORMAL_TERMINATION) {
|
|||
|
|
_isOnline = false;
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NODE_NORMAL_TERMINATION");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NODE_DOWN) {
|
|||
|
|
_isOnline = false;
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NODE_DOWN");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NODE_IDENTITY_COLLISION) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NODE_IDENTITY_COLLISION");
|
|||
|
|
_isOnline = false;
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NODE_UNRECOVERABLE_ERROR) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NODE_UNRECOVERABLE_ERROR");
|
|||
|
|
_isOnline = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Network events
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NETWORK_NOT_FOUND) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_NOT_FOUND");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NETWORK_REQ_CONFIG) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_REQ_CONFIG");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NETWORK_ACCESS_DENIED) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_ACCESS_DENIED");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NETWORK_READY_IP4) {
|
|||
|
|
_joinedAtLeastOneNetwork = true;
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_READY_IP4");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NETWORK_READY_IP6) {
|
|||
|
|
_joinedAtLeastOneNetwork = true;
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_READY_IP6");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NETWORK_DOWN) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_DOWN");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NETWORK_CLIENT_TOO_OLD) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_CLIENT_TOO_OLD");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NETWORK_REQ_CONFIG) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_REQ_CONFIG");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NETWORK_OK) {
|
|||
|
|
zts_network_details unmanagedDetails =
|
|||
|
|
(zts_network_details)Marshal.PtrToStructure(msg.network, typeof(zts_network_details));
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_OK");
|
|||
|
|
newEvent.networkDetails = new NetworkDetails();
|
|||
|
|
newEvent.networkDetails.networkId = unmanagedDetails.nwid;
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NETWORK_ACCESS_DENIED) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_ACCESS_DENIED");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NETWORK_READY_IP4_IP6) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_READY_IP4_IP6");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NETWORK_UPDATE) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_UPDATE");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Stack events
|
|||
|
|
if (msg.eventCode == Constants.EVENT_STACK_UP) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_STACK_UP");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_STACK_DOWN) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_STACK_DOWN");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Address events
|
|||
|
|
if (msg.eventCode == Constants.EVENT_ADDR_ADDED_IP4) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_ADDR_ADDED_IP4");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_ADDR_ADDED_IP6) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_ADDR_ADDED_IP6");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_ADDR_REMOVED_IP4) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_ADDR_REMOVED_IP4");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_ADDR_REMOVED_IP6) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_ADDR_REMOVED_IP6");
|
|||
|
|
}
|
|||
|
|
// peer events
|
|||
|
|
if (msg.eventCode == Constants.EVENT_PEER_DIRECT) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_PEER_DIRECT");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_PEER_RELAY) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_PEER_RELAY");
|
|||
|
|
}
|
|||
|
|
// newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_PEER_UNREACHABLE");
|
|||
|
|
if (msg.eventCode == Constants.EVENT_PEER_PATH_DISCOVERED) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_PEER_PATH_DISCOVERED");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_PEER_PATH_DEAD) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_PEER_PATH_DEAD");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Route events
|
|||
|
|
if (msg.eventCode == Constants.EVENT_ROUTE_ADDED) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_ROUTE_ADDED");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_ROUTE_REMOVED) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_ROUTE_REMOVED");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Netif events
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NETIF_UP) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETIF_UP");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NETIF_DOWN) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETIF_DOWN");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NETIF_REMOVED) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETIF_REMOVED");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NETIF_LINK_UP) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETIF_LINK_UP");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_NETIF_LINK_DOWN) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETIF_LINK_DOWN");
|
|||
|
|
}
|
|||
|
|
if (msg.eventCode == Constants.EVENT_ADDR_REMOVED_IP6) {
|
|||
|
|
newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_ADDR_REMOVED_IP6");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Pass the converted Event to the managed callback (visible to user)
|
|||
|
|
if (newEvent != null) {
|
|||
|
|
_managedCallback(newEvent);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Creates a new Node. Start this object by calling Start().
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="configFilePath">Where keys and config files will be stored on the filesystem</param>
|
|||
|
|
/// <param name="managedCallback">Where you would like to receive ZeroTier event notifications</param>
|
|||
|
|
/// <param name="servicePort">The port ZeroTier will use to send its encrypted </param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public Node(string configFilePath, ZeroTierManagedEventCallback managedCallback, UInt16 servicePort)
|
|||
|
|
{
|
|||
|
|
if (String.IsNullOrEmpty(configFilePath)) {
|
|||
|
|
throw new ArgumentNullException(nameof(configFilePath));
|
|||
|
|
}
|
|||
|
|
if (managedCallback == null) {
|
|||
|
|
throw new ArgumentNullException(nameof(managedCallback));
|
|||
|
|
}
|
|||
|
|
_nodeId = 0x0;
|
|||
|
|
_configFilePath = configFilePath;
|
|||
|
|
_servicePort = servicePort;
|
|||
|
|
_managedCallback = new ZeroTierManagedEventCallback(managedCallback);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Starts the ZeroTier node/service
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public int Start()
|
|||
|
|
{
|
|||
|
|
if (_hasBeenFreed == true) {
|
|||
|
|
throw new ObjectDisposedException("ZeroTier Node has previously been freed. Restart application to create new instance.");
|
|||
|
|
}
|
|||
|
|
return zts_start(_configFilePath,myZeroTierEventCallback,_servicePort);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Frees (most) resources used by ZeroTier. ZeroTier may not be started again after this call.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public int Free()
|
|||
|
|
{
|
|||
|
|
_nodeId = 0x0;
|
|||
|
|
_hasBeenFreed = true;
|
|||
|
|
return zts_free();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Stop all ZeroTier service activity. The service may be started again with Start().
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public int Stop()
|
|||
|
|
{
|
|||
|
|
_nodeId = 0x0;
|
|||
|
|
return zts_stop();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Restarts the ZeroTier service, internal stack and driver. (Mostly used for debugging.)
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public int Restart()
|
|||
|
|
{
|
|||
|
|
_nodeId = 0x0;
|
|||
|
|
return zts_restart();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Requests to join a ZeroTier network. Remember to authorize your node/device.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="nwid">Network ID</param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public int Join(ulong nwid)
|
|||
|
|
{
|
|||
|
|
return zts_join(nwid);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Leaves a ZeroTier network.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="nwid"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public int Leave(ulong nwid)
|
|||
|
|
{
|
|||
|
|
return zts_leave(nwid);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Returns whether the Node is online (able to reach the internet.)
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public bool IsOnline()
|
|||
|
|
{
|
|||
|
|
return _isOnline;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Returns whether routing information is available from at least one ZeroTier network.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public bool HasRoutes()
|
|||
|
|
{
|
|||
|
|
return _joinedAtLeastOneNetwork;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public ulong NodeId
|
|||
|
|
{
|
|||
|
|
get {
|
|||
|
|
return _nodeId;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* Structures and functions used internally to communicate with
|
|||
|
|
lower-level C API defined in include/ZeroTierSockets.h */
|
|||
|
|
|
|||
|
|
[DllImport("libzt", EntryPoint="CSharp_zts_start")]
|
|||
|
|
static extern int zts_start(string arg1, CSharpCallbackWithStruct arg2, ushort arg3);
|
|||
|
|
|
|||
|
|
[DllImport("libzt", EntryPoint="CSharp_zts_stop")]
|
|||
|
|
static extern int zts_stop();
|
|||
|
|
|
|||
|
|
[DllImport("libzt", EntryPoint="CSharp_zts_restart")]
|
|||
|
|
static extern int zts_restart();
|
|||
|
|
|
|||
|
|
[DllImport("libzt", EntryPoint="CSharp_zts_free")]
|
|||
|
|
static extern int zts_free();
|
|||
|
|
|
|||
|
|
[DllImport("libzt", EntryPoint="CSharp_zts_join")]
|
|||
|
|
static extern int zts_join(ulong arg1);
|
|||
|
|
|
|||
|
|
[DllImport("libzt", EntryPoint="CSharp_zts_leave")]
|
|||
|
|
static extern int zts_leave(ulong arg1);
|
|||
|
|
|
|||
|
|
[DllImport("libzt", EntryPoint="CSharp_zts_allow_network_caching")]
|
|||
|
|
static extern int zts_allow_network_caching(byte arg1);
|
|||
|
|
|
|||
|
|
[DllImport("libzt", EntryPoint="CSharp_zts_allow_peer_caching")]
|
|||
|
|
static extern int zts_allow_peer_caching(byte arg1);
|
|||
|
|
|
|||
|
|
[DllImport("libzt", EntryPoint="CSharp_zts_allow_local_conf")]
|
|||
|
|
static extern int zts_allow_local_conf(byte arg1);
|
|||
|
|
|
|||
|
|
[DllImport("libzt", EntryPoint="CSharp_zts_orbit")]
|
|||
|
|
static extern int zts_orbit(ulong arg1, ulong arg2);
|
|||
|
|
|
|||
|
|
[DllImport("libzt", EntryPoint="CSharp_zts_deorbit")]
|
|||
|
|
static extern int zts_deorbit(ulong arg1);
|
|||
|
|
|
|||
|
|
[DllImport("libzt", EntryPoint="CSharp_zts_get_6plane_addr")]
|
|||
|
|
static extern int zts_get_6plane_addr(IntPtr arg1, ulong arg2, ulong arg3);
|
|||
|
|
|
|||
|
|
[DllImport("libzt", EntryPoint="CSharp_zts_get_rfc4193_addr")]
|
|||
|
|
static extern int zts_get_rfc4193_addr(IntPtr arg1, ulong arg2, ulong arg3);
|
|||
|
|
|
|||
|
|
[DllImport("libzt", EntryPoint="CSharp_zts_generate_adhoc_nwid_from_range")]
|
|||
|
|
static extern ulong zts_generate_adhoc_nwid_from_range(ushort arg1, ushort arg2);
|
|||
|
|
|
|||
|
|
[DllImport("libzt", EntryPoint="CSharp_zts_delay_ms")]
|
|||
|
|
static extern void zts_delay_ms(int arg1);
|
|||
|
|
|
|||
|
|
[DllImport("libzt", EntryPoint="CSharp_zts_errno_get")]
|
|||
|
|
static extern int zts_errno_get();
|
|||
|
|
|
|||
|
|
[StructLayout(LayoutKind.Sequential)]
|
|||
|
|
struct zts_node_details
|
|||
|
|
{
|
|||
|
|
public ulong address;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Virtual network configuration
|
|||
|
|
*/
|
|||
|
|
[StructLayout(LayoutKind.Sequential)]
|
|||
|
|
struct zts_network_details
|
|||
|
|
{
|
|||
|
|
/**
|
|||
|
|
* 64-bit ZeroTier network ID
|
|||
|
|
*/
|
|||
|
|
public ulong nwid;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Ethernet MAC (48 bits) that should be assigned to port
|
|||
|
|
*/
|
|||
|
|
public ulong mac;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Network name (from network configuration master)
|
|||
|
|
*/
|
|||
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
|
|||
|
|
public byte[] name;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Network configuration request status
|
|||
|
|
*/
|
|||
|
|
public byte status; // ?
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Network type
|
|||
|
|
*/
|
|||
|
|
public byte type; // ?
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Maximum interface MTU
|
|||
|
|
*/
|
|||
|
|
public uint mtu;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* If nonzero, the network this port belongs to indicates DHCP availability
|
|||
|
|
*
|
|||
|
|
* This is a suggestion. The underlying implementation is free to ignore it
|
|||
|
|
* for security or other reasons. This is simply a netconf parameter that
|
|||
|
|
* means 'DHCP is available on this network.'
|
|||
|
|
*/
|
|||
|
|
public int dhcp;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* If nonzero, this port is allowed to bridge to other networks
|
|||
|
|
*
|
|||
|
|
* This is informational. If this is false (0), bridged packets will simply
|
|||
|
|
* be dropped and bridging won't work.
|
|||
|
|
*/
|
|||
|
|
public int bridge;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* If nonzero, this network supports and allows broadcast (ff:ff:ff:ff:ff:ff) traffic
|
|||
|
|
*/
|
|||
|
|
public int broadcastEnabled;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* If the network is in PORT_ERROR state, this is the (negative) error code most recently reported
|
|||
|
|
*/
|
|||
|
|
public int portError;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Revision number as reported by controller or 0 if still waiting for config
|
|||
|
|
*/
|
|||
|
|
public ulong netconfRevision;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Number of assigned addresses
|
|||
|
|
*/
|
|||
|
|
public uint assignedAddressCount;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* ZeroTier-assigned addresses (in sockaddr_storage structures)
|
|||
|
|
*
|
|||
|
|
* For IP, the port number of the sockaddr_XX structure contains the number
|
|||
|
|
* of bits in the address netmask. Only the IP address and port are used.
|
|||
|
|
* Other fields like interface number can be ignored.
|
|||
|
|
*
|
|||
|
|
* This is only used for ZeroTier-managed address assignments sent by the
|
|||
|
|
* virtual network's configuration master.
|
|||
|
|
*/
|
|||
|
|
//struct zts_sockaddr_storage assignedAddresses[ZTS_MAX_ZT_ASSIGNED_ADDRESSES];
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Number of ZT-pushed routes
|
|||
|
|
*/
|
|||
|
|
public uint routeCount;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Routes (excluding those implied by assigned addresses and their masks)
|
|||
|
|
*/
|
|||
|
|
//ZTS_VirtualNetworkRoute routes[ZTS_MAX_NETWORK_ROUTES];
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Number of multicast groups subscribed
|
|||
|
|
*/
|
|||
|
|
public uint multicastSubscriptionCount;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Multicast groups to which this network's device is subscribed
|
|||
|
|
*/
|
|||
|
|
//struct {
|
|||
|
|
// uint64_t mac; /* MAC in lower 48 bits */
|
|||
|
|
// uint32_t adi; /* Additional distinguishing information, usually zero except for IPv4 ARP groups */
|
|||
|
|
//} multicastSubscriptions[ZTS_MAX_MULTICAST_SUBSCRIPTIONS];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
[StructLayout(LayoutKind.Sequential)]
|
|||
|
|
struct zts_callback_msg
|
|||
|
|
{
|
|||
|
|
public short eventCode;
|
|||
|
|
[MarshalAs(UnmanagedType.LPStruct, SizeConst = 4)]
|
|||
|
|
public IntPtr node;
|
|||
|
|
public IntPtr network;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the value of errno from the unmanaged region
|
|||
|
|
/// </summary>
|
|||
|
|
/// <value></value>
|
|||
|
|
public static int ErrNo {
|
|||
|
|
get {
|
|||
|
|
return zts_errno_get();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|