BSD-license-compatible, and NO_STACK build variants
This commit is contained in:
@@ -24,6 +24,8 @@
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
// General connection object used by SocketTap and network stack drivers
|
||||
|
||||
#ifndef ZT_CONNECTION_HPP
|
||||
#define ZT_CONNECTION_HPP
|
||||
|
||||
@@ -31,7 +33,9 @@
|
||||
#include <sys/socket.h>
|
||||
|
||||
// picoTCP
|
||||
#include "pico_socket.h"
|
||||
#if defined(STACK_PICO)
|
||||
#include "pico_socket.h"
|
||||
#endif
|
||||
|
||||
// ZT
|
||||
#include "Phy.hpp"
|
||||
@@ -42,10 +46,9 @@
|
||||
#include "RingBuffer.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class SocketTap;
|
||||
|
||||
/*
|
||||
* Connection object
|
||||
*/
|
||||
struct Connection
|
||||
{
|
||||
int tot = 0;
|
||||
@@ -54,20 +57,25 @@ namespace ZeroTier {
|
||||
|
||||
Mutex _tx_m, _rx_m;
|
||||
|
||||
PhySocket *sock;
|
||||
struct pico_socket *picosock;
|
||||
PhySocket *sock;
|
||||
|
||||
#if defined(STACK_PICO)
|
||||
struct pico_socket *picosock;
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
void *pcb;
|
||||
#endif
|
||||
// TODO: For getsockname, etc
|
||||
struct sockaddr_storage *local_addr; // Address we've bound to locally
|
||||
struct sockaddr_storage *peer_addr; // Address of connection call to remote host
|
||||
|
||||
int socket_family, socket_type;
|
||||
|
||||
int app_fd; // provided to app for I/O
|
||||
int sdk_fd; // provided to SDK for I/O
|
||||
int app_fd; // used by app for I/O
|
||||
int sdk_fd; // used by lib for I/O
|
||||
|
||||
std::queue<Connection*> _AcceptedConnections;
|
||||
SocketTap *tap; // Reference to SocketTap
|
||||
SocketTap *tap;
|
||||
int state; // See libzt.h for (ZT_SOCK_STATE_*)
|
||||
|
||||
// timestamp for closure event
|
||||
|
||||
@@ -35,7 +35,14 @@
|
||||
// SDK
|
||||
#include "SocketTap.hpp"
|
||||
#include "libzt.h"
|
||||
#include "picoTCP.hpp"
|
||||
|
||||
// stack drivers
|
||||
#if defined(STACK_PICO)
|
||||
#include "picoTCP.hpp"
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
#include "lwIP.hpp"
|
||||
#endif
|
||||
|
||||
// ZT
|
||||
#include "Utils.hpp"
|
||||
@@ -98,26 +105,22 @@ namespace ZeroTier {
|
||||
|
||||
bool SocketTap::registerIpWithStack(const InetAddress &ip)
|
||||
{
|
||||
if(picostack) {
|
||||
if(ip.isV4())
|
||||
{
|
||||
#if defined(SDK_IPV4)
|
||||
//DEBUG_INFO("addr = %s", ip.toString().c_str());
|
||||
picostack->pico_init_interface(this, ip);
|
||||
_ips.push_back(ip);
|
||||
#endif
|
||||
}
|
||||
if(ip.isV6())
|
||||
{
|
||||
#if defined(SDK_IPV6)
|
||||
//DEBUG_INFO("addr = %s", ip.toString().c_str());
|
||||
picostack->pico_init_interface(this, ip);
|
||||
_ips.push_back(ip);
|
||||
#endif
|
||||
}
|
||||
#if defined(STACK_PICO)
|
||||
if(picostack){
|
||||
picostack->pico_init_interface(this, ip);
|
||||
_ips.push_back(ip);
|
||||
std::sort(_ips.begin(),_ips.end());
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if(lwipstack){
|
||||
lwipstack->lwip_init_interface(this, ip);
|
||||
_ips.push_back(ip);
|
||||
std::sort(_ips.begin(),_ips.end());
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -158,9 +161,14 @@ namespace ZeroTier {
|
||||
void SocketTap::put(const MAC &from,const MAC &to,unsigned int etherType,
|
||||
const void *data,unsigned int len)
|
||||
{
|
||||
// RX packet
|
||||
#if defined(STACK_PICO)
|
||||
if(picostack)
|
||||
picostack->pico_rx(this, from,to,etherType,data,len);
|
||||
picostack->pico_rx(this,from,to,etherType,data,len);
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if(lwipstack)
|
||||
lwipstack->lwip_rx(this,from,to,etherType,data,len);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string SocketTap::deviceName() const
|
||||
@@ -206,8 +214,14 @@ namespace ZeroTier {
|
||||
void SocketTap::threadMain()
|
||||
throw()
|
||||
{
|
||||
#if defined(STACK_PICO)
|
||||
if(picostack)
|
||||
picostack->pico_loop(this);
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if(lwipstack)
|
||||
lwipstack->lwip_loop(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SocketTap::phyOnUnixClose(PhySocket *sock,void **uptr)
|
||||
@@ -235,7 +249,6 @@ namespace ZeroTier {
|
||||
void SocketTap::phyOnUnixWritable(PhySocket *sock,void **uptr,bool stack_invoked)
|
||||
{
|
||||
DEBUG_INFO();
|
||||
//exit(0);
|
||||
if(sock)
|
||||
Read(sock,uptr,stack_invoked);
|
||||
}
|
||||
@@ -246,45 +259,68 @@ namespace ZeroTier {
|
||||
|
||||
int SocketTap::Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen) {
|
||||
Mutex::Lock _l(_tcpconns_m);
|
||||
#if defined(STACK_PICO)
|
||||
if(picostack)
|
||||
return picostack->pico_Connect(conn, fd, addr, addrlen);
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if(lwipstack)
|
||||
return lwipstack->lwip_Connect(conn, fd, addr, addrlen);
|
||||
#endif
|
||||
return ZT_ERR_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
int SocketTap::Bind(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen) {
|
||||
Mutex::Lock _l(_tcpconns_m);
|
||||
#if defined(STACK_PICO)
|
||||
if(picostack)
|
||||
return picostack->pico_Bind(conn, fd, addr, addrlen);
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if(lwipstack)
|
||||
return lwipstack->lwip_Bind(this, conn, fd, addr, addrlen);
|
||||
#endif
|
||||
return ZT_ERR_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
int SocketTap::Listen(Connection *conn, int fd, int backlog) {
|
||||
#if defined(STACK_PICO)
|
||||
Mutex::Lock _l(_tcpconns_m);
|
||||
if(picostack)
|
||||
return picostack->pico_Listen(conn, fd, backlog);
|
||||
return ZT_ERR_GENERAL_FAILURE;
|
||||
#endif
|
||||
return ZT_ERR_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
Connection* SocketTap::Accept(Connection *conn) {
|
||||
#if defined(STACK_PICO)
|
||||
Mutex::Lock _l(_tcpconns_m);
|
||||
if(picostack)
|
||||
return picostack->pico_Accept(conn);
|
||||
return NULL;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void SocketTap::Read(PhySocket *sock,void **uptr,bool stack_invoked) {
|
||||
#if defined(STACK_PICO)
|
||||
DEBUG_INFO();
|
||||
if(picostack)
|
||||
picostack->pico_Read(this, sock, (Connection*)uptr, stack_invoked);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SocketTap::Write(Connection *conn, void *data, ssize_t len) {
|
||||
#if defined(STACK_PICO)
|
||||
//DEBUG_INFO();
|
||||
if(picostack)
|
||||
picostack->pico_Write(conn, data, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SocketTap::Close(Connection *conn) {
|
||||
#if defined(STACK_PICO)
|
||||
if(!conn) {
|
||||
DEBUG_ERROR("invalid connection");
|
||||
return;
|
||||
@@ -321,10 +357,12 @@ namespace ZeroTier {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SocketTap::Housekeeping()
|
||||
{
|
||||
#if defined(STACK_PICO)
|
||||
Mutex::Lock _l(_tcpconns_m);
|
||||
std::time_t current_ts = std::time(nullptr);
|
||||
if(current_ts > last_housekeeping_ts + ZT_HOUSEKEEPING_INTERVAL) {
|
||||
@@ -338,6 +376,7 @@ namespace ZeroTier {
|
||||
}
|
||||
last_housekeeping_ts = std::time(nullptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -44,9 +44,10 @@
|
||||
#include "Phy.hpp"
|
||||
|
||||
#include "libzt.h"
|
||||
#include "picoTCP.hpp"
|
||||
#include "Connection.hpp"
|
||||
|
||||
#if defined(STACK_PICO)
|
||||
#include "picoTCP.hpp"
|
||||
#include "pico_protocol.h"
|
||||
#include "pico_stack.h"
|
||||
#include "pico_ipv4.h"
|
||||
@@ -55,6 +56,10 @@
|
||||
#include "pico_protocol.h"
|
||||
#include "pico_device.h"
|
||||
#include "pico_ipv6.h"
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
#include "lwIP.hpp"
|
||||
#endif
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
@@ -154,9 +159,30 @@ namespace ZeroTier {
|
||||
/* Vars */
|
||||
/****************************************************************************/
|
||||
|
||||
#if defined(STACK_PICO)
|
||||
|
||||
/*
|
||||
* Whether our picoTCP device has been initialized
|
||||
*/
|
||||
bool picodev_initialized = false;
|
||||
|
||||
struct pico_device *picodev;
|
||||
struct pico_device *picodev6;
|
||||
|
||||
/****************************************************************************/
|
||||
/* Guarded RX Frame Buffer for picoTCP */
|
||||
/****************************************************************************/
|
||||
|
||||
unsigned char pico_frame_rxbuf[MAX_PICO_FRAME_RX_BUF_SZ];
|
||||
int pico_frame_rxbuf_tot;
|
||||
Mutex _pico_frame_rxbuf_m;
|
||||
#endif
|
||||
|
||||
#if defined(STACK_LWIP)
|
||||
netif lwipdev;
|
||||
netif lwipdev6;
|
||||
#endif
|
||||
|
||||
std::vector<InetAddress> ips() const;
|
||||
std::vector<InetAddress> _ips;
|
||||
|
||||
@@ -185,19 +211,6 @@ namespace ZeroTier {
|
||||
*/
|
||||
std::time_t last_housekeeping_ts;
|
||||
|
||||
/*
|
||||
* Whether our picoTCP device has been initialized
|
||||
*/
|
||||
bool picodev_initialized = false;
|
||||
|
||||
/****************************************************************************/
|
||||
/* Guarded RX Frame Buffer for picoTCP */
|
||||
/****************************************************************************/
|
||||
|
||||
unsigned char pico_frame_rxbuf[MAX_PICO_FRAME_RX_BUF_SZ];
|
||||
int pico_frame_rxbuf_tot;
|
||||
Mutex _pico_frame_rxbuf_m;
|
||||
|
||||
/****************************************************************************/
|
||||
/* In these, we will call the stack's corresponding functions, this is */
|
||||
/* where one would put logic to select between different stacks */
|
||||
|
||||
@@ -24,12 +24,35 @@
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
#ifndef SDK_UTILITIES_HPP
|
||||
#define SDK_UTILITIES_HPP
|
||||
#ifndef UTILITIES_HPP
|
||||
#define UTILITIES_HPP
|
||||
|
||||
/*
|
||||
* Print a stacktrace
|
||||
*/
|
||||
// void zt_dump_stacktrace(int sig);
|
||||
|
||||
#if defined(STACK_LWIP) && defined(LIBZT_IPV4)
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
#include <netinet/in.h>
|
||||
|
||||
#define ip4_addr1b(ipaddr) (((u8_t*)(ipaddr))[0])
|
||||
#define ip4_addr2b(ipaddr) (((u8_t*)(ipaddr))[1])
|
||||
#define ip4_addr3b(ipaddr) (((u8_t*)(ipaddr))[2])
|
||||
#define ip4_addr4b(ipaddr) (((u8_t*)(ipaddr))[3])
|
||||
inline ip_addr_t convert_ip(struct sockaddr_in * addr)
|
||||
{
|
||||
ip_addr_t conn_addr;
|
||||
struct sockaddr_in *ipv4 = addr;
|
||||
short a = ip4_addr1b(&(ipv4->sin_addr));
|
||||
short b = ip4_addr2b(&(ipv4->sin_addr));
|
||||
short c = ip4_addr3b(&(ipv4->sin_addr));
|
||||
short d = ip4_addr4b(&(ipv4->sin_addr));
|
||||
IP4_ADDR(&conn_addr, a,b,c,d);
|
||||
return conn_addr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
219
src/libzt.cpp
219
src/libzt.cpp
@@ -43,7 +43,12 @@ for applications to use. See also: include/libzt.h */
|
||||
#include <poll.h>
|
||||
|
||||
// stack
|
||||
#include "pico_stack.h"
|
||||
#if defined(STACK_PICO)
|
||||
#include "pico_stack.h"
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
#include "lwIP.hpp"
|
||||
#endif
|
||||
|
||||
// ZT
|
||||
#include "OneService.hpp"
|
||||
@@ -69,7 +74,12 @@ namespace ZeroTier {
|
||||
/*
|
||||
* Global reference to stack
|
||||
*/
|
||||
#if defined(STACK_PICO)
|
||||
picoTCP *picostack = NULL;
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
lwIP *lwipstack = NULL;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* "sockets" that have been created but not bound to a SocketTap interface yet
|
||||
@@ -93,13 +103,16 @@ void zts_start(const char *path)
|
||||
{
|
||||
if(zt1Service)
|
||||
return;
|
||||
#if defined(STACK_PICO)
|
||||
if(ZeroTier::picostack)
|
||||
return;
|
||||
|
||||
ZeroTier::picostack = new ZeroTier::picoTCP();
|
||||
pico_stack_init();
|
||||
|
||||
//DEBUG_INFO("path=%s", path);
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
ZeroTier::lwipstack = new ZeroTier::lwIP();
|
||||
lwip_init();
|
||||
#endif
|
||||
if(path)
|
||||
ZeroTier::homeDir = path;
|
||||
pthread_t service_thread;
|
||||
@@ -354,7 +367,6 @@ int zts_socket(ZT_SOCKET_SIG) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
//DEBUG_INFO();
|
||||
int err = 0;
|
||||
if(!zt1Service) {
|
||||
DEBUG_ERROR("cannot create socket, no service running. call zts_start() first.");
|
||||
@@ -366,66 +378,44 @@ int zts_socket(ZT_SOCKET_SIG) {
|
||||
errno = EPROTONOSUPPORT; // seemingly closest match
|
||||
return -1;
|
||||
}
|
||||
|
||||
ZeroTier::_multiplexer_lock.lock();
|
||||
if(pico_ntimers() >= PICO_MAX_TIMERS) {
|
||||
DEBUG_ERROR("cannot provision additional socket due to limitation of PICO_MAX_TIMERS. current = %d", pico_ntimers());
|
||||
errno = EMFILE;
|
||||
|
||||
#if defined(STACK_PICO)
|
||||
struct pico_socket *p;
|
||||
err = ZeroTier::picostack->pico_Socket(&p, socket_family, socket_type, protocol);
|
||||
if(p) {
|
||||
ZeroTier::Connection *conn = new ZeroTier::Connection();
|
||||
conn->socket_family = socket_family;
|
||||
conn->socket_type = socket_type;
|
||||
conn->picosock = p;
|
||||
ZeroTier::unmap[conn->app_fd] = conn;
|
||||
err = conn->app_fd; // return one end of the socketpair
|
||||
}
|
||||
else {
|
||||
DEBUG_ERROR("failed to create pico_socket");
|
||||
err = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
|
||||
#if defined(STACK_LWIP)
|
||||
// TODO: check for max lwIP timers/sockets
|
||||
ZeroTier::Connection *conn = new ZeroTier::Connection();
|
||||
void *pcb;
|
||||
err = ZeroTier::lwipstack->lwip_Socket(&pcb, socket_family, socket_type, protocol);
|
||||
if(pcb) {
|
||||
ZeroTier::Connection *conn = new ZeroTier::Connection();
|
||||
int protocol_version = 0;
|
||||
struct pico_socket *psock;
|
||||
|
||||
if(socket_family == AF_INET)
|
||||
protocol_version = PICO_PROTO_IPV4;
|
||||
if(socket_family == AF_INET6)
|
||||
protocol_version = PICO_PROTO_IPV6;
|
||||
|
||||
if(socket_type == SOCK_DGRAM) {
|
||||
psock = pico_socket_open(
|
||||
protocol_version, PICO_PROTO_UDP, &ZeroTier::picoTCP::pico_cb_socket_activity);
|
||||
if(psock) { // configure size of UDP SND/RCV buffers
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
if(socket_type == SOCK_STREAM) {
|
||||
psock = pico_socket_open(
|
||||
protocol_version, PICO_PROTO_TCP, &ZeroTier::picoTCP::pico_cb_socket_activity);
|
||||
if(psock) { // configure size of TCP SND/RCV buffers
|
||||
int tx_buf_sz = ZT_STACK_TCP_SOCKET_TX_SZ;
|
||||
int rx_buf_sz = ZT_STACK_TCP_SOCKET_RX_SZ;
|
||||
int t_err = 0;
|
||||
|
||||
int value = 1;
|
||||
pico_socket_setoption(psock, PICO_TCP_NODELAY, &value);
|
||||
|
||||
if((t_err = pico_socket_setoption(psock, PICO_SOCKET_OPT_SNDBUF, &tx_buf_sz)) < 0)
|
||||
DEBUG_ERROR("unable to set SNDBUF size, err = %d, pico_err = %d", t_err, pico_err);
|
||||
if((t_err = pico_socket_setoption(psock, PICO_SOCKET_OPT_RCVBUF, &rx_buf_sz)) < 0)
|
||||
DEBUG_ERROR("unable to set RCVBUF size, err = %d, pico_err = %d", t_err, pico_err);
|
||||
|
||||
if(ZT_SOCK_BEHAVIOR_LINGER) {
|
||||
int linger_time_ms = ZT_SOCK_BEHAVIOR_LINGER_TIME;
|
||||
if((t_err = pico_socket_setoption(psock, PICO_SOCKET_OPT_LINGER, &linger_time_ms)) < 0)
|
||||
DEBUG_ERROR("unable to set LINGER, err = %d, pico_err = %d", t_err, pico_err);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(psock) {
|
||||
conn->socket_family = socket_family;
|
||||
conn->socket_type = socket_type;
|
||||
conn->picosock = psock;
|
||||
ZeroTier::unmap[conn->app_fd] = conn;
|
||||
err = conn->app_fd; // return one end of the socketpair
|
||||
}
|
||||
else {
|
||||
//DEBUG_ERROR("failed to create pico_socket");
|
||||
err = -1;
|
||||
}
|
||||
conn->socket_family = socket_family;
|
||||
conn->socket_type = socket_type;
|
||||
conn->pcb = pcb;
|
||||
ZeroTier::unmap[conn->app_fd] = conn;
|
||||
err = conn->app_fd; // return one end of the socketpair
|
||||
}
|
||||
else {
|
||||
DEBUG_ERROR("failed to create lwip pcb");
|
||||
err = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
ZeroTier::_multiplexer_lock.unlock();
|
||||
return err;
|
||||
}
|
||||
@@ -485,6 +475,7 @@ Linux:
|
||||
|
||||
*/
|
||||
int zts_connect(ZT_CONNECT_SIG) {
|
||||
#if defined(STACK_PICO)
|
||||
//DEBUG_INFO("fd = %d", fd);
|
||||
int err = 0;
|
||||
if(fd < 0) {
|
||||
@@ -604,6 +595,8 @@ int zts_connect(ZT_CONNECT_SIG) {
|
||||
}
|
||||
}
|
||||
return err;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -636,13 +629,11 @@ int zts_bind(ZT_BIND_SIG) {
|
||||
ZeroTier::Connection *conn = ZeroTier::unmap[fd];
|
||||
ZeroTier::SocketTap *tap;
|
||||
|
||||
if(conn) {
|
||||
char ipstr[INET6_ADDRSTRLEN]; //, nm_str[INET6_ADDRSTRLEN];
|
||||
if(conn) {
|
||||
char ipstr[INET6_ADDRSTRLEN];
|
||||
memset(ipstr, 0, INET6_ADDRSTRLEN);
|
||||
ZeroTier::InetAddress iaddr;
|
||||
|
||||
int port = 0;
|
||||
|
||||
if(conn->socket_family == AF_INET) {
|
||||
inet_ntop(AF_INET,
|
||||
(const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN);
|
||||
@@ -662,16 +653,28 @@ int zts_bind(ZT_BIND_SIG) {
|
||||
errno = EADDRNOTAVAIL;
|
||||
err = -1;
|
||||
}
|
||||
#if defined(STACK_PICO)
|
||||
else {
|
||||
conn->picosock->priv = new ZeroTier::ConnectionPair(tap, conn);
|
||||
tap->_Connections.push_back(conn); // Give this Connection to the tap we decided on
|
||||
err = tap->Bind(conn, fd, addr, addrlen); // Semantically: tap->stack->connect
|
||||
err = tap->Bind(conn, fd, addr, addrlen);
|
||||
conn->tap = tap;
|
||||
if(err == 0) { // success
|
||||
ZeroTier::unmap.erase(fd);
|
||||
ZeroTier::fdmap[fd] = new std::pair<ZeroTier::Connection*,ZeroTier::SocketTap*>(conn, tap);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
else {
|
||||
tap->_Connections.push_back(conn);
|
||||
err = tap->Bind(conn, fd, addr, addrlen);
|
||||
if(err == 0) { // success
|
||||
ZeroTier::unmap.erase(fd);
|
||||
ZeroTier::fdmap[fd] = new std::pair<ZeroTier::Connection*,ZeroTier::SocketTap*>(conn, tap);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
DEBUG_ERROR("unable to locate connection");
|
||||
@@ -701,6 +704,7 @@ Linux:
|
||||
[ ] [EOPNOTSUPP] The socket is not of a type that supports the listen() operation.
|
||||
*/
|
||||
int zts_listen(ZT_LISTEN_SIG) {
|
||||
#if defined(STACK_PICO)
|
||||
DEBUG_EXTRA("fd = %d", fd);
|
||||
int err = 0;
|
||||
if(fd < 0) {
|
||||
@@ -733,6 +737,8 @@ int zts_listen(ZT_LISTEN_SIG) {
|
||||
ZeroTier::_multiplexer_lock.unlock();
|
||||
}
|
||||
return err;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -750,6 +756,7 @@ Darwin:
|
||||
[ ] [ENFILE] The system file table is full.
|
||||
*/
|
||||
int zts_accept(ZT_ACCEPT_SIG) {
|
||||
#if defined(STACK_PICO)
|
||||
DEBUG_EXTRA("fd = %d", fd);
|
||||
int err = 0;
|
||||
if(fd < 0) {
|
||||
@@ -809,6 +816,8 @@ int zts_accept(ZT_ACCEPT_SIG) {
|
||||
ZeroTier::_multiplexer_lock.unlock();
|
||||
}
|
||||
return err;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -860,6 +869,7 @@ EPERM Firewall rules forbid connection.
|
||||
*/
|
||||
int zts_setsockopt(ZT_SETSOCKOPT_SIG)
|
||||
{
|
||||
#if defined(STACK_PICO)
|
||||
DEBUG_INFO("fd = %d", fd);
|
||||
int err = 0;
|
||||
if(fd < 0) {
|
||||
@@ -883,6 +893,8 @@ int zts_setsockopt(ZT_SETSOCKOPT_SIG)
|
||||
}
|
||||
err = setsockopt(fd, level, optname, optval, optlen);
|
||||
return err;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -964,6 +976,7 @@ Linux / Darwin:
|
||||
|
||||
int zts_close(ZT_CLOSE_SIG)
|
||||
{
|
||||
#if defined(STACK_PICO)
|
||||
DEBUG_EXTRA("fd = %d", fd);
|
||||
int err = 0;
|
||||
if(fd < 0) {
|
||||
@@ -1063,6 +1076,8 @@ int zts_close(ZT_CLOSE_SIG)
|
||||
}
|
||||
}
|
||||
return err;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zts_poll(ZT_POLL_SIG)
|
||||
@@ -1161,6 +1176,7 @@ int zts_write(ZT_WRITE_SIG) {
|
||||
|
||||
int zts_shutdown(ZT_SHUTDOWN_SIG)
|
||||
{
|
||||
#if defined(STACK_PICO)
|
||||
DEBUG_INFO("fd = %d", fd);
|
||||
|
||||
int err = 0, mode = 0;
|
||||
@@ -1237,6 +1253,8 @@ int zts_shutdown(ZT_SHUTDOWN_SIG)
|
||||
}
|
||||
}
|
||||
return err;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -1311,7 +1329,7 @@ namespace ZeroTier {
|
||||
jstring _str = (*env).NewStringUTF(address_string);
|
||||
env->CallBooleanMethod(addresses, env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"), _str);
|
||||
return addresses;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_ztjni_1get_1ipv6_1address(
|
||||
JNIEnv *env, jobject thisObj, jstring nwid)
|
||||
@@ -1325,7 +1343,7 @@ namespace ZeroTier {
|
||||
jstring _str = (*env).NewStringUTF(address_string);
|
||||
env->CallBooleanMethod(addresses, env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"), _str);
|
||||
return addresses;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the device is in integer form
|
||||
JNIEXPORT jint Java_zerotier_ZeroTier_ztjni_1get_1device_1id()
|
||||
@@ -1501,45 +1519,47 @@ namespace ZeroTier {
|
||||
/* SDK Socket API Helper functions --- DON'T CALL THESE DIRECTLY */
|
||||
/****************************************************************************/
|
||||
|
||||
int zts_get_pico_socket(int fd, struct pico_socket *s)
|
||||
{
|
||||
int err = 0;
|
||||
if(!zt1Service) {
|
||||
DEBUG_ERROR("cannot shutdown socket. service not started. call zts_start(path) first");
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
}
|
||||
else
|
||||
#if defined(STACK_PICO)
|
||||
int zts_get_pico_socket(int fd, struct pico_socket *s)
|
||||
{
|
||||
ZeroTier::_multiplexer_lock.lock();
|
||||
// First, look for for unassigned connections
|
||||
ZeroTier::Connection *conn = ZeroTier::unmap[fd];
|
||||
// Since we found an unassigned connection, we don't need to consult the stack or tap
|
||||
// during closure - it isn't yet stitched into the clockwork
|
||||
if(conn)
|
||||
{
|
||||
s = conn->picosock;
|
||||
return 1; // unassigned
|
||||
int err = 0;
|
||||
if(!zt1Service) {
|
||||
DEBUG_ERROR("cannot shutdown socket. service not started. call zts_start(path) first");
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
}
|
||||
else // assigned
|
||||
else
|
||||
{
|
||||
std::pair<ZeroTier::Connection*, ZeroTier::SocketTap*> *p = ZeroTier::fdmap[fd];
|
||||
if(!p)
|
||||
ZeroTier::_multiplexer_lock.lock();
|
||||
// First, look for for unassigned connections
|
||||
ZeroTier::Connection *conn = ZeroTier::unmap[fd];
|
||||
// Since we found an unassigned connection, we don't need to consult the stack or tap
|
||||
// during closure - it isn't yet stitched into the clockwork
|
||||
if(conn)
|
||||
{
|
||||
DEBUG_ERROR("unable to locate connection pair.");
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
s = conn->picosock;
|
||||
return 1; // unassigned
|
||||
}
|
||||
else // found everything, begin closure
|
||||
else // assigned
|
||||
{
|
||||
s = p->first->picosock;
|
||||
return 0;
|
||||
std::pair<ZeroTier::Connection*, ZeroTier::SocketTap*> *p = ZeroTier::fdmap[fd];
|
||||
if(!p)
|
||||
{
|
||||
DEBUG_ERROR("unable to locate connection pair.");
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
}
|
||||
else // found everything, begin closure
|
||||
{
|
||||
s = p->first->picosock;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ZeroTier::_multiplexer_lock.unlock();
|
||||
}
|
||||
ZeroTier::_multiplexer_lock.unlock();
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
int zts_nsockets()
|
||||
{
|
||||
@@ -1551,8 +1571,11 @@ int zts_nsockets()
|
||||
|
||||
int zts_maxsockets()
|
||||
{
|
||||
#if defined(STACK_PICO)
|
||||
// TODO: This is only an approximation
|
||||
return PICO_MAX_TIMERS - 10;
|
||||
#endif
|
||||
return 32;
|
||||
}
|
||||
|
||||
// Starts a ZeroTier service in the background
|
||||
@@ -1618,7 +1641,7 @@ void *zts_start_service(void *thread_id) {
|
||||
ZeroTier::OSUtils::rm((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S
|
||||
+ "identity.public").c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
continue; // restart!
|
||||
}
|
||||
break; // terminate loop -- normally we don't keep restarting
|
||||
|
||||
393
src/lwIP.cpp
Normal file
393
src/lwIP.cpp
Normal file
@@ -0,0 +1,393 @@
|
||||
/*
|
||||
* ZeroTier SDK - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* --
|
||||
*
|
||||
* You can be released from the requirements of the license by purchasing
|
||||
* a commercial license. Buying such a license is mandatory as soon as you
|
||||
* develop commercial closed-source software that incorporates or links
|
||||
* directly against ZeroTier software without disclosing the source code
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
// lwIP network stack driver
|
||||
|
||||
#include "libzt.h"
|
||||
#include "SocketTap.hpp"
|
||||
#include "Utilities.hpp"
|
||||
|
||||
#include "lwIP.hpp"
|
||||
#include "netif/ethernet.h"
|
||||
#include "lwip/etharp.h"
|
||||
|
||||
err_t tapif_init(struct netif *netif)
|
||||
{
|
||||
DEBUG_INFO();
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
err_t low_level_output(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
DEBUG_INFO();
|
||||
struct pbuf *q;
|
||||
char buf[ZT_MAX_MTU+32];
|
||||
char *bufptr;
|
||||
int totalLength = 0;
|
||||
|
||||
ZeroTier::SocketTap *tap = (ZeroTier::SocketTap*)netif->state;
|
||||
bufptr = buf;
|
||||
// Copy data from each pbuf, one at a time
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
memcpy(bufptr, q->payload, q->len);
|
||||
bufptr += q->len;
|
||||
totalLength += q->len;
|
||||
}
|
||||
// Split ethernet header and feed into handler
|
||||
struct eth_hdr *ethhdr;
|
||||
ethhdr = (struct eth_hdr *)buf;
|
||||
|
||||
ZeroTier::MAC src_mac;
|
||||
ZeroTier::MAC dest_mac;
|
||||
src_mac.setTo(ethhdr->src.addr, 6);
|
||||
dest_mac.setTo(ethhdr->dest.addr, 6);
|
||||
|
||||
tap->_handler(tap->_arg,NULL,tap->_nwid,src_mac,dest_mac,
|
||||
ZeroTier::Utils::ntoh((uint16_t)ethhdr->type),0,buf + sizeof(struct eth_hdr),totalLength - sizeof(struct eth_hdr));
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
namespace ZeroTier
|
||||
{
|
||||
void lwIP::lwip_init_interface(SocketTap *tap, const InetAddress &ip)
|
||||
{
|
||||
DEBUG_INFO();
|
||||
Mutex::Lock _l(tap->_ips_m);
|
||||
|
||||
if (std::find(tap->_ips.begin(),tap->_ips.end(),ip) == tap->_ips.end()) {
|
||||
tap->_ips.push_back(ip);
|
||||
std::sort(tap->_ips.begin(),tap->_ips.end());
|
||||
#if defined(LIBZT_IPV4)
|
||||
if (ip.isV4()) {
|
||||
// Set IP
|
||||
static ip_addr_t ipaddr, netmask, gw;
|
||||
IP4_ADDR(&gw,127,0,0,1);
|
||||
ipaddr.addr = *((u32_t *)ip.rawIpData());
|
||||
netmask.addr = *((u32_t *)ip.netmask().rawIpData());
|
||||
netif_add(&(tap->lwipdev),&ipaddr, &netmask, &gw, NULL, tapif_init, ethernet_input);
|
||||
tap->lwipdev.state = tap;
|
||||
tap->lwipdev.output = etharp_output;
|
||||
tap->_mac.copyTo(tap->lwipdev.hwaddr, 6);
|
||||
tap->lwipdev.mtu = tap->_mtu;
|
||||
tap->lwipdev.name[0] = 'l';
|
||||
tap->lwipdev.name[1] = '4';
|
||||
tap->lwipdev.linkoutput = low_level_output;
|
||||
tap->lwipdev.hwaddr_len = 6;
|
||||
tap->lwipdev.flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
|
||||
netif_set_default(&(tap->lwipdev));
|
||||
netif_set_up(&(tap->lwipdev));
|
||||
DEBUG_INFO("addr=%s, netmask=%s", ip.toString().c_str(), ip.netmask().toString().c_str());
|
||||
}
|
||||
#endif
|
||||
#if defined(LIBZT_IPV6)
|
||||
if(ip.isV6()) {
|
||||
DEBUG_INFO("local_addr=%s", ip.toString().c_str());
|
||||
static ip6_addr_t addr6;
|
||||
struct sockaddr_in6 in6;
|
||||
memcpy(in6.sin6_addr.s6_addr,ip.rawIpData(),16);
|
||||
in6_to_ip6((ip6_addr *)&addr6, &in6);
|
||||
tap->lwipdev6.mtu = tap->_mtu;
|
||||
tap->lwipdev6.name[0] = 'l';
|
||||
tap->lwipdev6.name[1] = '6';
|
||||
tap->lwipdev6.hwaddr_len = 6;
|
||||
tap->lwipdev6.linkoutput = low_level_output;
|
||||
tap->lwipdev6.ip6_autoconfig_enabled = 1;
|
||||
tap->_mac.copyTo(tap->lwipdev6.hwaddr, tap->lwipdev6.hwaddr_len);
|
||||
netif_create_ip6_linklocal_address(&(tap->lwipdev6), 1);
|
||||
netif_add(&(tap->lwipdev6), NULL, tapif_init, ethernet_input);
|
||||
netif_set_default(&(tap->lwipdev6));
|
||||
netif_set_up(&(tap->lwipdev6));
|
||||
netif_ip6_addr_set_state(&(tap->lwipdev6), 1, IP6_ADDR_TENTATIVE);
|
||||
ip6_addr_copy(ip_2_ip6(tap->lwipdev6.ip6_addr[1]), addr6);
|
||||
tap->lwipdev6.output_ip6 = ethip6_output;
|
||||
tap->lwipdev6.state = tap;
|
||||
tap->lwipdev6.flags = NETIF_FLAG_LINK_UP | NETIF_FLAG_UP;
|
||||
DEBUG_INFO("addr=%s, netmask=%s", ip.toString().c_str(), ip.netmask().toString().c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void lwIP::lwip_loop(SocketTap *tap)
|
||||
{
|
||||
DEBUG_INFO();
|
||||
uint64_t prev_tcp_time = 0, prev_status_time = 0, prev_discovery_time = 0;
|
||||
while(tap->_run)
|
||||
{
|
||||
uint64_t now = OSUtils::now();
|
||||
uint64_t since_tcp = now - prev_tcp_time;
|
||||
uint64_t since_discovery = now - prev_discovery_time;
|
||||
uint64_t since_status = now - prev_status_time;
|
||||
uint64_t tcp_remaining = LWIP_TCP_TIMER_INTERVAL;
|
||||
uint64_t discovery_remaining = 5000;
|
||||
|
||||
#if defined(LIBZT_IPV6)
|
||||
#define DISCOVERY_INTERVAL 1000
|
||||
#elif defined(LIBZT_IPV4)
|
||||
#define DISCOVERY_INTERVAL ARP_TMR_INTERVAL
|
||||
#endif
|
||||
// Main TCP/ETHARP timer section
|
||||
if (since_tcp >= LWIP_TCP_TIMER_INTERVAL) {
|
||||
prev_tcp_time = now;
|
||||
tcp_tmr();
|
||||
}
|
||||
else {
|
||||
tcp_remaining = LWIP_TCP_TIMER_INTERVAL - since_tcp;
|
||||
}
|
||||
if (since_discovery >= DISCOVERY_INTERVAL) {
|
||||
prev_discovery_time = now;
|
||||
#if defined(LIBZT_IPV4)
|
||||
etharp_tmr();
|
||||
#endif
|
||||
#if defined(LIBZT_IPV6)
|
||||
nd6_tmr();
|
||||
#endif
|
||||
} else {
|
||||
discovery_remaining = DISCOVERY_INTERVAL - since_discovery;
|
||||
}
|
||||
tap->_phy.poll((unsigned long)std::min(tcp_remaining,discovery_remaining));
|
||||
}
|
||||
}
|
||||
|
||||
void lwIP::lwip_rx(SocketTap *tap, const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
|
||||
{
|
||||
DEBUG_INFO();
|
||||
struct pbuf *p,*q;
|
||||
if (!tap->_enabled)
|
||||
return;
|
||||
struct eth_hdr ethhdr;
|
||||
from.copyTo(ethhdr.src.addr, 6);
|
||||
to.copyTo(ethhdr.dest.addr, 6);
|
||||
ethhdr.type = ZeroTier::Utils::hton((uint16_t)etherType);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, len+sizeof(struct eth_hdr), PBUF_POOL);
|
||||
if (p != NULL) {
|
||||
const char *dataptr = reinterpret_cast<const char *>(data);
|
||||
// First pbuf gets ethernet header at start
|
||||
q = p;
|
||||
if (q->len < sizeof(ethhdr)) {
|
||||
DEBUG_ERROR("dropped packet: first pbuf smaller than ethernet header");
|
||||
return;
|
||||
}
|
||||
memcpy(q->payload,ðhdr,sizeof(ethhdr));
|
||||
memcpy((char*)q->payload + sizeof(ethhdr),dataptr,q->len - sizeof(ethhdr));
|
||||
dataptr += q->len - sizeof(ethhdr);
|
||||
|
||||
// Remaining pbufs (if any) get rest of data
|
||||
while ((q = q->next)) {
|
||||
memcpy(q->payload,dataptr,q->len);
|
||||
dataptr += q->len;
|
||||
}
|
||||
}
|
||||
else {
|
||||
DEBUG_ERROR("dropped packet: no pbufs available");
|
||||
return;
|
||||
}
|
||||
{
|
||||
#if defined(LIBZT_IPV6)
|
||||
if(tap->lwipdev6.input(p, &(tap->lwipdev6)) != ERR_OK) {
|
||||
DEBUG_ERROR("error while feeding frame into stack lwipdev6");
|
||||
}
|
||||
#endif
|
||||
#if defined(LIBZT_IPV4)
|
||||
if(tap->lwipdev.input(p, &(tap->lwipdev)) != ERR_OK) {
|
||||
DEBUG_ERROR("error while feeding frame into stack lwipdev");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int lwIP::lwip_Socket(void **pcb, int socket_family, int socket_type, int protocol)
|
||||
{
|
||||
// TODO: check lwIP timers, and max sockets
|
||||
DEBUG_INFO();
|
||||
if(socket_type == SOCK_STREAM) {
|
||||
struct tcp_pcb *new_tcp_PCB = tcp_new();
|
||||
*pcb = new_tcp_PCB;
|
||||
return ERR_OK;
|
||||
}
|
||||
if(socket_type == SOCK_DGRAM) {
|
||||
struct udp_pcb *new_udp_PCB = udp_new();
|
||||
*pcb = new_udp_PCB;
|
||||
return ERR_OK;
|
||||
}
|
||||
if(socket_type == SOCK_RAW) {
|
||||
DEBUG_ERROR("SOCK_RAW, not currently supported.");
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int lwIP::lwip_Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
DEBUG_INFO();
|
||||
}
|
||||
|
||||
int lwIP::lwip_Bind(SocketTap *tap, Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
DEBUG_INFO();
|
||||
ip_addr_t ba;
|
||||
char addrstr[INET6_ADDRSTRLEN];
|
||||
int port = 0, err = 0;
|
||||
|
||||
#if defined(LIBZT_IPV4)
|
||||
DEBUG_ERROR("A");
|
||||
struct sockaddr_in *in4;
|
||||
if(addr->sa_family == AF_INET) {
|
||||
DEBUG_ERROR("A");
|
||||
in4 = (struct sockaddr_in *)addr;
|
||||
DEBUG_ERROR("A");
|
||||
inet_ntop(AF_INET, &(in4->sin_addr), addrstr, INET_ADDRSTRLEN);
|
||||
DEBUG_ERROR("A");
|
||||
DEBUG_INFO("%s:%d", addrstr, lwip_ntohs(in4->sin_port));
|
||||
}
|
||||
ba = convert_ip(in4);
|
||||
port = lwip_ntohs(in4->sin_port);
|
||||
DEBUG_INFO("port=%d", port);
|
||||
DEBUG_INFO("port=%d", lwip_ntohs(port));
|
||||
#endif
|
||||
#if defined(LIBZT_IPV6)
|
||||
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&addr;
|
||||
in6_to_ip6((ip6_addr *)&ba, in6);
|
||||
if(addr->sa_family == AF_INET6) {
|
||||
struct sockaddr_in6 *connaddr6 = (struct sockaddr_in6 *)addr;
|
||||
inet_ntop(AF_INET6, &(connaddr6->sin6_addr), addrstr, INET6_ADDRSTRLEN);
|
||||
DEBUG_INFO("%s:%d", addrstr, lwip_ntohs(connaddr6->sin6_port));
|
||||
}
|
||||
#endif
|
||||
if(conn->socket_type == SOCK_DGRAM) {
|
||||
err = udp_bind((struct udp_pcb*)conn->pcb, (const ip_addr_t *)&ba, port);
|
||||
if(err == ERR_USE) {
|
||||
err = -1;
|
||||
errno = EADDRINUSE; // port in use
|
||||
}
|
||||
else {
|
||||
// set the recv callback
|
||||
udp_recv((struct udp_pcb*)conn->pcb, nc_udp_recved, new ConnectionPair(tap, conn));
|
||||
err = ERR_OK;
|
||||
errno = ERR_OK; // success
|
||||
}
|
||||
}
|
||||
else if (conn->socket_type == SOCK_STREAM) {
|
||||
err = tcp_bind((struct tcp_pcb*)conn->pcb, (const ip_addr_t *)&ba, port);
|
||||
if(err != ERR_OK) {
|
||||
DEBUG_ERROR("err=%d", err);
|
||||
if(err == ERR_USE){
|
||||
err = -1;
|
||||
errno = EADDRINUSE;
|
||||
}
|
||||
if(err == ERR_MEM){
|
||||
err = -1;
|
||||
errno = ENOMEM;
|
||||
}
|
||||
if(err == ERR_BUF){
|
||||
err = -1;
|
||||
errno = ENOMEM;
|
||||
}
|
||||
}
|
||||
else {
|
||||
err = ERR_OK;
|
||||
errno = ERR_OK; // success
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int lwIP::lwip_Listen(SocketTap *tap, PhySocket *sock, PhySocket *rpcSock, void **uptr, struct listen_st *listen_rpc)
|
||||
{
|
||||
DEBUG_INFO();
|
||||
// to be implemented
|
||||
}
|
||||
|
||||
int lwIP::lwip_Read(SocketTap *tap, PhySocket *sock, void **uptr, bool lwip_invoked)
|
||||
{
|
||||
DEBUG_EXTRA();
|
||||
// to be implemented
|
||||
}
|
||||
|
||||
int lwIP::lwip_Write(SocketTap *tap, Connection *conn)
|
||||
{
|
||||
DEBUG_EXTRA("conn=%p", (void*)&conn);
|
||||
// to be implemented
|
||||
}
|
||||
|
||||
int lwIP::lwip_Close(SocketTap *tap, PhySocket *sock, Connection *conn)
|
||||
{
|
||||
DEBUG_INFO();
|
||||
// to be implemented
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* Callbacks from lwIP stack */
|
||||
/****************************************************************************/
|
||||
|
||||
err_t lwIP::nc_recved(void *arg, struct tcp_pcb *PCB, struct pbuf *p, err_t err)
|
||||
{
|
||||
DEBUG_INFO();
|
||||
// to be implemented
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
err_t lwIP::nc_accept(void *arg, struct tcp_pcb *newPCB, err_t err)
|
||||
{
|
||||
DEBUG_INFO();
|
||||
// to be implemented
|
||||
return -1;
|
||||
}
|
||||
|
||||
void lwIP::nc_udp_recved(void * arg, struct udp_pcb * upcb, struct pbuf * p, const ip_addr_t * addr, u16_t port)
|
||||
{
|
||||
DEBUG_INFO();
|
||||
// to be implemented
|
||||
}
|
||||
|
||||
err_t lwIP::nc_sent(void* arg, struct tcp_pcb *PCB, u16_t len)
|
||||
{
|
||||
DEBUG_EXTRA("pcb=%p", (void*)&PCB);
|
||||
// to be implemented
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
err_t lwIP::nc_connected(void *arg, struct tcp_pcb *PCB, err_t err)
|
||||
{
|
||||
DEBUG_ATTN("pcb=%p", (void*)&PCB);
|
||||
// to be implemented
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
err_t lwIP::nc_poll(void* arg, struct tcp_pcb *PCB)
|
||||
{
|
||||
DEBUG_INFO();
|
||||
// to be implemented
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void lwIP::nc_err(void *arg, err_t err)
|
||||
{
|
||||
DEBUG_INFO();
|
||||
// to be implemented
|
||||
}
|
||||
}
|
||||
204
src/lwIP.hpp
Normal file
204
src/lwIP.hpp
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* ZeroTier SDK - Network Virtualization Everywhere
|
||||
* Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* --
|
||||
*
|
||||
* You can be released from the requirements of the license by purchasing
|
||||
* a commercial license. Buying such a license is mandatory as soon as you
|
||||
* develop commercial closed-source software that incorporates or links
|
||||
* directly against ZeroTier software without disclosing the source code
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
// lwIP network stack driver
|
||||
|
||||
#ifndef ZT_LWIP_HPP
|
||||
#define ZT_LWIP_HPP
|
||||
|
||||
#include <stdio.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/init.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/priv/tcp_priv.h"
|
||||
|
||||
#include "Mutex.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
|
||||
#include "libzt.h"
|
||||
#include "SocketTap.hpp"
|
||||
|
||||
struct tcp_pcb;
|
||||
struct netif;
|
||||
|
||||
#if defined(LIBZT_IPV4)
|
||||
#define LWIP_NETIF_ADD_SIG struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input
|
||||
#define LWIP_ETHARP_OUTPUT_SIG struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr
|
||||
#endif
|
||||
#if defined(LIBZT_IPV6)
|
||||
#define LWIP_NETIF_ADD_SIG struct netif *netif, void *state, netif_init_fn init, netif_input_fn input
|
||||
#define LWIP_ETHIP6_OUTPUT_SIG struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr
|
||||
#define LWIP_ETHARP_OUTPUT_SIG struct netif *netif, struct pbuf *q, const ip6_addr_t *ipaddr
|
||||
#define LWIP_NETIF_IP6_ADDR_SET_STATE_SIG struct netif* netif, s8_t addr_idx, u8_t state
|
||||
#define LWIP_NETIF_CREATE_IP6_LINKLOCAL_ADDRESS_SIG struct netif *netif, u8_t from_mac_48bit
|
||||
#endif
|
||||
|
||||
#define LWIP_PBUF_FREE_SIG struct pbuf *p
|
||||
#define LWIP_PBUF_ALLOC_SIG pbuf_layer layer, u16_t length, pbuf_type type
|
||||
#define LWIP_HTONS_SIG u16_t x
|
||||
#define LWIP_NTOHS_SIG u16_t x
|
||||
|
||||
#define LWIP_UDP_NEW_SIG void
|
||||
#define LWIP_UDP_CONNECT_SIG struct udp_pcb * pcb, const ip_addr_t * ipaddr, u16_t port
|
||||
#define LWIP_UDP_SEND_SIG struct udp_pcb * pcb, struct pbuf * p
|
||||
#define LWIP_UDP_SENDTO_SIG struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, u16_t dst_port
|
||||
#define LWIP_UDP_RECV_SIG struct udp_pcb * pcb, void (* recv)(void * arg, struct udp_pcb * upcb, struct pbuf * p, ip_addr_t * addr, u16_t port), void * recv_arg
|
||||
#define LWIP_UDP_RECVED_SIG struct udp_pcb * pcb, u16_t len
|
||||
#define LWIP_UDP_BIND_SIG struct udp_pcb * pcb, const ip_addr_t * ipaddr, u16_t port
|
||||
#define LWIP_UDP_REMOVE_SIG struct udp_pcb *pcb
|
||||
|
||||
#define LWIP_TCP_WRITE_SIG struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags
|
||||
#define LWIP_TCP_SENT_SIG struct tcp_pcb * pcb, err_t (* sent)(void * arg, struct tcp_pcb * tpcb, u16_t len)
|
||||
#define LWIP_TCP_NEW_SIG void
|
||||
#define LWIP_TCP_RECV_SIG struct tcp_pcb * pcb, err_t (* recv)(void * arg, struct tcp_pcb * tpcb, struct pbuf * p, err_t err)
|
||||
#define LWIP_TCP_RECVED_SIG struct tcp_pcb * pcb, u16_t len
|
||||
//#define LWIP_TCP_SNDBUF_SIG struct tcp_pcb * pcb
|
||||
#define LWIP_TCP_CONNECT_SIG struct tcp_pcb * pcb, const ip_addr_t * ipaddr, u16_t port, err_t (* connected)(void * arg, struct tcp_pcb * tpcb, err_t err)
|
||||
#define LWIP_TCP_RECV_SIG struct tcp_pcb * pcb, err_t (* recv)(void * arg, struct tcp_pcb * tpcb, struct pbuf * p, err_t err)
|
||||
#define LWIP_TCP_ERR_SIG struct tcp_pcb * pcb, void (* err)(void * arg, err_t err)
|
||||
#define LWIP_TCP_POLL_SIG struct tcp_pcb * pcb, err_t (* poll)(void * arg, struct tcp_pcb * tpcb), u8_t interval
|
||||
#define LWIP_TCP_ARG_SIG struct tcp_pcb * pcb, void * arg
|
||||
#define LWIP_TCP_CLOSE_SIG struct tcp_pcb * pcb
|
||||
#define LWIP_TCP_ABORT_SIG struct tcp_pcb * pcb
|
||||
#define LWIP_TCP_OUTPUT_SIG struct tcp_pcb * pcb
|
||||
#define LWIP_TCP_ACCEPT_SIG struct tcp_pcb * pcb, err_t (* accept)(void * arg, struct tcp_pcb * newpcb, err_t err)
|
||||
#define LWIP_TCP_LISTEN_SIG struct tcp_pcb * pcb
|
||||
#define LWIP_TCP_LISTEN_WITH_BACKLOG_SIG struct tcp_pcb * pcb, u8_t backlog
|
||||
#define LWIP_TCP_BIND_SIG struct tcp_pcb * pcb, const ip_addr_t * ipaddr, u16_t port
|
||||
#define LWIP_TCP_INPUT_SIG struct pbuf *p, struct netif *inp
|
||||
|
||||
#define LWIP_ETHERNET_INPUT_SIG struct pbuf *p, struct netif *netif
|
||||
#define LWIP_IP_INPUT_SIG struct pbuf *p, struct netif *inp
|
||||
#define LWIP_NETIF_SET_DEFAULT_SIG struct netif *netif
|
||||
#define LWIP_NETIF_SET_UP_SIG struct netif *netif
|
||||
#define LWIP_NETIF_POLL_SIG struct netif *netif
|
||||
|
||||
|
||||
#if defined(LIBZT_IPV4)
|
||||
extern "C" err_t etharp_output(LWIP_ETHARP_OUTPUT_SIG);
|
||||
#endif
|
||||
#if defined(LIBZT_IPV6)
|
||||
extern "C" void nd6_tmr(void);
|
||||
extern "C" void netif_ip6_addr_set_state(LWIP_NETIF_IP6_ADDR_SET_STATE_SIG);
|
||||
extern "C" void netif_create_ip6_linklocal_address(LWIP_NETIF_CREATE_IP6_LINKLOCAL_ADDRESS_SIG);
|
||||
extern "C" err_t _ethip6_output(LWIP_ETHIP6_OUTPUT_SIG);
|
||||
#endif
|
||||
|
||||
extern "C" void lwip_init();
|
||||
extern "C" err_t ethernet_input(LWIP_ETHERNET_INPUT_SIG);
|
||||
extern "C" void netif_poll(LWIP_NETIF_POLL_SIG);
|
||||
|
||||
//extern "C" err_t etharp_output(LWIP_ETHARP_OUTPUT_SIG);
|
||||
//extern "C" err_t ethernet_input(LWIP_ETHERNET_INPUT_SIG);
|
||||
extern "C" void netif_set_up(LWIP_NETIF_SET_UP_SIG);
|
||||
extern "C" void netif_set_default(LWIP_NETIF_SET_DEFAULT_SIG);
|
||||
//extern "C" struct netif *netif_add(LWIP_NETIF_ADD_SIG);
|
||||
extern "C" err_t tapif_init(struct netif *netif);
|
||||
extern "C" err_t low_level_output(struct netif *netif, struct pbuf *p);
|
||||
extern "C" err_t tcp_write(LWIP_TCP_WRITE_SIG);
|
||||
extern "C" void tcp_sent(LWIP_TCP_SENT_SIG);
|
||||
extern "C" struct tcp_pcb *tcp_new(LWIP_TCP_NEW_SIG);
|
||||
//u16_t tcp_sndbuf(struct tcp_pcb * pcb);
|
||||
extern "C" err_t tcp_connect(LWIP_TCP_CONNECT_SIG);
|
||||
extern "C" struct udp_pcb *udp_new(LWIP_UDP_NEW_SIG);
|
||||
extern "C" err_t udp_connect(LWIP_UDP_CONNECT_SIG);
|
||||
extern "C" err_t udp_send(LWIP_UDP_SEND_SIG);
|
||||
extern "C" err_t udp_sendto(LWIP_UDP_SENDTO_SIG);
|
||||
//extern "C" void udp_recv(LWIP_UDP_RECV_SIG);
|
||||
extern "C" void udp_recved(LWIP_UDP_RECVED_SIG);
|
||||
extern "C" err_t udp_bind(LWIP_UDP_BIND_SIG);
|
||||
extern "C" void udp_remove(LWIP_UDP_REMOVE_SIG);
|
||||
extern "C" void tcp_recv(LWIP_TCP_RECV_SIG);
|
||||
extern "C" void tcp_recved(LWIP_TCP_RECVED_SIG);
|
||||
extern "C" void tcp_err(LWIP_TCP_ERR_SIG);
|
||||
extern "C" void tcp_poll(LWIP_TCP_POLL_SIG);
|
||||
extern "C" void tcp_arg(LWIP_TCP_ARG_SIG);
|
||||
extern "C" err_t tcp_close(LWIP_TCP_CLOSE_SIG);
|
||||
extern "C" void tcp_abort(LWIP_TCP_ABORT_SIG);
|
||||
extern "C" err_t tcp_output(LWIP_TCP_OUTPUT_SIG);
|
||||
extern "C" void tcp_accept(LWIP_TCP_ACCEPT_SIG);
|
||||
//extern "C" struct tcp_pcb *tcp_listen(LWIP_TCP_LISTEN_SIG);
|
||||
extern "C" struct tcp_pcb *tcp_listen_with_backlog(LWIP_TCP_LISTEN_WITH_BACKLOG_SIG);
|
||||
extern "C" err_t tcp_bind(LWIP_TCP_BIND_SIG);
|
||||
extern "C" void etharp_tmr(void);
|
||||
extern "C" void tcp_tmr(void);
|
||||
extern "C" u8_t pbuf_free(LWIP_PBUF_FREE_SIG);
|
||||
extern "C" struct pbuf *pbuf_alloc(LWIP_PBUF_ALLOC_SIG);
|
||||
extern "C" u16_t lwip_htons(LWIP_HTONS_SIG);
|
||||
extern "C" u16_t lwip_ntohs(LWIP_NTOHS_SIG);
|
||||
extern "C" void tcp_input(LWIP_TCP_INPUT_SIG);
|
||||
extern "C" err_t ip_input(LWIP_IP_INPUT_SIG);
|
||||
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class SocketTap;
|
||||
struct Connection;
|
||||
|
||||
class lwIP
|
||||
{
|
||||
public:
|
||||
|
||||
/*
|
||||
* Set up an interface in the network stack for the SocketTap
|
||||
*/
|
||||
void lwip_init_interface(SocketTap *tap, const InetAddress &ip);
|
||||
|
||||
/*
|
||||
* Main stack loop
|
||||
*/
|
||||
void lwip_loop(SocketTap *tap);
|
||||
|
||||
/*
|
||||
* Packets from the ZeroTier virtual wire enter the stack here
|
||||
*/
|
||||
void lwip_rx(SocketTap *tap, const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len);
|
||||
|
||||
int lwip_Socket(void **pcb, int socket_family, int socket_type, int protocol);
|
||||
int lwip_Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
int lwip_Bind(SocketTap *tap, Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
int lwip_Listen(SocketTap *tap, PhySocket *sock, PhySocket *rpcSock, void **uptr, struct listen_st *listen_rpc);
|
||||
int lwip_Read(SocketTap *tap, PhySocket *sock, void **uptr, bool lwip_invoked);
|
||||
int lwip_Write(SocketTap *tap, Connection *conn);
|
||||
int lwip_Close(SocketTap *tap, PhySocket *sock, Connection *conn);
|
||||
|
||||
static err_t nc_recved(void *arg, struct tcp_pcb *PCB, struct pbuf *p, err_t err);
|
||||
static err_t nc_accept(void *arg, struct tcp_pcb *newPCB, err_t err);
|
||||
static void nc_udp_recved(void * arg, struct udp_pcb * upcb, struct pbuf * p, const ip_addr_t * addr, u16_t port);
|
||||
static void nc_err(void *arg, err_t err);
|
||||
static err_t nc_poll(void* arg, struct tcp_pcb *PCB);
|
||||
static err_t nc_sent(void *arg, struct tcp_pcb *PCB, u16_t len);
|
||||
static err_t nc_connected(void *arg, struct tcp_pcb *PCB, err_t err);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -502,6 +502,58 @@ namespace ZeroTier {
|
||||
}
|
||||
return loop_score;
|
||||
}
|
||||
|
||||
int picoTCP::pico_Socket(struct pico_socket **p, int socket_family, int socket_type, int protocol)
|
||||
{
|
||||
int err = 0;
|
||||
if(pico_ntimers() >= PICO_MAX_TIMERS) {
|
||||
DEBUG_ERROR("cannot create additional socket, see PICO_MAX_TIMERS. current = %d", pico_ntimers());
|
||||
errno = EMFILE;
|
||||
err = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int protocol_version = 0;
|
||||
struct pico_socket *psock;
|
||||
if(socket_family == AF_INET)
|
||||
protocol_version = PICO_PROTO_IPV4;
|
||||
if(socket_family == AF_INET6)
|
||||
protocol_version = PICO_PROTO_IPV6;
|
||||
|
||||
if(socket_type == SOCK_DGRAM) {
|
||||
DEBUG_ERROR("SOCK_DGRAM");
|
||||
psock = pico_socket_open(
|
||||
protocol_version, PICO_PROTO_UDP, &ZeroTier::picoTCP::pico_cb_socket_activity);
|
||||
if(psock) { // configure size of UDP SND/RCV buffers
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
if(socket_type == SOCK_STREAM) {
|
||||
psock = pico_socket_open(
|
||||
protocol_version, PICO_PROTO_TCP, &ZeroTier::picoTCP::pico_cb_socket_activity);
|
||||
if(psock) { // configure size of TCP SND/RCV buffers
|
||||
int tx_buf_sz = ZT_STACK_TCP_SOCKET_TX_SZ;
|
||||
int rx_buf_sz = ZT_STACK_TCP_SOCKET_RX_SZ;
|
||||
int t_err = 0;
|
||||
int value = 1;
|
||||
pico_socket_setoption(psock, PICO_TCP_NODELAY, &value);
|
||||
|
||||
if((t_err = pico_socket_setoption(psock, PICO_SOCKET_OPT_SNDBUF, &tx_buf_sz)) < 0)
|
||||
DEBUG_ERROR("unable to set SNDBUF size, err = %d, pico_err = %d", t_err, pico_err);
|
||||
if((t_err = pico_socket_setoption(psock, PICO_SOCKET_OPT_RCVBUF, &rx_buf_sz)) < 0)
|
||||
DEBUG_ERROR("unable to set RCVBUF size, err = %d, pico_err = %d", t_err, pico_err);
|
||||
|
||||
if(ZT_SOCK_BEHAVIOR_LINGER) {
|
||||
int linger_time_ms = ZT_SOCK_BEHAVIOR_LINGER_TIME;
|
||||
if((t_err = pico_socket_setoption(psock, PICO_SOCKET_OPT_LINGER, &linger_time_ms)) < 0)
|
||||
DEBUG_ERROR("unable to set LINGER, err = %d, pico_err = %d", t_err, pico_err);
|
||||
}
|
||||
}
|
||||
}
|
||||
*p = psock;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int picoTCP::pico_Connect(Connection *conn, int fd, const struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
|
||||
@@ -121,7 +121,12 @@ namespace ZeroTier
|
||||
* Packets from the ZeroTier virtual wire enter the stack here
|
||||
*/
|
||||
void pico_rx(SocketTap *tap, const ZeroTier::MAC &from,const ZeroTier::MAC &to,unsigned int etherType,const void *data,unsigned int len);
|
||||
|
||||
|
||||
/*
|
||||
* Creates a stack-specific "socket" or "connection object"
|
||||
*/
|
||||
int pico_Socket(struct pico_socket **p, int socket_family, int socket_type, int protocol);
|
||||
|
||||
/*
|
||||
* Connect to remote host via userspace network stack interface - Called from SocketTap
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user