Expand C API and simplify NodeService
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
* 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: 2025-01-01
|
||||
* Change Date: 2026-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.
|
||||
@@ -14,7 +14,7 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Virtual ethernet tap device and combined network stack driver
|
||||
* Virtual Ethernet tap device and combined network stack driver
|
||||
*/
|
||||
|
||||
#include "Constants.hpp"
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "MAC.hpp"
|
||||
#include "MulticastGroup.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
#include "lwip/etharp.h"
|
||||
#include "lwip/ethip6.h"
|
||||
#include "lwip/netif.h"
|
||||
@@ -30,18 +31,17 @@
|
||||
#include "netif/ethernet.h"
|
||||
|
||||
#ifdef LWIP_STATS
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/stats.h"
|
||||
#endif
|
||||
|
||||
#include "Debug.hpp"
|
||||
#include "Events.hpp"
|
||||
#include "VirtualTap.hpp"
|
||||
#include "ZeroTierSockets.h"
|
||||
|
||||
#if defined(__WINDOWS__)
|
||||
#include "Synchapi.h"
|
||||
#include "Synchapi.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#define ZTS_TAP_THREAD_POLLING_INTERVAL 50
|
||||
@@ -49,18 +49,18 @@
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
extern void _enqueueEvent(int16_t eventCode, void* arg = NULL);
|
||||
extern Events* zts_events;
|
||||
|
||||
/**
|
||||
* A virtual tap device. The ZeroTier core service creates one of these for each
|
||||
* virtual network joined. It will be destroyed upon leave().
|
||||
* Virtual tap device. ZeroTier will create one per joined network. It will
|
||||
* then be destroyed upon leaving the network.
|
||||
*/
|
||||
VirtualTap::VirtualTap(
|
||||
const char* homePath,
|
||||
const MAC& mac,
|
||||
unsigned int mtu,
|
||||
unsigned int metric,
|
||||
uint64_t nwid,
|
||||
uint64_t net_id,
|
||||
const char* friendlyName,
|
||||
void (*handler)(
|
||||
void*,
|
||||
@@ -81,13 +81,11 @@ VirtualTap::VirtualTap(
|
||||
, _run(true)
|
||||
, _mac(mac)
|
||||
, _mtu(mtu)
|
||||
, _nwid(nwid)
|
||||
, _net_id(net_id)
|
||||
, _unixListenSocket((PhySocket*)0)
|
||||
, _phy(this, false, true)
|
||||
{
|
||||
memset(vtap_full_name, 0, sizeof(vtap_full_name));
|
||||
snprintf(vtap_full_name, sizeof(vtap_full_name), "libzt%llx", (unsigned long long)_nwid);
|
||||
_dev = vtap_full_name;
|
||||
OSUtils::ztsnprintf(vtap_full_name, VTAP_NAME_LEN, "libzt-vtap-%llx", _net_id);
|
||||
#ifndef __WINDOWS__
|
||||
::pipe(_shutdownSignalPipe);
|
||||
#endif
|
||||
@@ -97,8 +95,8 @@ VirtualTap::VirtualTap(
|
||||
|
||||
VirtualTap::~VirtualTap()
|
||||
{
|
||||
struct zts_network_details* nd = new zts_network_details;
|
||||
nd->nwid = _nwid;
|
||||
zts_net_info_t* nd = new zts_net_info_t;
|
||||
nd->net_id = _net_id;
|
||||
_run = false;
|
||||
#ifndef __WINDOWS__
|
||||
::write(_shutdownSignalPipe[1], "\0", 1);
|
||||
@@ -108,7 +106,7 @@ VirtualTap::~VirtualTap()
|
||||
netif4 = NULL;
|
||||
_lwip_remove_netif(netif6);
|
||||
netif6 = NULL;
|
||||
_enqueueEvent(ZTS_EVENT_NETWORK_DOWN, (void*)nd);
|
||||
_events->enqueue(ZTS_EVENT_NETWORK_DOWN, (void*)nd);
|
||||
Thread::join(_thread);
|
||||
#ifndef __WINDOWS__
|
||||
::close(_shutdownSignalPipe[0]);
|
||||
@@ -131,6 +129,11 @@ bool VirtualTap::enabled() const
|
||||
return _enabled;
|
||||
}
|
||||
|
||||
void VirtualTap::setUserEventSystem(Events* events)
|
||||
{
|
||||
_events = events;
|
||||
}
|
||||
|
||||
bool VirtualTap::hasIpv4Addr()
|
||||
{
|
||||
Mutex::Lock _l(_ips_m);
|
||||
@@ -159,21 +162,21 @@ bool VirtualTap::hasIpv6Addr()
|
||||
|
||||
bool VirtualTap::addIp(const InetAddress& ip)
|
||||
{
|
||||
char ipbuf[128];
|
||||
// ip.toString(ipbuf);
|
||||
// DEBUG_INFO("addr=%s", ipbuf);
|
||||
|
||||
// TODO: Rewrite to allow for more addresses
|
||||
char ipbuf[128] = { 0 };
|
||||
/* Limit address assignments to one per type.
|
||||
This limitation can be removed if some changes
|
||||
are made in the netif driver. */
|
||||
if (ip.isV4() && hasIpv4Addr()) {
|
||||
ip.toString(ipbuf);
|
||||
DEBUG_INFO("failed to add IP (%s), only one per type per netif allowed\n", ipbuf);
|
||||
// DEBUG_INFO("failed to add IP (%s), only one per type per netif
|
||||
// allowed\n", ipbuf);
|
||||
return false;
|
||||
}
|
||||
if (ip.isV6() && hasIpv6Addr()) {
|
||||
ip.toString(ipbuf);
|
||||
DEBUG_INFO("failed to add IP (%s), only one per type per netif allowed\n", ipbuf);
|
||||
// DEBUG_INFO("failed to add IP (%s), only one per type per netif
|
||||
// allowed\n", ipbuf);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -218,16 +221,6 @@ void VirtualTap::put(
|
||||
}
|
||||
}
|
||||
|
||||
std::string VirtualTap::deviceName() const
|
||||
{
|
||||
return _dev;
|
||||
}
|
||||
|
||||
void VirtualTap::setFriendlyName(const char* friendlyName)
|
||||
{
|
||||
DEBUG_INFO("%s", friendlyName);
|
||||
}
|
||||
|
||||
void VirtualTap::scanMulticastGroups(
|
||||
std::vector<MulticastGroup>& added,
|
||||
std::vector<MulticastGroup>& removed)
|
||||
@@ -299,10 +292,13 @@ void VirtualTap::phyOnDatagram(
|
||||
void* data,
|
||||
unsigned long len)
|
||||
{
|
||||
// Intentionally empty
|
||||
}
|
||||
|
||||
void VirtualTap::phyOnTcpConnect(PhySocket* sock, void** uptr, bool success)
|
||||
{
|
||||
}
|
||||
|
||||
void VirtualTap::phyOnTcpAccept(
|
||||
PhySocket* sockL,
|
||||
PhySocket* sockN,
|
||||
@@ -311,22 +307,26 @@ void VirtualTap::phyOnTcpAccept(
|
||||
const struct sockaddr* from)
|
||||
{
|
||||
}
|
||||
|
||||
void VirtualTap::phyOnTcpClose(PhySocket* sock, void** uptr)
|
||||
{
|
||||
}
|
||||
|
||||
void VirtualTap::phyOnTcpData(PhySocket* sock, void** uptr, void* data, unsigned long len)
|
||||
{
|
||||
}
|
||||
|
||||
void VirtualTap::phyOnTcpWritable(PhySocket* sock, void** uptr)
|
||||
{
|
||||
}
|
||||
|
||||
void VirtualTap::phyOnUnixClose(PhySocket* sock, void** uptr)
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Netif driver code for lwIP network stack //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//----------------------------------------------------------------------------//
|
||||
// Netif driver code for lwIP network stack //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
bool _has_exited = false;
|
||||
bool _has_started = false;
|
||||
@@ -342,39 +342,39 @@ static void _tcpip_init_done(void* arg)
|
||||
{
|
||||
sys_sem_t* sem;
|
||||
sem = (sys_sem_t*)arg;
|
||||
_setState(ZTS_STATE_STACK_RUNNING);
|
||||
zts_events->setState(ZTS_STATE_STACK_RUNNING);
|
||||
_has_started = true;
|
||||
_enqueueEvent(ZTS_EVENT_STACK_UP);
|
||||
zts_events->enqueue(ZTS_EVENT_STACK_UP, NULL);
|
||||
sys_sem_signal(sem);
|
||||
}
|
||||
|
||||
static void _main_lwip_driver_loop(void* arg)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
pthread_setname_np(pthread_self(), ZTS_LWIP_DRIVER_THREAD_NAME);
|
||||
pthread_setname_np(pthread_self(), ZTS_LWIP_THREAD_NAME);
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
pthread_setname_np(ZTS_LWIP_DRIVER_THREAD_NAME);
|
||||
pthread_setname_np(ZTS_LWIP_THREAD_NAME);
|
||||
#endif
|
||||
sys_sem_t sem;
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
if (sys_sem_new(&sem, 0) != ERR_OK) {
|
||||
DEBUG_ERROR("failed to create semaphore");
|
||||
// DEBUG_ERROR("failed to create semaphore");
|
||||
}
|
||||
tcpip_init(_tcpip_init_done, &sem);
|
||||
sys_sem_wait(&sem);
|
||||
// Main loop
|
||||
while (_getState(ZTS_STATE_STACK_RUNNING)) {
|
||||
zts_delay_ms(LWIP_DRIVER_LOOP_INTERVAL);
|
||||
while (zts_events->getState(ZTS_STATE_STACK_RUNNING)) {
|
||||
zts_util_delay(LWIP_DRIVER_LOOP_INTERVAL);
|
||||
}
|
||||
_has_exited = true;
|
||||
_enqueueEvent(ZTS_EVENT_STACK_DOWN);
|
||||
zts_events->enqueue(ZTS_EVENT_STACK_DOWN, NULL);
|
||||
}
|
||||
|
||||
bool _lwip_is_up()
|
||||
{
|
||||
Mutex::Lock _l(stackLock);
|
||||
return _getState(ZTS_STATE_STACK_RUNNING);
|
||||
return zts_events->getState(ZTS_STATE_STACK_RUNNING);
|
||||
}
|
||||
|
||||
void _lwip_driver_init()
|
||||
@@ -390,7 +390,7 @@ void _lwip_driver_init()
|
||||
sys_init(); // Required for win32 init of critical sections
|
||||
#endif
|
||||
sys_thread_new(
|
||||
ZTS_LWIP_DRIVER_THREAD_NAME,
|
||||
ZTS_LWIP_THREAD_NAME,
|
||||
_main_lwip_driver_loop,
|
||||
NULL,
|
||||
DEFAULT_THREAD_STACKSIZE,
|
||||
@@ -404,11 +404,11 @@ void _lwip_driver_shutdown()
|
||||
}
|
||||
Mutex::Lock _l(stackLock);
|
||||
// Set flag to stop sending frames into the core
|
||||
_clrState(ZTS_STATE_STACK_RUNNING);
|
||||
zts_events->clrState(ZTS_STATE_STACK_RUNNING);
|
||||
// Wait until the main lwIP thread has exited
|
||||
if (_has_started) {
|
||||
while (! _has_exited) {
|
||||
zts_delay_ms(LWIP_DRIVER_LOOP_INTERVAL);
|
||||
zts_util_delay(LWIP_DRIVER_LOOP_INTERVAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -432,7 +432,7 @@ err_t _lwip_eth_tx(struct netif* n, struct pbuf* p)
|
||||
return ERR_IF;
|
||||
}
|
||||
struct pbuf* q;
|
||||
char buf[ZT_MAX_MTU + 32];
|
||||
char buf[ZT_MAX_MTU + 32] = { 0 };
|
||||
char* bufptr;
|
||||
int totalLength = 0;
|
||||
|
||||
@@ -454,29 +454,8 @@ err_t _lwip_eth_tx(struct netif* n, struct pbuf* p)
|
||||
char* data = buf + sizeof(struct eth_hdr);
|
||||
int len = totalLength - sizeof(struct eth_hdr);
|
||||
int proto = Utils::ntoh((uint16_t)ethhdr->type);
|
||||
tap->_handler(tap->_arg, NULL, tap->_nwid, src_mac, dest_mac, proto, 0, data, len);
|
||||
if (ZT_MSG_TRANSFER == true) {
|
||||
char flagbuf[32];
|
||||
memset(&flagbuf, 0, 32);
|
||||
char macBuf[ZTS_MAC_ADDRSTRLEN], nodeBuf[16];
|
||||
snprintf(
|
||||
macBuf,
|
||||
ZTS_MAC_ADDRSTRLEN,
|
||||
"%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
ethhdr->dest.addr[0],
|
||||
ethhdr->dest.addr[1],
|
||||
ethhdr->dest.addr[2],
|
||||
ethhdr->dest.addr[3],
|
||||
ethhdr->dest.addr[4],
|
||||
ethhdr->dest.addr[5]);
|
||||
MAC mac;
|
||||
mac.setTo(ethhdr->dest.addr, 6);
|
||||
mac.toAddress(tap->_nwid).toString(nodeBuf);
|
||||
/*
|
||||
DEBUG_TRANS("len=%5d dst=%s [%s TX <-- %s] ethertype=0x%04x %s", totalLength, macBuf,
|
||||
nodeBuf, tap->nodeId().c_str(), Utils::ntoh(ethhdr->type), flagbuf);
|
||||
*/
|
||||
}
|
||||
tap->_handler(tap->_arg, NULL, tap->_net_id, src_mac, dest_mac, proto, 0, data, len);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
@@ -491,7 +470,7 @@ void _lwip_eth_rx(
|
||||
#ifdef LWIP_STATS
|
||||
stats_display();
|
||||
#endif
|
||||
if (! _getState(ZTS_STATE_STACK_RUNNING)) {
|
||||
if (! zts_events->getState(ZTS_STATE_STACK_RUNNING)) {
|
||||
return;
|
||||
}
|
||||
struct pbuf *p, *q;
|
||||
@@ -500,40 +479,19 @@ void _lwip_eth_rx(
|
||||
to.copyTo(ethhdr.dest.addr, 6);
|
||||
ethhdr.type = Utils::hton((uint16_t)etherType);
|
||||
|
||||
if (ZT_MSG_TRANSFER == true) {
|
||||
char flagbuf[32];
|
||||
memset(&flagbuf, 0, 32);
|
||||
char macBuf[ZTS_MAC_ADDRSTRLEN], nodeBuf[16];
|
||||
snprintf(
|
||||
macBuf,
|
||||
ZTS_MAC_ADDRSTRLEN,
|
||||
"%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
ethhdr.dest.addr[0],
|
||||
ethhdr.dest.addr[1],
|
||||
ethhdr.dest.addr[2],
|
||||
ethhdr.dest.addr[3],
|
||||
ethhdr.dest.addr[4],
|
||||
ethhdr.dest.addr[5]);
|
||||
MAC mac;
|
||||
mac.setTo(ethhdr.src.addr, 6);
|
||||
mac.toAddress(tap->_nwid).toString(nodeBuf);
|
||||
/*
|
||||
DEBUG_TRANS("len=%5d dst=%s [%s RX --> %s] ethertype=0x%04x %s", len, macBuf, nodeBuf,
|
||||
tap->nodeId().c_str(), Utils::ntoh(ethhdr.type), flagbuf);
|
||||
*/
|
||||
}
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, (uint16_t)len + sizeof(struct eth_hdr), PBUF_RAM);
|
||||
if (! p) {
|
||||
DEBUG_ERROR("dropped packet: unable to allocate memory for pbuf");
|
||||
// DEBUG_ERROR("dropped packet: unable to allocate memory for
|
||||
// pbuf");
|
||||
return;
|
||||
}
|
||||
// First pbuf gets ethernet header at start
|
||||
// First pbuf gets Ethernet header at start
|
||||
q = p;
|
||||
if (q->len < sizeof(ethhdr)) {
|
||||
pbuf_free(p);
|
||||
p = NULL;
|
||||
DEBUG_ERROR("dropped packet: first pbuf smaller than ethernet header");
|
||||
// DEBUG_ERROR("dropped packet: first pbuf smaller than Ethernet
|
||||
// header");
|
||||
return;
|
||||
}
|
||||
// Copy frame data into pbuf
|
||||
@@ -554,7 +512,7 @@ void _lwip_eth_rx(
|
||||
if (tap->netif4) {
|
||||
if ((err = ((struct netif*)tap->netif4)->input(p, (struct netif*)tap->netif4))
|
||||
!= ERR_OK) {
|
||||
DEBUG_ERROR("packet input error (%d)", err);
|
||||
// DEBUG_ERROR("packet input error (%d)", err);
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
||||
@@ -563,7 +521,7 @@ void _lwip_eth_rx(
|
||||
if (tap->netif6) {
|
||||
if ((err = ((struct netif*)tap->netif6)->input(p, (struct netif*)tap->netif6))
|
||||
!= ERR_OK) {
|
||||
DEBUG_ERROR("packet input error (%d)", err);
|
||||
// DEBUG_ERROR("packet input error (%d)", err);
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
||||
@@ -581,59 +539,6 @@ bool _lwip_is_netif_up(void* n)
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
static struct zts_netif_details *_lwip_prepare_netif_status_msg(struct netif *n)
|
||||
{
|
||||
if (!n || !n->state) {
|
||||
return NULL;
|
||||
}
|
||||
VirtualTap *tap = (VirtualTap *)n->state;
|
||||
struct zts_netif_details *details = new zts_netif_details();
|
||||
details->nwid = tap->_nwid;
|
||||
memcpy(&(details->mac), n->hwaddr, n->hwaddr_len);
|
||||
details->mtu = n->mtu;
|
||||
return details;
|
||||
}
|
||||
|
||||
static void _netif_remove_callback(struct netif *n)
|
||||
{
|
||||
// Called from core, no need to lock
|
||||
if (!n || !n->state) {
|
||||
return;
|
||||
}
|
||||
VirtualTap *tap = (VirtualTap *)n->state;
|
||||
struct zts_netif_details *details = new zts_netif_details();
|
||||
details->nwid = tap->_nwid;
|
||||
details->mac = 0;
|
||||
details->mtu = 0;
|
||||
_enqueueEvent(ZTS_EVENT_NETIF_REMOVED, (void*)details);
|
||||
}
|
||||
|
||||
static void _netif_status_callback(struct netif *n)
|
||||
{
|
||||
// Called from core, no need to lock
|
||||
if (!n) {
|
||||
return;
|
||||
} if (netif_is_up(n)) {
|
||||
_enqueueEvent(ZTS_EVENT_NETIF_UP, (void*)_lwip_prepare_netif_status_msg(n));
|
||||
} else {
|
||||
_enqueueEvent(ZTS_EVENT_NETIF_DOWN, (void*)_lwip_prepare_netif_status_msg(n));
|
||||
}
|
||||
}
|
||||
|
||||
static void _netif_link_callback(struct netif *n)
|
||||
{
|
||||
// Called from core, no need to lock
|
||||
if (!n) {
|
||||
return;
|
||||
} if (netif_is_link_up(n)) {
|
||||
_enqueueEvent(ZTS_EVENT_NETIF_LINK_UP, (void*)_lwip_prepare_netif_status_msg(n));
|
||||
} else {
|
||||
_enqueueEvent(ZTS_EVENT_NETIF_LINK_DOWN, (void*)_lwip_prepare_netif_status_msg(n));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
static err_t _netif_init4(struct netif* n)
|
||||
{
|
||||
if (! n || ! n->state) {
|
||||
@@ -676,7 +581,7 @@ static err_t _netif_init6(struct netif* n)
|
||||
|
||||
void _lwip_init_interface(void* tapref, const InetAddress& ip)
|
||||
{
|
||||
char macbuf[ZTS_MAC_ADDRSTRLEN];
|
||||
char macbuf[ZTS_MAC_ADDRSTRLEN] = { 0 };
|
||||
|
||||
VirtualTap* vtap = (VirtualTap*)tapref;
|
||||
struct netif* n = NULL;
|
||||
@@ -691,11 +596,7 @@ void _lwip_init_interface(void* tapref, const InetAddress& ip)
|
||||
isNewNetif = true;
|
||||
netifCount++;
|
||||
}
|
||||
/*
|
||||
netif_set_status_callback(n, _netif_status_callback);
|
||||
netif_set_remove_callback(n, _netif_remove_callback);
|
||||
netif_set_link_callback(n, _netif_link_callback);
|
||||
*/
|
||||
|
||||
static ip4_addr_t ip4, netmask, gw;
|
||||
IP4_ADDR(&gw, 127, 0, 0, 1);
|
||||
ip4.addr = *((u32_t*)ip.rawIpData());
|
||||
@@ -714,12 +615,6 @@ void _lwip_init_interface(void* tapref, const InetAddress& ip)
|
||||
n->hwaddr[3],
|
||||
n->hwaddr[4],
|
||||
n->hwaddr[5]);
|
||||
/*
|
||||
char nmbuf[INET6_ADDRSTRLEN];
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
DEBUG_INFO("initialized netif=%p as [mac=%s, addr=%s, nm=%s, tap=%p]",n,
|
||||
macbuf, ip.toString(ipbuf), ip.netmask().toString(nmbuf), vtap);
|
||||
*/
|
||||
}
|
||||
if (ip.isV6()) {
|
||||
if (vtap->netif6) {
|
||||
@@ -729,11 +624,7 @@ void _lwip_init_interface(void* tapref, const InetAddress& ip)
|
||||
n = new struct netif;
|
||||
isNewNetif = true;
|
||||
netifCount++;
|
||||
} /*
|
||||
netif_set_status_callback(n, _netif_status_callback);
|
||||
netif_set_remove_callback(n, _netif_remove_callback);
|
||||
netif_set_link_callback(n, _netif_link_callback);
|
||||
*/
|
||||
}
|
||||
static ip6_addr_t ip6;
|
||||
memcpy(&(ip6.addr), ip.rawIpData(), sizeof(ip6.addr));
|
||||
LOCK_TCPIP_CORE();
|
||||
@@ -760,10 +651,6 @@ void _lwip_init_interface(void* tapref, const InetAddress& ip)
|
||||
n->hwaddr[3],
|
||||
n->hwaddr[4],
|
||||
n->hwaddr[5]);
|
||||
/*
|
||||
DEBUG_INFO("initialized netif=%p as [mac=%s, addr=%s, tap=%p]", n,
|
||||
macbuf, ip.toString(ipbuf), vtap);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user