Stubbed out some of the more obscure socket options for both drivers
This commit is contained in:
@@ -84,6 +84,42 @@ struct zts_ifreq {
|
||||
|
||||
#endif
|
||||
|
||||
// Provide missing optnames for setsockopt() implementations
|
||||
#ifdef _WIN32
|
||||
#ifdef _WIN64
|
||||
#else
|
||||
#endif
|
||||
#elif __APPLE__
|
||||
#define IP_BIND_ADDRESS_NO_PORT 201
|
||||
#define IP_FREEBIND 202
|
||||
#define IP_MTU 203
|
||||
#define IP_MTU_DISCOVER 204
|
||||
#define IP_MULTICAST_ALL 205
|
||||
#define IP_NODEFRAG 206
|
||||
#define IP_RECVORIGDSTADDR 207
|
||||
#define IP_ROUTER_ALERT 208
|
||||
#define IP_TRANSPARENT 209
|
||||
#define TCP_INFO 210
|
||||
#define SO_STYLE 100
|
||||
#define TCP_CORK 101
|
||||
#define TCP_DEFER_ACCEPT 102
|
||||
#define TCP_KEEPIDLE 103
|
||||
#define TCP_LINGER2 104
|
||||
#define TCP_QUICKACK 105
|
||||
#define TCP_SYNCNT 106
|
||||
#define TCP_WINDOW_CLAMP 107
|
||||
#define UDP_CORK 108
|
||||
#elif __linux__
|
||||
#define SO_STYLE 100
|
||||
#define UDP_CORK 101
|
||||
#define IP_BIND_ADDRESS_NO_PORT 201
|
||||
#define IP_NODEFRAG 206
|
||||
#elif __unix__
|
||||
#elif defined(_POSIX_VERSION)
|
||||
#else
|
||||
# error "Unknown platform"
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
/* Legend */
|
||||
/****************************************************************************/
|
||||
@@ -574,12 +610,12 @@ bool can_provision_new_socket(int socket_type);
|
||||
* haven't passed that limit. Someday if multiple stacks are used simultaneously
|
||||
* the logic for this function should change accordingly.
|
||||
*/
|
||||
int zts_nsockets();
|
||||
int zts_num_active_virt_sockets();
|
||||
|
||||
/*
|
||||
* Returns maximum number of sockets allowed by network stack
|
||||
*/
|
||||
int zts_maxsockets();
|
||||
int zts_maxsockets(int socket_type);
|
||||
|
||||
int pico_ntimers();
|
||||
|
||||
@@ -596,31 +632,31 @@ ZeroTier::VirtualTap *getAnyTap();
|
||||
/*
|
||||
* Returns a pointer to a VirtualSocket for a given fd
|
||||
*/
|
||||
ZeroTier::VirtualSocket *get_virtual_socket(int fd);
|
||||
ZeroTier::VirtualSocket *get_virt_socket(int fd);
|
||||
|
||||
/*
|
||||
* Removes a VirtualSocket
|
||||
*/
|
||||
int del_virtual_socket(int fd);
|
||||
int del_virt_socket(int fd);
|
||||
|
||||
/*
|
||||
* Adds a virtualSocket
|
||||
*/
|
||||
int add_unassigned_virtual_socket(int fd, ZeroTier::VirtualSocket *vs);
|
||||
int add_unassigned_virt_socket(int fd, ZeroTier::VirtualSocket *vs);
|
||||
/*
|
||||
* Removes unassigned VirtualSocket
|
||||
*/
|
||||
int del_unassigned_virtual_socket(int fd);
|
||||
int del_unassigned_virt_socket(int fd);
|
||||
|
||||
/*
|
||||
* Adds an assigned VirtualSocket
|
||||
*/
|
||||
int add_assigned_virtual_socket(ZeroTier::VirtualTap *tap, ZeroTier::VirtualSocket *vs, int fd);
|
||||
int add_assigned_virt_socket(ZeroTier::VirtualTap *tap, ZeroTier::VirtualSocket *vs, int fd);
|
||||
|
||||
/*
|
||||
* Removes an assigned VirtualSocket
|
||||
*/
|
||||
int del_assigned_virtual_socket(ZeroTier::VirtualTap *tap, ZeroTier::VirtualSocket *vs, int fd);
|
||||
int del_assigned_virt_socket(ZeroTier::VirtualTap *tap, ZeroTier::VirtualSocket *vs, int fd);
|
||||
|
||||
/*
|
||||
* Gets a pair of associated virtual objects (VirtualSocket bound to a VirtualTap)
|
||||
@@ -628,9 +664,9 @@ int del_assigned_virtual_socket(ZeroTier::VirtualTap *tap, ZeroTier::VirtualSock
|
||||
std::pair<ZeroTier::VirtualSocket*, ZeroTier::VirtualTap*> *get_assigned_virtual_pair(int fd);
|
||||
|
||||
/*
|
||||
* Destroys all virtual tap devices
|
||||
* Disable all virtual tap devices
|
||||
*/
|
||||
void dismantleTaps();
|
||||
void disableTaps();
|
||||
|
||||
/*
|
||||
* Get device ID (from file)
|
||||
|
||||
@@ -61,8 +61,6 @@ class VirtualTap;
|
||||
|
||||
extern std::vector<void*> vtaps;
|
||||
|
||||
// static bool picodev_initialized;
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
int VirtualTap::devno = 0;
|
||||
@@ -135,12 +133,18 @@ namespace ZeroTier {
|
||||
if (picostack) {
|
||||
picostack->pico_register_address(this, ip);
|
||||
return true;
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if (lwipstack) {
|
||||
lwipstack->lwip_init_interface(this, ip);
|
||||
return true;
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
@@ -148,12 +152,13 @@ namespace ZeroTier {
|
||||
|
||||
bool VirtualTap::addIp(const InetAddress &ip)
|
||||
{
|
||||
int err = false;
|
||||
#if defined(NO_STACK)
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
DEBUG_INFO("addIp (%s)", ip.toString(ipbuf));
|
||||
_ips.push_back(ip);
|
||||
std::sort(_ips.begin(),_ips.end());
|
||||
return true;
|
||||
err = true;
|
||||
#endif
|
||||
#if defined(STACK_PICO) || defined(STACK_LWIP)
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
@@ -165,16 +170,18 @@ namespace ZeroTier {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
err = false;
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
bool VirtualTap::removeIp(const InetAddress &ip)
|
||||
{
|
||||
Mutex::Lock _l(_ips_m);
|
||||
std::vector<InetAddress>::iterator i(std::find(_ips.begin(),_ips.end(),ip));
|
||||
if (i == _ips.end())
|
||||
if (i == _ips.end()) {
|
||||
return false;
|
||||
}
|
||||
_ips.erase(i);
|
||||
if (ip.isV4()) {
|
||||
// FIXME: De-register from network stacks
|
||||
@@ -197,11 +204,15 @@ namespace ZeroTier {
|
||||
#if defined(STACK_PICO)
|
||||
if (picostack) {
|
||||
picostack->pico_eth_rx(this,from,to,etherType,data,len);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
}
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if (lwipstack) {
|
||||
lwipstack->lwip_eth_rx(this,from,to,etherType,data,len);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -257,9 +268,7 @@ namespace ZeroTier {
|
||||
|
||||
void VirtualTap::setMtu(unsigned int mtu)
|
||||
{
|
||||
if (_mtu != mtu) {
|
||||
_mtu = mtu;
|
||||
}
|
||||
_mtu = mtu;
|
||||
}
|
||||
|
||||
void VirtualTap::threadMain()
|
||||
@@ -275,6 +284,8 @@ namespace ZeroTier {
|
||||
//addIp(localhost); // Add a single link to localhost to the picoTCP device (TODO: should be placed elsewhere)
|
||||
picostack->pico_loop(this);
|
||||
}
|
||||
} else {
|
||||
handle_general_failure();
|
||||
}
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
@@ -283,33 +294,37 @@ namespace ZeroTier {
|
||||
#endif
|
||||
}
|
||||
|
||||
void VirtualTap::phyOnUnixClose(PhySocket *sock,void **uptr)
|
||||
void VirtualTap::phyOnUnixClose(PhySocket *sock, void **uptr)
|
||||
{
|
||||
if (sock) {
|
||||
VirtualSocket *vs = (VirtualSocket*)uptr;
|
||||
if (vs) {
|
||||
Close(vs);
|
||||
}
|
||||
} else {
|
||||
handle_general_failure();
|
||||
}
|
||||
}
|
||||
|
||||
void VirtualTap::phyOnUnixData(PhySocket *sock, void **uptr, void *data, ssize_t len)
|
||||
{
|
||||
//DEBUG_ATTN("sock->fd=%d", _phy.getDescriptor(sock));
|
||||
VirtualSocket *vs = (VirtualSocket*)*uptr;
|
||||
if (vs == NULL) {
|
||||
handle_general_failure();
|
||||
return;
|
||||
}
|
||||
if (len > 0) {
|
||||
Write(vs, data, len);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void VirtualTap::phyOnUnixWritable(PhySocket *sock, void **uptr, bool stack_invoked)
|
||||
{
|
||||
if (sock)
|
||||
if (sock) {
|
||||
Read(sock,uptr,stack_invoked);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a route to the virtual tap
|
||||
@@ -321,11 +336,18 @@ namespace ZeroTier {
|
||||
#if defined(STACK_PICO)
|
||||
if (picostack) {
|
||||
return picostack->pico_route_add(this, addr, nm, gw, 0);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if (lwipstack) {
|
||||
// TODO
|
||||
return true;
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
@@ -340,11 +362,18 @@ namespace ZeroTier {
|
||||
#if defined(STACK_PICO)
|
||||
if (picostack) {
|
||||
return picostack->pico_route_del(this, addr, nm, 0);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if (lwipstack) {
|
||||
// TODO
|
||||
return true;
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
@@ -362,7 +391,6 @@ namespace ZeroTier {
|
||||
for(int i=0; i<_VirtualSockets.size(); i++) {
|
||||
if (vs == _VirtualSockets[i]) {
|
||||
_VirtualSockets.erase(_VirtualSockets.begin() + i);
|
||||
//DEBUG_EXTRA("Removed vs=%p from vt=%p", vs, this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -375,22 +403,46 @@ namespace ZeroTier {
|
||||
|
||||
int VirtualTap::add_DNS_Nameserver(struct sockaddr *addr)
|
||||
{
|
||||
int err = -1;
|
||||
#if defined(STACK_PICO)
|
||||
return picostack->pico_add_dns_nameserver(addr);
|
||||
if (picostack) {
|
||||
err = picostack->pico_add_dns_nameserver(addr);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
return lwipstack->lwip_add_dns_nameserver(addr);
|
||||
if (lwipstack) {
|
||||
err = lwipstack->lwip_add_dns_nameserver(addr);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
int VirtualTap::del_DNS_Nameserver(struct sockaddr *addr)
|
||||
{
|
||||
int err = -1;
|
||||
#if defined(STACK_PICO)
|
||||
return picostack->pico_del_dns_nameserver(addr);
|
||||
if (picostack) {
|
||||
err = picostack->pico_del_dns_nameserver(addr);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
return lwipstack->lwip_del_dns_nameserver(addr);
|
||||
if (lwipstack) {
|
||||
err = lwipstack->lwip_del_dns_nameserver(addr);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -398,26 +450,35 @@ namespace ZeroTier {
|
||||
/****************************************************************************/
|
||||
|
||||
// Connect
|
||||
int VirtualTap::Connect(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen) {
|
||||
int VirtualTap::Connect(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
int err = -1;
|
||||
#if defined(NO_STACK)
|
||||
return -1;
|
||||
return err;
|
||||
#endif
|
||||
#if defined(STACK_PICO)
|
||||
if (picostack) {
|
||||
Mutex::Lock _l(_tcpconns_m);
|
||||
return picostack->pico_Connect(vs, addr, addrlen);
|
||||
err = picostack->pico_Connect(vs, addr, addrlen);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if (lwipstack) {
|
||||
return lwipstack->lwip_Connect(vs, addr, addrlen);
|
||||
err = lwipstack->lwip_Connect(vs, addr, addrlen);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
return err;
|
||||
}
|
||||
|
||||
// Bind VirtualSocket to a network stack's interface
|
||||
int VirtualTap::Bind(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen) {
|
||||
int VirtualTap::Bind(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
#if defined(NO_STACK)
|
||||
return -1;
|
||||
#endif
|
||||
@@ -425,85 +486,111 @@ namespace ZeroTier {
|
||||
if (picostack) {
|
||||
Mutex::Lock _l(_tcpconns_m);
|
||||
return picostack->pico_Bind(vs, addr, addrlen);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if (lwipstack) {
|
||||
Mutex::Lock _l(_tcpconns_m);
|
||||
return lwipstack->lwip_Bind(this, vs, addr, addrlen);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Listen for an incoming VirtualSocket
|
||||
int VirtualTap::Listen(VirtualSocket *vs, int backlog) {
|
||||
int VirtualTap::Listen(VirtualSocket *vs, int backlog)
|
||||
{
|
||||
int err = -1;
|
||||
#if defined(NO_STACK)
|
||||
return -1;
|
||||
return err;
|
||||
#endif
|
||||
#if defined(STACK_PICO)
|
||||
if (picostack) {
|
||||
Mutex::Lock _l(_tcpconns_m);
|
||||
return picostack->pico_Listen(vs, backlog);
|
||||
}
|
||||
else {
|
||||
return ZT_ERR_GENERAL_FAILURE;
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if (lwipstack) {
|
||||
Mutex::Lock _l(_tcpconns_m);
|
||||
return lwipstack->lwip_Listen(vs, backlog);
|
||||
}
|
||||
else {
|
||||
return ZT_ERR_GENERAL_FAILURE;
|
||||
err = lwipstack->lwip_Listen(vs, backlog);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
// Accept a VirtualSocket
|
||||
VirtualSocket* VirtualTap::Accept(VirtualSocket *vs) {
|
||||
VirtualSocket* VirtualTap::Accept(VirtualSocket *vs)
|
||||
{
|
||||
VirtualSocket *new_vs = NULL;
|
||||
#if defined(NO_STACK)
|
||||
return NULL;
|
||||
new_vs = NULL;
|
||||
#endif
|
||||
#if defined(STACK_PICO)
|
||||
// TODO: separation of church and state
|
||||
if (picostack) {
|
||||
Mutex::Lock _l(_tcpconns_m);
|
||||
return picostack->pico_Accept(vs);
|
||||
}
|
||||
else {
|
||||
new_vs = picostack->pico_Accept(vs);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if (lwipstack) {
|
||||
Mutex::Lock _l(_tcpconns_m);
|
||||
return lwipstack->lwip_Accept(vs);
|
||||
}
|
||||
else {
|
||||
new_vs = lwipstack->lwip_Accept(vs);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
return new_vs;
|
||||
}
|
||||
|
||||
// Read from stack/buffers into the app's socket
|
||||
int VirtualTap::Read(PhySocket *sock,void **uptr,bool stack_invoked) {
|
||||
int VirtualTap::Read(PhySocket *sock,void **uptr,bool stack_invoked)
|
||||
{
|
||||
int err = -1;
|
||||
#if defined(NO_STACK)
|
||||
#endif
|
||||
#if defined(STACK_PICO)
|
||||
if (picostack) {
|
||||
return picostack->pico_Read(this, sock, (VirtualSocket*)uptr, stack_invoked);
|
||||
err = picostack->pico_Read(this, sock, (VirtualSocket*)uptr, stack_invoked);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if (lwipstack) {
|
||||
return lwipstack->lwip_Read((VirtualSocket*)*(_phy.getuptr(sock)), stack_invoked);
|
||||
err = lwipstack->lwip_Read((VirtualSocket*)*(_phy.getuptr(sock)), stack_invoked);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
return err;
|
||||
}
|
||||
|
||||
// Write data from app socket to the virtual wire, either raw over VL2, or via network stack
|
||||
int VirtualTap::Write(VirtualSocket *vs, void *data, ssize_t len) {
|
||||
int VirtualTap::Write(VirtualSocket *vs, void *data, ssize_t len)
|
||||
{
|
||||
int err = -1;
|
||||
#if defined(NO_STACK)
|
||||
#endif
|
||||
// VL2, SOCK_RAW, no network stack
|
||||
if (vs->socket_type == SOCK_RAW) {
|
||||
struct ether_header *eh = (struct ether_header *) data;
|
||||
@@ -516,15 +603,21 @@ namespace ZeroTier {
|
||||
}
|
||||
#if defined(STACK_PICO)
|
||||
if (picostack) {
|
||||
return picostack->pico_Write(vs, data, len);
|
||||
err = picostack->pico_Write(vs, data, len);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if (lwipstack) {
|
||||
return lwipstack->lwip_Write(vs, data, len);
|
||||
err = lwipstack->lwip_Write(vs, data, len);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
return err;
|
||||
}
|
||||
|
||||
// Send data to a specified host
|
||||
@@ -532,9 +625,8 @@ namespace ZeroTier {
|
||||
{
|
||||
/* FIXME: There is a call to *_Connect for each send, we should probably figure out a better way to do this,
|
||||
possibly consult the stack for "connection" state */
|
||||
|
||||
// TODO: flags
|
||||
int err = 0;
|
||||
int err = -1;
|
||||
#if defined(STACK_PICO)
|
||||
if (picostack) {
|
||||
if ((err = picostack->pico_Connect(vs, addr, addrlen)) < 0) { // implicit
|
||||
@@ -545,6 +637,9 @@ namespace ZeroTier {
|
||||
errno = ENOBUFS; // TODO: translate pico err to something more useful
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
@@ -555,6 +650,9 @@ namespace ZeroTier {
|
||||
if ((err = lwipstack->lwip_Write(vs, (void*)buf, len)) < 0) {
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return err;
|
||||
@@ -562,21 +660,29 @@ namespace ZeroTier {
|
||||
|
||||
// Remove VritualSocket from VirtualTap, and instruct network stacks to dismantle their
|
||||
// respective protocol control structures
|
||||
int VirtualTap::Close(VirtualSocket *vs) {
|
||||
int VirtualTap::Close(VirtualSocket *vs)
|
||||
{
|
||||
int err = 0;
|
||||
if (vs == NULL) {
|
||||
DEBUG_ERROR("invalid VirtualSocket");
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
removeVirtualSocket(vs);
|
||||
#if defined(STACK_PICO)
|
||||
if (picostack) {
|
||||
err = picostack->pico_Close(vs);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if (lwipstack) {
|
||||
err = lwipstack->lwip_Close(vs);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
if (vs->sock) {
|
||||
@@ -592,11 +698,17 @@ namespace ZeroTier {
|
||||
#if defined(STACK_PICO)
|
||||
if (picostack) {
|
||||
err = picostack->pico_Shutdown(vs, how);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if (lwipstack) {
|
||||
err = lwipstack->lwip_Shutdown(vs, how);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return err;
|
||||
@@ -660,7 +772,6 @@ namespace ZeroTier {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Clean up VirtualSocket objects
|
||||
last_housekeeping_ts = std::time(nullptr);
|
||||
}
|
||||
|
||||
202
src/libzt.cpp
202
src/libzt.cpp
@@ -161,7 +161,7 @@ void zts_simple_start(const char *path, const char *nwid)
|
||||
void zts_stop() {
|
||||
if (ZeroTier::zt1Service) {
|
||||
ZeroTier::zt1Service->terminate();
|
||||
dismantleTaps();
|
||||
disableTaps();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,7 +215,8 @@ void zts_leave_soft(const char * filepath, const char * nwid) {
|
||||
void zts_get_homepath(char *homePath, int len) {
|
||||
if (ZeroTier::homeDir.length()) {
|
||||
memset(homePath, 0, len);
|
||||
memcpy(homePath, ZeroTier::homeDir.c_str(), len < ZeroTier::homeDir.length() ? len : ZeroTier::homeDir.length());
|
||||
int buf_len = len < ZeroTier::homeDir.length() ? len : ZeroTier::homeDir.length();
|
||||
memcpy(homePath, ZeroTier::homeDir.c_str(), buf_len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,7 +415,7 @@ int zts_socket(ZT_SOCKET_SIG) {
|
||||
vs->socket_family = socket_family;
|
||||
vs->socket_type = socket_type;
|
||||
vs->protocol = protocol;
|
||||
add_unassigned_virtual_socket(vs->app_fd, vs);
|
||||
add_unassigned_virt_socket(vs->app_fd, vs);
|
||||
return vs->app_fd;
|
||||
}
|
||||
#if defined(STACK_PICO)
|
||||
@@ -425,7 +426,7 @@ int zts_socket(ZT_SOCKET_SIG) {
|
||||
vs->socket_family = socket_family;
|
||||
vs->socket_type = socket_type;
|
||||
vs->picosock = p;
|
||||
add_unassigned_virtual_socket(vs->app_fd, vs);
|
||||
add_unassigned_virt_socket(vs->app_fd, vs);
|
||||
err = vs->app_fd; // return one end of the socketpair
|
||||
}
|
||||
else {
|
||||
@@ -443,7 +444,7 @@ int zts_socket(ZT_SOCKET_SIG) {
|
||||
vs->socket_family = socket_family;
|
||||
vs->socket_type = socket_type;
|
||||
vs->pcb = pcb;
|
||||
add_unassigned_virtual_socket(vs->app_fd, vs);
|
||||
add_unassigned_virt_socket(vs->app_fd, vs);
|
||||
// return one end of the socketpair for the app to use
|
||||
err = vs->app_fd;
|
||||
}
|
||||
@@ -523,7 +524,7 @@ int zts_connect(ZT_CONNECT_SIG) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
ZeroTier::VirtualSocket *vs = get_virtual_socket(fd);
|
||||
ZeroTier::VirtualSocket *vs = get_virt_socket(fd);
|
||||
if (vs == NULL) {
|
||||
DEBUG_ERROR("invalid socket, unable to locate VirtualSocket for fd=%d", fd);
|
||||
errno = EBADF;
|
||||
@@ -570,8 +571,8 @@ int zts_connect(ZT_CONNECT_SIG) {
|
||||
vs->sock = tap->_phy.wrapSocket(vs->sdk_fd, vs);
|
||||
|
||||
// TODO: Consolidate these calls
|
||||
del_unassigned_virtual_socket(fd);
|
||||
add_assigned_virtual_socket(tap, vs, fd);
|
||||
del_unassigned_virt_socket(fd);
|
||||
add_assigned_virt_socket(tap, vs, fd);
|
||||
|
||||
// save peer addr, for calls like getpeername
|
||||
memcpy(&(vs->peer_addr), addr, sizeof(vs->peer_addr));
|
||||
@@ -652,7 +653,7 @@ int zts_bind(ZT_BIND_SIG) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
ZeroTier::VirtualSocket *vs = get_virtual_socket(fd);
|
||||
ZeroTier::VirtualSocket *vs = get_virt_socket(fd);
|
||||
if (vs == NULL) {
|
||||
DEBUG_ERROR("no VirtualSocket for fd=%d", fd);
|
||||
errno = ENOTSOCK;
|
||||
@@ -704,8 +705,8 @@ int zts_bind(ZT_BIND_SIG) {
|
||||
err = tap->Bind(vs, addr, addrlen);
|
||||
if (err == 0) { // success
|
||||
vs->tap = tap;
|
||||
del_unassigned_virtual_socket(fd);
|
||||
add_assigned_virtual_socket(tap, vs, fd);
|
||||
del_unassigned_virt_socket(fd);
|
||||
add_assigned_virt_socket(tap, vs, fd);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
@@ -827,7 +828,7 @@ int zts_accept(ZT_ACCEPT_SIG) {
|
||||
}
|
||||
}
|
||||
if (accepted_vs) {
|
||||
add_assigned_virtual_socket(tap, accepted_vs, accepted_vs->app_fd);
|
||||
add_assigned_virt_socket(tap, accepted_vs, accepted_vs->app_fd);
|
||||
err = accepted_vs->app_fd;
|
||||
}
|
||||
}
|
||||
@@ -908,43 +909,42 @@ int zts_accept4(ZT_ACCEPT4_SIG)
|
||||
this error may also be returned if optlen is not in a
|
||||
valid part of the process address space.
|
||||
[ ] [EDOM] The argument value is out of bounds.
|
||||
|
||||
int fd, int level, int optname, const void *optval, socklen_t optlen
|
||||
*/
|
||||
int zts_setsockopt(ZT_SETSOCKOPT_SIG)
|
||||
{
|
||||
// TODO: Move stack-specific logic into stack driver section
|
||||
//DEBUG_INFO("fd=%d", fd);
|
||||
DEBUG_EXTRA("fd=%d, level=%d, optname=%d", fd, level, optname);
|
||||
int err = errno = 0;
|
||||
if (fd < 0 || fd >= ZT_MAX_SOCKETS) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
#if defined(STACK_PICO)
|
||||
ZeroTier::VirtualSocket *vs = get_virtual_socket(fd);
|
||||
ZeroTier::VirtualSocket *vs = get_virt_socket(fd);
|
||||
if (vs == NULL) {
|
||||
DEBUG_ERROR("invalid fd=%d", fd);
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
struct pico_socket *p = vs->picosock;
|
||||
if (p) {
|
||||
// Disable Nagle's algorithm
|
||||
int value = 1;
|
||||
if ((err = pico_socket_setoption(p, PICO_TCP_NODELAY, &value)) < 0) {
|
||||
if (err == PICO_ERR_EINVAL) {
|
||||
DEBUG_ERROR("error while disabling Nagle's algorithm");
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(STACK_PICO)
|
||||
if (ZeroTier::picostack) {
|
||||
err = ZeroTier::picostack->pico_setsockopt(vs, level, optname, optval, optlen);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
// TODO: errno?
|
||||
err = -1;
|
||||
}
|
||||
err = setsockopt(fd, level, optname, optval, optlen);
|
||||
return err;
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
// TODO
|
||||
if (ZeroTier::lwipstack) {
|
||||
err = ZeroTier::lwipstack->lwip_setsockopt(vs, level, optname, optval, optlen);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
// TODO: errno?
|
||||
err = -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -960,12 +960,36 @@ int zts_setsockopt(ZT_SETSOCKOPT_SIG)
|
||||
*/
|
||||
int zts_getsockopt(ZT_GETSOCKOPT_SIG)
|
||||
{
|
||||
DEBUG_EXTRA("fd=%d, level=%d, optname=%d", fd, level, optname);
|
||||
int err = errno = 0;
|
||||
if (fd < 0 || fd >= ZT_MAX_SOCKETS) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
err = getsockopt(fd, level, optname, optval, optlen);
|
||||
ZeroTier::VirtualSocket *vs = get_virt_socket(fd);
|
||||
if (vs == NULL) {
|
||||
DEBUG_ERROR("invalid fd=%d", fd);
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
#if defined(STACK_PICO)
|
||||
if (ZeroTier::picostack) {
|
||||
err = ZeroTier::picostack->pico_getsockopt(vs, level, optname, optval, optlen);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
// TODO: errno?
|
||||
err = -1;
|
||||
}
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if (ZeroTier::lwipstack) {
|
||||
err = ZeroTier::lwipstack->lwip_getsockopt(vs, level, optname, optval, optlen);
|
||||
} else {
|
||||
handle_general_failure();
|
||||
// TODO: errno?
|
||||
err = -1;
|
||||
}
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1008,7 +1032,7 @@ int zts_getpeername(ZT_GETPEERNAME_SIG)
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
ZeroTier::VirtualSocket *vs = get_virtual_socket(fd);
|
||||
ZeroTier::VirtualSocket *vs = get_virt_socket(fd);
|
||||
if (vs == NULL) {
|
||||
errno = ENOTCONN;
|
||||
return -1;
|
||||
@@ -1083,14 +1107,14 @@ int zts_close(ZT_CLOSE_SIG)
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
ZeroTier::VirtualSocket *vs = get_virtual_socket(fd);
|
||||
ZeroTier::VirtualSocket *vs = get_virt_socket(fd);
|
||||
if (vs == NULL) {
|
||||
DEBUG_ERROR("no vs found for fd=%d", fd);
|
||||
handle_general_failure();
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
del_virtual_socket(fd);
|
||||
del_virt_socket(fd);
|
||||
if (vs->tap) {
|
||||
vs->tap->Close(vs);
|
||||
}
|
||||
@@ -1231,7 +1255,7 @@ ssize_t zts_sendto(ZT_SENDTO_SIG)
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
ZeroTier::VirtualSocket *vs = get_virtual_socket(fd);
|
||||
ZeroTier::VirtualSocket *vs = get_virt_socket(fd);
|
||||
if (vs == NULL) {
|
||||
DEBUG_ERROR("no vs found for fd=%x", fd);
|
||||
handle_general_failure();
|
||||
@@ -1356,7 +1380,7 @@ ssize_t zts_send(ZT_SEND_SIG)
|
||||
errno = EMSGSIZE;
|
||||
return -1;
|
||||
}
|
||||
ZeroTier::VirtualSocket *vs = get_virtual_socket(fd);
|
||||
ZeroTier::VirtualSocket *vs = get_virt_socket(fd);
|
||||
if (vs == NULL) {
|
||||
DEBUG_ERROR("invalid vs for fd=%d", fd);
|
||||
errno = EBADF;
|
||||
@@ -1468,7 +1492,7 @@ ssize_t zts_recv(ZT_RECV_SIG)
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
ZeroTier::VirtualSocket *vs = get_virtual_socket(fd);
|
||||
ZeroTier::VirtualSocket *vs = get_virt_socket(fd);
|
||||
if (vs == NULL) {
|
||||
DEBUG_ERROR("invalid vs for fd=%d", fd);
|
||||
errno = EBADF;
|
||||
@@ -1671,7 +1695,7 @@ int zts_shutdown(ZT_SHUTDOWN_SIG)
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
ZeroTier::VirtualSocket *vs = get_virtual_socket(fd);
|
||||
ZeroTier::VirtualSocket *vs = get_virt_socket(fd);
|
||||
if (vs == NULL) {
|
||||
DEBUG_ERROR("invalid vs for fd=%d", fd);
|
||||
errno = EBADF;
|
||||
@@ -1855,7 +1879,8 @@ namespace ZeroTier {
|
||||
return rxbytes;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1write(JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len)
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1write(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jarray buf, jint len)
|
||||
{
|
||||
jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0);
|
||||
char * bufp = (char *)malloc(sizeof(char)*len);
|
||||
@@ -1865,7 +1890,8 @@ namespace ZeroTier {
|
||||
return written_bytes;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1read(JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len)
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1read(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jarray buf, jint len)
|
||||
{
|
||||
jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0);
|
||||
int read_bytes = read(fd, body, len);
|
||||
@@ -1874,19 +1900,23 @@ namespace ZeroTier {
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1setsockopt(
|
||||
JNIEnv *env, jobject thisObj, jint fd, jint level, jint optname, jint optval, jint optlen) {
|
||||
JNIEnv *env, jobject thisObj,
|
||||
jint fd, jint level, jint optname, jint optval, jint optlen) {
|
||||
return zts_setsockopt(fd, level, optname, (const void*)optval, optlen);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getsockopt(JNIEnv *env, jobject thisObj, jint fd, jint level, jint optname, jint optval, jint optlen) {
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getsockopt(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jint level, jint optname, jint optval, jint optlen) {
|
||||
return zts_getsockopt(fd, level, optname, (void*)optval, (socklen_t *)optlen);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1socket(JNIEnv *env, jobject thisObj, jint family, jint type, jint protocol) {
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1socket(JNIEnv *env, jobject thisObj,
|
||||
jint family, jint type, jint protocol) {
|
||||
return zts_socket(family, type, protocol);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1connect(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port) {
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1connect(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jstring addrstr, jint port) {
|
||||
struct sockaddr_in addr;
|
||||
const char *str = (*env).GetStringUTFChars( addrstr, 0);
|
||||
addr.sin_addr.s_addr = inet_addr(str);
|
||||
@@ -1896,7 +1926,8 @@ namespace ZeroTier {
|
||||
return zts_connect(fd, (struct sockaddr *)&addr, sizeof(addr));
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1bind(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port) {
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1bind(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jstring addrstr, jint port) {
|
||||
struct sockaddr_in addr;
|
||||
const char *str = (*env).GetStringUTFChars( addrstr, 0);
|
||||
DEBUG_INFO("fd=%d, addr=%s, port=%d", fd, str, port);
|
||||
@@ -1908,7 +1939,8 @@ namespace ZeroTier {
|
||||
}
|
||||
|
||||
#if defined(__linux__)
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1accept4(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port, jint flags) {
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1accept4(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jstring addrstr, jint port, jint flags) {
|
||||
struct sockaddr_in addr;
|
||||
char *str;
|
||||
// = env->GetStringUTFChars(addrstr, NULL);
|
||||
@@ -1920,7 +1952,8 @@ namespace ZeroTier {
|
||||
}
|
||||
#endif
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1accept(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port) {
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1accept(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jstring addrstr, jint port) {
|
||||
struct sockaddr_in addr;
|
||||
// TODO: Send addr info back to Javaland
|
||||
addr.sin_addr.s_addr = inet_addr("");
|
||||
@@ -1929,15 +1962,18 @@ namespace ZeroTier {
|
||||
return zts_accept(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(addr));
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1listen(JNIEnv *env, jobject thisObj, jint fd, int backlog) {
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1listen(JNIEnv *env, jobject thisObj,
|
||||
jint fd, int backlog) {
|
||||
return zts_listen(fd, backlog);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1close(JNIEnv *env, jobject thisObj, jint fd) {
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1close(JNIEnv *env, jobject thisObj,
|
||||
jint fd) {
|
||||
return zts_close(fd);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getsockname(JNIEnv *env, jobject thisObj, jint fd, jobject ztaddr) {
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getsockname(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jobject ztaddr) {
|
||||
struct sockaddr_in addr;
|
||||
int err = zts_getsockname(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr));
|
||||
jfieldID fid;
|
||||
@@ -1949,7 +1985,8 @@ namespace ZeroTier {
|
||||
return err;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getpeername(JNIEnv *env, jobject thisObj, jint fd, jobject ztaddr) {
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getpeername(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jobject ztaddr) {
|
||||
struct sockaddr_in addr;
|
||||
int err = zts_getpeername(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr));
|
||||
jfieldID fid;
|
||||
@@ -1961,7 +1998,8 @@ namespace ZeroTier {
|
||||
return err;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1fcntl(JNIEnv *env, jobject thisObj, jint fd, jint cmd, jint flags) {
|
||||
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1fcntl(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jint cmd, jint flags) {
|
||||
return zts_fcntl(fd,cmd,flags);
|
||||
}
|
||||
}
|
||||
@@ -1973,6 +2011,7 @@ namespace ZeroTier {
|
||||
|
||||
bool can_provision_new_socket(int socket_type)
|
||||
{
|
||||
int can = false;
|
||||
#if defined(STACK_PICO)
|
||||
return !(pico_ntimers()+1 > PICO_MAX_TIMERS);
|
||||
#endif
|
||||
@@ -1986,15 +2025,16 @@ bool can_provision_new_socket(int socket_type)
|
||||
if (socket_type == SOCK_RAW) {
|
||||
return !(ZeroTier::lwIP::lwip_num_current_raw_pcbs()+1 > MEMP_NUM_RAW_PCB);
|
||||
}
|
||||
return true;
|
||||
can = true;
|
||||
#endif
|
||||
#if defined(NO_STACK)
|
||||
// always true since there's no network stack timer/memory limitation
|
||||
return true;
|
||||
can = true;
|
||||
#endif
|
||||
return can;
|
||||
}
|
||||
|
||||
int zts_nsockets()
|
||||
int zts_num_active_virt_sockets()
|
||||
{
|
||||
ZeroTier::_multiplexer_lock.lock();
|
||||
int num = ZeroTier::unmap.size() + ZeroTier::fdmap.size();
|
||||
@@ -2002,18 +2042,32 @@ int zts_nsockets()
|
||||
return num;
|
||||
}
|
||||
|
||||
int zts_maxsockets()
|
||||
int zts_maxsockets(int socket_type)
|
||||
{
|
||||
int max = 0;
|
||||
#if defined(STACK_PICO)
|
||||
// TODO: This is only an approximation
|
||||
return PICO_MAX_TIMERS - 10;
|
||||
// TODO: distinquish by type
|
||||
max = PICO_MAX_TIMERS - 10;
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
return 32;
|
||||
if (socket_type == SOCK_STREAM) {
|
||||
max = MEMP_NUM_TCP_PCB;
|
||||
}
|
||||
if (socket_type == SOCK_DGRAM) {
|
||||
max = MEMP_NUM_UDP_PCB;
|
||||
}
|
||||
#endif
|
||||
#if defined(NO_STACK)
|
||||
return 1024; // arbitrary
|
||||
// arbitrary
|
||||
#if defined(__linux__)
|
||||
max = RLIMIT_NOFILE;
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
max = 1024;
|
||||
#endif
|
||||
#endif
|
||||
return max;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -2124,7 +2178,7 @@ ZeroTier::VirtualTap *getAnyTap()
|
||||
/* VirtualSocket / VirtualTap helper functions - DON'T CALL THESE DIRECTLY */
|
||||
/****************************************************************************/
|
||||
|
||||
ZeroTier::VirtualSocket *get_virtual_socket(int fd)
|
||||
ZeroTier::VirtualSocket *get_virt_socket(int fd)
|
||||
{
|
||||
ZeroTier::_multiplexer_lock.lock();
|
||||
// try to locate in unmapped set
|
||||
@@ -2143,7 +2197,7 @@ ZeroTier::VirtualSocket *get_virtual_socket(int fd)
|
||||
return vs;
|
||||
}
|
||||
|
||||
int del_virtual_socket(int fd)
|
||||
int del_virt_socket(int fd)
|
||||
{
|
||||
int err = 0;
|
||||
ZeroTier::_multiplexer_lock.lock();
|
||||
@@ -2166,7 +2220,7 @@ int del_virtual_socket(int fd)
|
||||
return err;
|
||||
}
|
||||
|
||||
int add_unassigned_virtual_socket(int fd, ZeroTier::VirtualSocket *vs)
|
||||
int add_unassigned_virt_socket(int fd, ZeroTier::VirtualSocket *vs)
|
||||
{
|
||||
int err = 0;
|
||||
ZeroTier::_multiplexer_lock.lock();
|
||||
@@ -2189,7 +2243,7 @@ int add_unassigned_virtual_socket(int fd, ZeroTier::VirtualSocket *vs)
|
||||
return err;
|
||||
}
|
||||
|
||||
int del_unassigned_virtual_socket(int fd)
|
||||
int del_unassigned_virt_socket(int fd)
|
||||
{
|
||||
int err = 0;
|
||||
ZeroTier::_multiplexer_lock.lock();
|
||||
@@ -2208,12 +2262,13 @@ int del_unassigned_virtual_socket(int fd)
|
||||
return err;
|
||||
}
|
||||
|
||||
int add_assigned_virtual_socket(ZeroTier::VirtualTap *tap, ZeroTier::VirtualSocket *vs, int fd)
|
||||
int add_assigned_virt_socket(ZeroTier::VirtualTap *tap, ZeroTier::VirtualSocket *vs, int fd)
|
||||
{
|
||||
int err = 0;
|
||||
ZeroTier::_multiplexer_lock.lock();
|
||||
try {
|
||||
std::map<int, std::pair<ZeroTier::VirtualSocket*,ZeroTier::VirtualTap*>*>::iterator fd_iter = ZeroTier::fdmap.find(fd);
|
||||
std::map<int, std::pair<ZeroTier::VirtualSocket*,ZeroTier::VirtualTap*>*>::iterator fd_iter;
|
||||
fd_iter = ZeroTier::fdmap.find(fd);
|
||||
if (fd_iter == ZeroTier::fdmap.end()) {
|
||||
ZeroTier::fdmap[fd] = new std::pair<ZeroTier::VirtualSocket*,ZeroTier::VirtualTap*>(vs, tap);
|
||||
}
|
||||
@@ -2231,12 +2286,13 @@ int add_assigned_virtual_socket(ZeroTier::VirtualTap *tap, ZeroTier::VirtualSock
|
||||
return err;
|
||||
}
|
||||
|
||||
int del_assigned_virtual_socket(ZeroTier::VirtualTap *tap, ZeroTier::VirtualSocket *vs, int fd)
|
||||
int del_assigned_virt_socket(ZeroTier::VirtualTap *tap, ZeroTier::VirtualSocket *vs, int fd)
|
||||
{
|
||||
int err = 0;
|
||||
ZeroTier::_multiplexer_lock.lock();
|
||||
try {
|
||||
std::map<int, std::pair<ZeroTier::VirtualSocket*,ZeroTier::VirtualTap*>*>::iterator fd_iter = ZeroTier::fdmap.find(fd);
|
||||
std::map<int, std::pair<ZeroTier::VirtualSocket*,ZeroTier::VirtualTap*>*>::iterator fd_iter;
|
||||
fd_iter = ZeroTier::fdmap.find(fd);
|
||||
if (fd_iter != ZeroTier::fdmap.end()) {
|
||||
ZeroTier::fdmap.erase(fd_iter);
|
||||
}
|
||||
@@ -2258,15 +2314,13 @@ std::pair<ZeroTier::VirtualSocket*, ZeroTier::VirtualTap*> *get_assigned_virtual
|
||||
return p;
|
||||
}
|
||||
|
||||
void dismantleTaps()
|
||||
void disableTaps()
|
||||
{
|
||||
ZeroTier::_vtaps_lock.lock();
|
||||
for(int i=0; i<ZeroTier::vtaps.size(); i++) {
|
||||
DEBUG_ERROR("ZeroTier::vtapsf[i]=%p", ZeroTier::vtaps[i]);
|
||||
delete (ZeroTier::VirtualTap*)ZeroTier::vtaps[i];
|
||||
ZeroTier::vtaps[i] = NULL;
|
||||
DEBUG_EXTRA("vt=%p", ZeroTier::vtaps[i]);
|
||||
((ZeroTier::VirtualTap*)ZeroTier::vtaps[i])->_enabled = false;
|
||||
}
|
||||
ZeroTier::vtaps.clear();
|
||||
ZeroTier::_vtaps_lock.unlock();
|
||||
}
|
||||
|
||||
|
||||
702
src/lwIP.cpp
702
src/lwIP.cpp
@@ -88,7 +88,7 @@ err_t lwip_eth_tx(struct netif *netif, struct pbuf *p)
|
||||
int proto = ZeroTier::Utils::ntoh((uint16_t)ethhdr->type);
|
||||
tap->_handler(tap->_arg, NULL, tap->_nwid, src_mac, dest_mac, proto, 0, data, len);
|
||||
|
||||
if (ZT_DEBUG_LEVEL >= ZT_MSG_TRANSFER) {
|
||||
if (ZT_MSG_TRANSFER == true) {
|
||||
char flagbuf[32];
|
||||
memset(&flagbuf, 0, 32);
|
||||
char macBuf[ZT_MAC_ADDRSTRLEN], nodeBuf[ZT_ID_LEN];
|
||||
@@ -333,7 +333,11 @@ namespace ZeroTier
|
||||
dataptr += q->len;
|
||||
}
|
||||
}
|
||||
if (ZT_DEBUG_LEVEL >= ZT_MSG_TRANSFER) {
|
||||
else {
|
||||
DEBUG_ERROR("dropped packet: no pbufs available");
|
||||
return;
|
||||
}
|
||||
if (ZT_MSG_TRANSFER == true) {
|
||||
char flagbuf[32];
|
||||
memset(&flagbuf, 0, 32);
|
||||
char macBuf[ZT_MAC_ADDRSTRLEN], nodeBuf[ZT_ID_LEN];
|
||||
@@ -344,10 +348,6 @@ namespace ZeroTier
|
||||
DEBUG_TRANS("len=%5d dst=%s [%s RX --> %s] proto=0x%04x %s %s", len, macBuf, nodeBuf, tap->nodeId().c_str(),
|
||||
ZeroTier::Utils::ntoh(ethhdr.type), beautify_eth_proto_nums(ZeroTier::Utils::ntoh(ethhdr.type)), flagbuf);
|
||||
}
|
||||
else {
|
||||
DEBUG_ERROR("dropped packet: no pbufs available");
|
||||
return;
|
||||
}
|
||||
{
|
||||
#if defined(LIBZT_IPV4)
|
||||
if (tap->lwipdev.input(p, &(tap->lwipdev)) != ERR_OK) {
|
||||
@@ -658,12 +658,12 @@ namespace ZeroTier
|
||||
if (vs->pcb) {
|
||||
struct tcp_pcb* tpcb = (struct tcp_pcb*)vs->pcb;
|
||||
if (tpcb->state == CLOSED) {
|
||||
DEBUG_ERROR("pcb is in CLOSED state");
|
||||
DEBUG_EXTRA("pcb is in CLOSED state");
|
||||
// calling tcp_close() here would be redundant
|
||||
return 0;
|
||||
}
|
||||
if (tpcb->state == CLOSE_WAIT) {
|
||||
DEBUG_ERROR("pcb is in CLOSE_WAIT state");
|
||||
DEBUG_EXTRA("pcb is in CLOSE_WAIT state");
|
||||
// calling tcp_close() here would be redundant
|
||||
}
|
||||
if (tpcb->state > TIME_WAIT) {
|
||||
@@ -922,7 +922,7 @@ namespace ZeroTier
|
||||
|
||||
err_t lwIP::lwip_cb_connected(void *arg, struct tcp_pcb *PCB, err_t err)
|
||||
{
|
||||
DEBUG_ATTN("pcb=%p", PCB);
|
||||
DEBUG_EXTRA("pcb=%p", PCB);
|
||||
VirtualSocket *vs = (VirtualSocket *)arg;
|
||||
if (vs == NULL) {
|
||||
DEBUG_ERROR("invalid virtual socket");
|
||||
@@ -994,6 +994,690 @@ namespace ZeroTier
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
int lwIP::lwip_setsockopt(VirtualSocket *vs, int level, int optname, const void *optval, socklen_t optlen)
|
||||
{
|
||||
int err = -1;
|
||||
errno = 0;
|
||||
if (vs == NULL) {
|
||||
DEBUG_ERROR("invalid vs");
|
||||
return -1;
|
||||
} else {
|
||||
DEBUG_EXTRA("fd=%d, level=%d, optname=%d", vs->app_fd, level, optname);
|
||||
}
|
||||
if (level == SOL_SOCKET)
|
||||
{
|
||||
/* Turns on recording of debugging information. This option enables or disables debugging in the underlying
|
||||
protocol modules. This option takes an int value. This is a Boolean option.*/
|
||||
if (optname == SO_DEBUG)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Specifies that the rules used in validating addresses supplied to bind() should allow reuse of local
|
||||
addresses, if this is supported by the protocol. This option takes an int value. This is a Boolean option.*/
|
||||
if (optname == SO_REUSEADDR)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Keeps connections active by enabling the periodic transmission of messages, if this is supported by the
|
||||
protocol. This option takes an int value. */
|
||||
if (optname == SO_KEEPALIVE)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Requests that outgoing messages bypass the standard routing facilities. */
|
||||
if (optname == SO_DONTROUTE)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Lingers on a close() if data is present. */
|
||||
if (optname == SO_LINGER)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Permits sending of broadcast messages, if this is supported by the protocol. This option takes an int
|
||||
value. This is a Boolean option. */
|
||||
if (optname == SO_BROADCAST)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Leaves received out-of-band data (data marked urgent) inline. This option takes an int value. This is a
|
||||
Boolean option. */
|
||||
if (optname == SO_OOBINLINE)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Sets send buffer size. This option takes an int value. */
|
||||
if (optname == SO_SNDBUF)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Sets receive buffer size. This option takes an int value. */
|
||||
if (optname == SO_RCVBUF)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* */
|
||||
if (optname == SO_STYLE)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* */
|
||||
if (optname == SO_TYPE)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Get error status and clear */
|
||||
if (optname == SO_ERROR)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (level == IPPROTO_IP)
|
||||
{
|
||||
if (optname == IP_ADD_MEMBERSHIP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_ADD_SOURCE_MEMBERSHIP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_BIND_ADDRESS_NO_PORT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_BLOCK_SOURCE) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_DROP_MEMBERSHIP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_DROP_SOURCE_MEMBERSHIP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_FREEBIND) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_HDRINCL) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MSFILTER) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MTU) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MTU_DISCOVER) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MULTICAST_ALL) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MULTICAST_IF) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MULTICAST_LOOP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MULTICAST_TTL) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_NODEFRAG) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_OPTIONS) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_PKTINFO) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_RECVOPTS) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_RECVORIGDSTADDR) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_RECVTOS) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_RECVTTL) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_RETOPTS) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_ROUTER_ALERT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_TOS) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_TRANSPARENT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_TTL) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_UNBLOCK_SOURCE) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
// TODO
|
||||
return -1;
|
||||
}
|
||||
if (level == IPPROTO_TCP)
|
||||
{
|
||||
struct tcp_pcb *pcb = (struct tcp_pcb*)(vs->pcb);
|
||||
if (pcb == NULL) {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
/* If set, don't send out partial frames. */
|
||||
if (optname == TCP_CORK) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Allow a listener to be awakened only when data arrives on the socket. */
|
||||
if (optname == TCP_DEFER_ACCEPT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Used to collect information about this socket. The kernel returns a struct tcp_info as defined in the
|
||||
file /usr/include/linux/tcp.h.*/
|
||||
if (optname == TCP_INFO) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* The maximum number of keepalive probes TCP should send before dropping the connection.*/
|
||||
if (optname == TCP_KEEPCNT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* The time (in seconds) the connection needs to remain idle before TCP starts sending keepalive probes,
|
||||
if the socket option SO_KEEPALIVE has been set on this socket. */
|
||||
if (optname == TCP_KEEPIDLE) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* The time (in seconds) between individual keepalive probes.*/
|
||||
if (optname == TCP_KEEPINTVL) {
|
||||
// TODO
|
||||
return -1;
|
||||
}
|
||||
/* The lifetime of orphaned FIN_WAIT2 state sockets. */
|
||||
if (optname == TCP_LINGER2) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* The maximum segment size for outgoing TCP packets. */
|
||||
if (optname == TCP_MAXSEG) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* If set, disable the Nagle algorithm. */
|
||||
if (optname == TCP_NODELAY) {
|
||||
pcb->flags |= TF_NODELAY;
|
||||
return 0;
|
||||
}
|
||||
/* Enable quickack mode if set or disable quickack mode if cleared. */
|
||||
if (optname == TCP_QUICKACK) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Set the number of SYN retransmits that TCP should send before aborting the attempt to connect. It
|
||||
cannot exceed 255. */
|
||||
if (optname == TCP_SYNCNT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Bound the size of the advertised window to this value. The kernel imposes a minimum size of
|
||||
SOCK_MIN_RCVBUF/2. */
|
||||
if (optname == TCP_WINDOW_CLAMP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (level == IPPROTO_UDP)
|
||||
{
|
||||
/*If this option is enabled, then all data output on this socket is accumulated into a single
|
||||
datagram that is transmitted when the option is disabled. */
|
||||
if (optname == UDP_CORK) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int lwIP::lwip_getsockopt(VirtualSocket *vs, int level, int optname, void *optval, socklen_t *optlen)
|
||||
{
|
||||
int err = -1, optval_tmp = 0;
|
||||
errno = 0;
|
||||
if (vs == NULL) {
|
||||
DEBUG_ERROR("invalid vs");
|
||||
return -1;
|
||||
} else {
|
||||
DEBUG_EXTRA("fd=%d, level=%d, optname=%d", vs->app_fd, level, optname);
|
||||
}
|
||||
if (level == SOL_SOCKET)
|
||||
{
|
||||
/* Turns on recording of debugging information. This option enables or disables debugging in the underlying
|
||||
protocol modules. This option takes an int value. This is a Boolean option.*/
|
||||
if (optname == SO_DEBUG)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Specifies that the rules used in validating addresses supplied to bind() should allow reuse of local
|
||||
addresses, if this is supported by the protocol. This option takes an int value. This is a Boolean option.*/
|
||||
if (optname == SO_REUSEADDR)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Keeps connections active by enabling the periodic transmission of messages, if this is supported by the
|
||||
protocol. This option takes an int value. */
|
||||
if (optname == SO_KEEPALIVE)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Requests that outgoing messages bypass the standard routing facilities. */
|
||||
if (optname == SO_DONTROUTE)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Lingers on a close() if data is present. */
|
||||
if (optname == SO_LINGER)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Permits sending of broadcast messages, if this is supported by the protocol. This option takes an int
|
||||
value. This is a Boolean option. */
|
||||
if (optname == SO_BROADCAST)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Leaves received out-of-band data (data marked urgent) inline. This option takes an int value. This is a
|
||||
Boolean option. */
|
||||
if (optname == SO_OOBINLINE)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Sets send buffer size. This option takes an int value. */
|
||||
if (optname == SO_SNDBUF)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Sets receive buffer size. This option takes an int value. */
|
||||
if (optname == SO_RCVBUF)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* */
|
||||
if (optname == SO_STYLE)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* */
|
||||
if (optname == SO_TYPE)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Get error status and clear */
|
||||
if (optname == SO_ERROR)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (level == IPPROTO_IP)
|
||||
{
|
||||
if (optname == IP_ADD_MEMBERSHIP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_ADD_SOURCE_MEMBERSHIP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_BIND_ADDRESS_NO_PORT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_BLOCK_SOURCE) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_DROP_MEMBERSHIP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_DROP_SOURCE_MEMBERSHIP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_FREEBIND) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_HDRINCL) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MSFILTER) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MTU) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MTU_DISCOVER) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MULTICAST_ALL) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MULTICAST_IF) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MULTICAST_LOOP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MULTICAST_TTL) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_NODEFRAG) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_OPTIONS) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_PKTINFO) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_RECVOPTS) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_RECVORIGDSTADDR) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_RECVTOS) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_RECVTTL) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_RETOPTS) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_ROUTER_ALERT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_TOS) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_TRANSPARENT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_TTL) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_UNBLOCK_SOURCE) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
// TODO
|
||||
return -1;
|
||||
}
|
||||
if (level == IPPROTO_TCP)
|
||||
{
|
||||
struct tcp_pcb *pcb = (struct tcp_pcb*)(vs->pcb);
|
||||
if (pcb == NULL) {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
/* If set, don't send out partial frames. */
|
||||
if (optname == TCP_CORK) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
err = -1;
|
||||
}
|
||||
/* Allow a listener to be awakened only when data arrives on the socket. */
|
||||
if (optname == TCP_DEFER_ACCEPT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
err = -1;
|
||||
}
|
||||
/* Used to collect information about this socket. */
|
||||
if (optname == TCP_INFO) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
err = -1;
|
||||
}
|
||||
/* The maximum number of keepalive probes TCP should send before dropping the connection.*/
|
||||
if (optname == TCP_KEEPCNT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
err = -1;
|
||||
}
|
||||
/* The time (in seconds) the connection needs to remain idle before TCP starts sending keepalive probes,
|
||||
if the socket option SO_KEEPALIVE has been set on this socket. */
|
||||
if (optname == TCP_KEEPIDLE) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
err = -1;
|
||||
}
|
||||
/* The time (in seconds) between individual keepalive probes.*/
|
||||
if (optname == TCP_KEEPINTVL) {
|
||||
// TODO
|
||||
err = -1;
|
||||
}
|
||||
/* The lifetime of orphaned FIN_WAIT2 state sockets. */
|
||||
if (optname == TCP_LINGER2) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
err = -1;
|
||||
}
|
||||
/* The maximum segment size for outgoing TCP packets. */
|
||||
if (optname == TCP_MAXSEG) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
err = -1;
|
||||
}
|
||||
/* If set, disable the Nagle algorithm. */
|
||||
if (optname == TCP_NODELAY) {
|
||||
optval_tmp = pcb->flags & TF_NODELAY;
|
||||
memcpy(optval, &optval_tmp, *optlen);
|
||||
err = 0;
|
||||
}
|
||||
/* Enable quickack mode if set or disable quickack mode if cleared. */
|
||||
if (optname == TCP_QUICKACK) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
err = -1;
|
||||
}
|
||||
/* Set the number of SYN retransmits that TCP should send before aborting the attempt to connect. It
|
||||
cannot exceed 255. */
|
||||
if (optname == TCP_SYNCNT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
err = -1;
|
||||
}
|
||||
/* Bound the size of the advertised window to this value. The kernel imposes a minimum size of
|
||||
SOCK_MIN_RCVBUF/2. */
|
||||
if (optname == TCP_WINDOW_CLAMP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
err = -1;
|
||||
}
|
||||
}
|
||||
if (level == IPPROTO_UDP)
|
||||
{
|
||||
/* If this option is enabled, then all data output on this socket is accumulated into a single
|
||||
datagram that is transmitted when the option is disabled. */
|
||||
if (optname == UDP_CORK) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
err = -1;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void lwIP::lwip_cb_err(void *arg, err_t err)
|
||||
{
|
||||
VirtualSocket *vs = (VirtualSocket *)arg;
|
||||
|
||||
10
src/lwIP.hpp
10
src/lwIP.hpp
@@ -287,6 +287,16 @@ namespace ZeroTier {
|
||||
*/
|
||||
int lwip_Shutdown(VirtualSocket *vs, int how);
|
||||
|
||||
/*
|
||||
* Sets a property of a socket
|
||||
*/
|
||||
static int lwip_setsockopt(VirtualSocket *vs, int level, int optname, const void *optval, socklen_t optlen);
|
||||
|
||||
/*
|
||||
* Gets a property of a socket
|
||||
*/
|
||||
static int lwip_getsockopt(VirtualSocket *vs, int level, int optname, void *optval, socklen_t *optlen);
|
||||
|
||||
// --- Callbacks from network stack ---
|
||||
|
||||
//static void netif_status_callback(struct netif *nif);
|
||||
|
||||
757
src/picoTCP.cpp
757
src/picoTCP.cpp
@@ -564,7 +564,7 @@ namespace ZeroTier {
|
||||
MAC dest_mac;
|
||||
src_mac.setTo(ethhdr->saddr, 6);
|
||||
dest_mac.setTo(ethhdr->daddr, 6);
|
||||
if (ZT_DEBUG_LEVEL >= ZT_MSG_TRANSFER) {
|
||||
if (ZT_MSG_TRANSFER == true) {
|
||||
char macBuf[ZT_MAC_ADDRSTRLEN], nodeBuf[ZT_ID_LEN];
|
||||
mac2str(macBuf, ZT_MAC_ADDRSTRLEN, ethhdr->daddr);
|
||||
ZeroTier::MAC mac;
|
||||
@@ -641,7 +641,7 @@ namespace ZeroTier {
|
||||
ethhdr.proto = Utils::hton((uint16_t)etherType);
|
||||
int32_t msg_len = len + sizeof(int32_t) + sizeof(struct pico_eth_hdr);
|
||||
|
||||
if (ZT_DEBUG_LEVEL >= ZT_MSG_TRANSFER) {
|
||||
if (ZT_MSG_TRANSFER == true) {
|
||||
char macBuf[ZT_MAC_ADDRSTRLEN], nodeBuf[ZT_ID_LEN];
|
||||
mac2str(macBuf, sizeof(macBuf), ethhdr.saddr);
|
||||
ZeroTier::MAC mac;
|
||||
@@ -716,8 +716,11 @@ namespace ZeroTier {
|
||||
// get frame len
|
||||
memcpy(&len, tap->pico_frame_rxbuf, sizeof(int32_t));
|
||||
if (len > sizeof(int32_t)) { // meaning, since we package the len in the msg, we don't want to recv a 0-(sizeof(int32_t)) sized frame
|
||||
DEBUG_ERROR("tap->pico_frame_rxbuf + sizeof(int32_t)=%p, len=%d", tap->pico_frame_rxbuf + sizeof(int32_t), len-(sizeof(int32_t)));
|
||||
memcpy(frame, tap->pico_frame_rxbuf + sizeof(int32_t), len-(sizeof(int32_t)) ); // get frame data
|
||||
DEBUG_ERROR("tap->pico_frame_rxbuf=%p, tap->pico_frame_rxbuf + len=%p, MAX_PICO_FRAME_RX_BUF_SZ-len=%d", tap->pico_frame_rxbuf, tap->pico_frame_rxbuf + len, MAX_PICO_FRAME_RX_BUF_SZ-len);
|
||||
memmove(tap->pico_frame_rxbuf, tap->pico_frame_rxbuf + len, MAX_PICO_FRAME_RX_BUF_SZ-len); // shift buffer
|
||||
DEBUG_ERROR("dev=%p, frame=%p, len=%d", dev, frame, (len-sizeof(int32_t)));
|
||||
if ((err = pico_stack_recv(dev, (uint8_t*)frame, (len-sizeof(int32_t)))) < 0) {
|
||||
if (picostack) {
|
||||
DEBUG_ERROR("pico_stack_recv(), err=%d, pico_err=%d, %s", err, pico_err, picostack->beautify_pico_error(pico_err));
|
||||
@@ -745,44 +748,43 @@ namespace ZeroTier {
|
||||
else {
|
||||
int protocol_version = 0;
|
||||
struct pico_socket *psock;
|
||||
if (socket_family == AF_INET)
|
||||
if (socket_family == AF_INET) {
|
||||
protocol_version = PICO_PROTO_IPV4;
|
||||
if (socket_family == AF_INET6)
|
||||
}
|
||||
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_ev);
|
||||
psock = pico_socket_open(protocol_version, PICO_PROTO_UDP, &ZeroTier::picoTCP::pico_cb_socket_ev);
|
||||
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_ev);
|
||||
psock = pico_socket_open(protocol_version, PICO_PROTO_TCP, &ZeroTier::picoTCP::pico_cb_socket_ev);
|
||||
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)
|
||||
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, %s",
|
||||
t_err, pico_err, beautify_pico_error(pico_err));
|
||||
if ((t_err = pico_socket_setoption(psock, PICO_SOCKET_OPT_RCVBUF, &rx_buf_sz)) < 0)
|
||||
}
|
||||
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, %s",
|
||||
t_err, pico_err, beautify_pico_error(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)
|
||||
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, %s",
|
||||
t_err, pico_err, beautify_pico_error(pico_err));
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
*p = psock;
|
||||
@@ -1024,6 +1026,727 @@ namespace ZeroTier {
|
||||
return err;
|
||||
}
|
||||
|
||||
int picoTCP::pico_setsockopt(VirtualSocket *vs, int level, int optname, const void *optval, socklen_t optlen)
|
||||
{
|
||||
int err = -1;
|
||||
errno = 0;
|
||||
if (vs == NULL) {
|
||||
DEBUG_ERROR("invalid vs");
|
||||
return -1;
|
||||
} else {
|
||||
DEBUG_EXTRA("fd=%d, level=%d, optname=%d", vs->app_fd, level, optname);
|
||||
}
|
||||
if (level == SOL_SOCKET)
|
||||
{
|
||||
/* Turns on recording of debugging information. This option enables or disables debugging in the underlying
|
||||
protocol modules. This option takes an int value. This is a Boolean option.*/
|
||||
if (optname == SO_DEBUG)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Specifies that the rules used in validating addresses supplied to bind() should allow reuse of local
|
||||
addresses, if this is supported by the protocol. This option takes an int value. This is a Boolean option.*/
|
||||
if (optname == SO_REUSEADDR)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Keeps connections active by enabling the periodic transmission of messages, if this is supported by the
|
||||
protocol. This option takes an int value. */
|
||||
if (optname == SO_KEEPALIVE)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Requests that outgoing messages bypass the standard routing facilities. */
|
||||
if (optname == SO_DONTROUTE)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Lingers on a close() if data is present. */
|
||||
if (optname == SO_LINGER)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Permits sending of broadcast messages, if this is supported by the protocol. This option takes an int
|
||||
value. This is a Boolean option. */
|
||||
if (optname == SO_BROADCAST)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Leaves received out-of-band data (data marked urgent) inline. This option takes an int value. This is a
|
||||
Boolean option. */
|
||||
if (optname == SO_OOBINLINE)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Sets send buffer size. This option takes an int value. */
|
||||
if (optname == SO_SNDBUF)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Sets receive buffer size. This option takes an int value. */
|
||||
if (optname == SO_RCVBUF)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* */
|
||||
if (optname == SO_STYLE)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* */
|
||||
if (optname == SO_TYPE)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Get error status and clear */
|
||||
if (optname == SO_ERROR)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (level == IPPROTO_IP)
|
||||
{
|
||||
if (optname == IP_ADD_MEMBERSHIP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_ADD_SOURCE_MEMBERSHIP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_BIND_ADDRESS_NO_PORT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_BLOCK_SOURCE) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_DROP_MEMBERSHIP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_DROP_SOURCE_MEMBERSHIP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_FREEBIND) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_HDRINCL) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MSFILTER) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MTU) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MTU_DISCOVER) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MULTICAST_ALL) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MULTICAST_IF) {
|
||||
/*
|
||||
if ((err = pico_socket_getoption(p, PICO_TCP_NODELAY, &optval_tmp)) < 0) {
|
||||
if (err == PICO_ERR_EINVAL) {
|
||||
DEBUG_ERROR("error while disabling Nagle's algorithm");
|
||||
errno = ENOPROTOOPT;
|
||||
err = -1;
|
||||
}
|
||||
}
|
||||
memcpy(optval, &optval_tmp, *optlen);
|
||||
*/
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MULTICAST_LOOP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MULTICAST_TTL) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_NODEFRAG) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_OPTIONS) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_PKTINFO) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_RECVOPTS) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_RECVORIGDSTADDR) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_RECVTOS) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_RECVTTL) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_RETOPTS) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_ROUTER_ALERT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_TOS) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_TRANSPARENT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_TTL) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_UNBLOCK_SOURCE) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
// TODO
|
||||
return -1;
|
||||
}
|
||||
if (level == IPPROTO_TCP)
|
||||
{
|
||||
struct pico_socket *p = vs->picosock;
|
||||
if (p == NULL) {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
/* If set, don't send out partial frames. */
|
||||
if (optname == TCP_CORK) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Allow a listener to be awakened only when data arrives on the socket. */
|
||||
if (optname == TCP_DEFER_ACCEPT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Used to collect information about this socket. The kernel returns a struct tcp_info as defined in the
|
||||
file /usr/include/linux/tcp.h.*/
|
||||
if (optname == TCP_INFO) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* The maximum number of keepalive probes TCP should send before dropping the connection.*/
|
||||
if (optname == TCP_KEEPCNT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* The time (in seconds) the connection needs to remain idle before TCP starts sending keepalive probes,
|
||||
if the socket option SO_KEEPALIVE has been set on this socket. */
|
||||
if (optname == TCP_KEEPIDLE) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* The time (in seconds) between individual keepalive probes.*/
|
||||
if (optname == TCP_KEEPINTVL) {
|
||||
// TODO
|
||||
return -1;
|
||||
}
|
||||
/* The lifetime of orphaned FIN_WAIT2 state sockets. */
|
||||
if (optname == TCP_LINGER2) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* The maximum segment size for outgoing TCP packets. */
|
||||
if (optname == TCP_MAXSEG) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* If set, disable the Nagle algorithm. */
|
||||
if (optname == TCP_NODELAY) {
|
||||
int no_delay = *((const int*)optval);
|
||||
if ((err = pico_socket_setoption(p, PICO_TCP_NODELAY, &no_delay) < 0)) {
|
||||
if (err == PICO_ERR_EINVAL) {
|
||||
DEBUG_ERROR("error while disabling Nagle's algorithm");
|
||||
errno = EINVAL;
|
||||
err = -1;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
/* Enable quickack mode if set or disable quickack mode if cleared. */
|
||||
if (optname == TCP_QUICKACK) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Set the number of SYN retransmits that TCP should send before aborting the attempt to connect. It
|
||||
cannot exceed 255. */
|
||||
if (optname == TCP_SYNCNT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Bound the size of the advertised window to this value. The kernel imposes a minimum size of
|
||||
SOCK_MIN_RCVBUF/2. */
|
||||
if (optname == TCP_WINDOW_CLAMP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (level == IPPROTO_UDP)
|
||||
{
|
||||
/*If this option is enabled, then all data output on this socket is accumulated into a single
|
||||
datagram that is transmitted when the option is disabled. */
|
||||
if (optname == UDP_CORK) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int picoTCP::pico_getsockopt(VirtualSocket *vs, int level, int optname, void *optval, socklen_t *optlen)
|
||||
{
|
||||
int err = -1, optval_tmp = 0;
|
||||
errno = 0;
|
||||
if (vs == NULL) {
|
||||
DEBUG_ERROR("invalid vs");
|
||||
return -1;
|
||||
} else {
|
||||
DEBUG_EXTRA("fd=%d, level=%d, optname=%d", vs->app_fd, level, optname);
|
||||
}
|
||||
if (level == SOL_SOCKET)
|
||||
{
|
||||
/* Turns on recording of debugging information. This option enables or disables debugging in the underlying
|
||||
protocol modules. This option takes an int value. This is a Boolean option.*/
|
||||
if (optname == SO_DEBUG)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Specifies that the rules used in validating addresses supplied to bind() should allow reuse of local
|
||||
addresses, if this is supported by the protocol. This option takes an int value. This is a Boolean option.*/
|
||||
if (optname == SO_REUSEADDR)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Keeps connections active by enabling the periodic transmission of messages, if this is supported by the
|
||||
protocol. This option takes an int value. */
|
||||
if (optname == SO_KEEPALIVE)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Requests that outgoing messages bypass the standard routing facilities. */
|
||||
if (optname == SO_DONTROUTE)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Lingers on a close() if data is present. */
|
||||
if (optname == SO_LINGER)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Permits sending of broadcast messages, if this is supported by the protocol. This option takes an int
|
||||
value. This is a Boolean option. */
|
||||
if (optname == SO_BROADCAST)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Leaves received out-of-band data (data marked urgent) inline. This option takes an int value. This is a
|
||||
Boolean option. */
|
||||
if (optname == SO_OOBINLINE)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Sets send buffer size. This option takes an int value. */
|
||||
if (optname == SO_SNDBUF)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Sets receive buffer size. This option takes an int value. */
|
||||
if (optname == SO_RCVBUF)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* */
|
||||
if (optname == SO_STYLE)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* */
|
||||
if (optname == SO_TYPE)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Get error status and clear */
|
||||
if (optname == SO_ERROR)
|
||||
{
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (level == IPPROTO_IP)
|
||||
{
|
||||
if (optname == IP_ADD_MEMBERSHIP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_ADD_SOURCE_MEMBERSHIP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_BIND_ADDRESS_NO_PORT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_BLOCK_SOURCE) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_DROP_MEMBERSHIP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_DROP_SOURCE_MEMBERSHIP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_FREEBIND) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_HDRINCL) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MSFILTER) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MTU) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MTU_DISCOVER) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MULTICAST_ALL) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MULTICAST_IF) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MULTICAST_LOOP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_MULTICAST_TTL) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_NODEFRAG) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_OPTIONS) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_PKTINFO) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_RECVOPTS) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_RECVORIGDSTADDR) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_RECVTOS) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_RECVTTL) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_RETOPTS) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_ROUTER_ALERT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_TOS) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_TRANSPARENT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_TTL) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
if (optname == IP_UNBLOCK_SOURCE) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
// TODO
|
||||
return -1;
|
||||
}
|
||||
if (level == IPPROTO_TCP)
|
||||
{
|
||||
struct pico_socket *p = vs->picosock;
|
||||
if (p == NULL) {
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
/* If set, don't send out partial frames. */
|
||||
if (optname == TCP_CORK) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Allow a listener to be awakened only when data arrives on the socket. */
|
||||
if (optname == TCP_DEFER_ACCEPT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Used to collect information about this socket. */
|
||||
if (optname == TCP_INFO) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* The maximum number of keepalive probes TCP should send before dropping the connection.*/
|
||||
if (optname == TCP_KEEPCNT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* The time (in seconds) the connection needs to remain idle before TCP starts sending keepalive probes,
|
||||
if the socket option SO_KEEPALIVE has been set on this socket. */
|
||||
if (optname == TCP_KEEPIDLE) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* The time (in seconds) between individual keepalive probes.*/
|
||||
if (optname == TCP_KEEPINTVL) {
|
||||
// TODO
|
||||
return -1;
|
||||
}
|
||||
/* The lifetime of orphaned FIN_WAIT2 state sockets. */
|
||||
if (optname == TCP_LINGER2) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* The maximum segment size for outgoing TCP packets. */
|
||||
if (optname == TCP_MAXSEG) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* If set, disable the Nagle algorithm. */
|
||||
if (optname == TCP_NODELAY) {
|
||||
|
||||
/*
|
||||
|
||||
TODO:
|
||||
|
||||
PICO TCP NODELAY - Nagle algorithm, value casted to (int *) (0 = disabled, 1 = enabled)
|
||||
• PICO SOCKET OPT RCVBUF - Read current receive buffer size for the socket
|
||||
• PICO SOCKET OPT SNDBUF - Read current receive buffer size for the socket
|
||||
• PICO IP MULTICAST IF - (Not supported) Link multicast datagrams are sent from
|
||||
• PICO IP MULTICAST TTL - TTL (0-255) of multicast datagrams
|
||||
• PICO IP MULTICAST LOOP - Loop back a copy of an outgoing multicast datagram, as long
|
||||
as it is a member of the multicast group, or not
|
||||
|
||||
*/
|
||||
if ((err = pico_socket_getoption(p, PICO_TCP_NODELAY, &optval_tmp)) < 0) {
|
||||
if (err == PICO_ERR_EINVAL) {
|
||||
DEBUG_ERROR("error while disabling Nagle's algorithm");
|
||||
errno = ENOPROTOOPT;
|
||||
err = -1;
|
||||
}
|
||||
}
|
||||
memcpy(optval, &optval_tmp, *optlen);
|
||||
return err;
|
||||
}
|
||||
/* Enable quickack mode if set or disable quickack mode if cleared. */
|
||||
if (optname == TCP_QUICKACK) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Set the number of SYN retransmits that TCP should send before aborting the attempt to connect. It
|
||||
cannot exceed 255. */
|
||||
if (optname == TCP_SYNCNT) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
/* Bound the size of the advertised window to this value. The kernel imposes a minimum size of
|
||||
SOCK_MIN_RCVBUF/2. */
|
||||
if (optname == TCP_WINDOW_CLAMP) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (level == IPPROTO_UDP)
|
||||
{
|
||||
/*If this option is enabled, then all data output on this socket is accumulated into a single
|
||||
datagram that is transmitted when the option is disabled. */
|
||||
if (optname == UDP_CORK) {
|
||||
// TODO
|
||||
errno = ENOPROTOOPT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int picoTCP::map_pico_err_to_errno(int err)
|
||||
{
|
||||
if (err == PICO_ERR_NOERR) { errno = 0; return 0; } //
|
||||
|
||||
@@ -150,7 +150,8 @@ namespace ZeroTier
|
||||
/*
|
||||
* Packets from the ZeroTier virtual wire enter the stack here
|
||||
*/
|
||||
void pico_eth_rx(VirtualTap *tap, const ZeroTier::MAC &from,const ZeroTier::MAC &to,unsigned int etherType,const void *data,unsigned int len);
|
||||
void pico_eth_rx(VirtualTap *tap, const ZeroTier::MAC &from, const ZeroTier::MAC &to,
|
||||
unsigned int etherType, const void *data, unsigned int len);
|
||||
|
||||
/*
|
||||
* Creates a stack-specific "socket" or "VirtualSocket object"
|
||||
@@ -180,7 +181,7 @@ namespace ZeroTier
|
||||
/*
|
||||
* Read from RX buffer to application - Called from VirtualTap
|
||||
*/
|
||||
int pico_Read(VirtualTap *tap, ZeroTier::PhySocket *sock,VirtualSocket *vs,bool stack_invoked);
|
||||
int pico_Read(VirtualTap *tap, ZeroTier::PhySocket *sock, VirtualSocket *vs, bool stack_invoked);
|
||||
|
||||
/*
|
||||
* Write to userspace network stack - Called from VirtualTap
|
||||
@@ -197,6 +198,16 @@ namespace ZeroTier
|
||||
*/
|
||||
int pico_Shutdown(VirtualSocket *vs, int how);
|
||||
|
||||
/*
|
||||
* Sets a property of a socket
|
||||
*/
|
||||
static int pico_setsockopt(VirtualSocket *vs, int level, int optname, const void *optval, socklen_t optlen);
|
||||
|
||||
/*
|
||||
* Gets a property of a socket
|
||||
*/
|
||||
static int pico_getsockopt(VirtualSocket *vs, int level, int optname, void *optval, socklen_t *optlen);
|
||||
|
||||
/*
|
||||
* Converts a pico_err to its most closely-related errno, and sets errno
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user