29 changed files with 4351 additions and 4102 deletions
Binary file not shown.
@ -0,0 +1,188 @@
|
||||
/**
|
||||
* libzt API example |
||||
* |
||||
* Pingable node joined to public ZT network "earth" |
||||
*/ |
||||
|
||||
/**
|
||||
* |
||||
* IDENTITIES and AUTHORIZATION: |
||||
* |
||||
* - Upon the first execution of this code, a new identity will be generated and placed in |
||||
* the location given in the first argument to zts_start(path, ...). If you accidentally |
||||
* duplicate the identity files and use them simultaneously in a different node instance |
||||
* you will experience undefined behavior and it is likely nothing will work. |
||||
*
|
||||
* - You must authorize the node ID provided by the ZTS_EVENT_NODE_ONLINE callback to join |
||||
* your network, otherwise nothing will happen. This can be done manually or via |
||||
* our web API: https://my.zerotier.com/help/api
|
||||
* |
||||
* - Exceptions to the above rule are: |
||||
* 1) Joining a public network (such as "earth") |
||||
* 2) Joining an Ad-hoc network, (no controller and therefore requires no authorization.) |
||||
* |
||||
* |
||||
* ESTABLISHING A CONNECTION: |
||||
* |
||||
* - Creating a standard socket connection generally works the same as it would using |
||||
* an ordinary socket interface, however with libzt there is a subtle difference in |
||||
* how connections are established which may cause confusion: |
||||
* |
||||
* The underlying virtual ZT layer creates what are called "transport-triggered links" |
||||
* between nodes. That is, links are not established until an attempt to communicate |
||||
* with a peer has taken place. The side effect is that the first few packets sent from |
||||
* a libzt instance are usually relayed via our free infrastructure and it isn't until a |
||||
* root server has passed contact information to both peers that a direct connection will be |
||||
* established. Therefore, it is required that multiple connection attempts be undertaken |
||||
* when initially communicating with a peer. After a transport-triggered link is |
||||
* established libzt will inform you via ZTS_EVENT_PEER_P2P for a specific peer ID. No |
||||
* action is required on your part for this callback event. |
||||
* |
||||
* Note: In these initial moments before ZTS_EVENT_PEER_P2P has been received for a |
||||
* specific peer, traffic may be slow, jittery and there may be high packet loss. |
||||
* This will subside within a couple of seconds. |
||||
* |
||||
* |
||||
* ERROR HANDLING: |
||||
* |
||||
* - libzt's API is actually composed of two categories of functions with slightly |
||||
* different error reporting mechanisms. |
||||
* |
||||
* Category 1: Control functions (zts_start, zts_join, zts_get_peer_status, etc). Errors |
||||
* returned by these functions can be any of the following: |
||||
* |
||||
* ZTS_ERR_OK 0 // No error
|
||||
* ZTS_ERR_SOCKET -1 // Socket error, see zts_errno
|
||||
* ZTS_ERR_SERVICE -2 // You probably did something at the wrong time
|
||||
* ZTS_ERR_ARG -3 // Invalid argument
|
||||
* ZTS_ERR_NO_RESULT -4 // No result (not necessarily an error)
|
||||
* ZTS_ERR_GENERAL -5 // Consider filing a bug report
|
||||
* |
||||
* Category 2: Sockets (zts_socket, zts_bind, zts_connect, zts_listen, etc). |
||||
* Errors returned by these functions can be the same as the above. With |
||||
* the added possibility of zts_errno being set. Much like standard |
||||
* errno this will provide a more specific reason for an error's occurrence. |
||||
* See ZeroTierSockets.h for values. |
||||
* |
||||
* |
||||
* API COMPATIBILITY WITH HOST OS: |
||||
* |
||||
* - While the ZeroTier socket interface can coexist with your host OS's own interface in |
||||
* the same file with no type and naming conflicts, try not to mix and match host |
||||
* OS/libzt structures, functions, or constants. It may look similar and may even work |
||||
* some of the time but there enough differences that it will cause headaches. Here |
||||
* are a few guidelines: |
||||
* |
||||
* If you are calling a zts_* function, use the appropriate ZTS_* constants: |
||||
*
|
||||
* zts_socket(ZTS_AF_INET6, ZTS_SOCK_DGRAM, 0); (CORRECT) |
||||
* zts_socket(AF_INET6, SOCK_DGRAM, 0); (INCORRECT) |
||||
* |
||||
* If you are calling a zts_* function, use the appropriate zts_* structure: |
||||
* |
||||
* struct zts_sockaddr_in in4; <------ Note the zts_* prefix |
||||
* ... |
||||
* zts_bind(fd, (struct zts_sockaddr *)&in4, sizeof(struct zts_sockaddr_in)) < 0) |
||||
* |
||||
*/ |
||||
|
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
|
||||
#include "ZeroTierSockets.h" |
||||
|
||||
bool nodeReady = false; |
||||
bool networkReady = false; |
||||
|
||||
// Example callbacks
|
||||
void myZeroTierEventCallback(void *msgPtr) |
||||
{ |
||||
struct zts_callback_msg *msg = (struct zts_callback_msg *)msgPtr; |
||||
|
||||
if (msg->eventCode == ZTS_EVENT_NODE_ONLINE) { |
||||
printf("ZTS_EVENT_NODE_ONLINE --- This node's ID is %llx\n", msg->node->address); |
||||
nodeReady = true; |
||||
} |
||||
if (msg->eventCode == ZTS_EVENT_NODE_OFFLINE) { |
||||
printf("ZTS_EVENT_NODE_OFFLINE --- Check your physical Internet connection, router, firewall, etc. What ports are you blocking?\n"); |
||||
nodeReady = false; |
||||
} |
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_REQ_CONFIG) { |
||||
printf("ZTS_EVENT_NETWORK_REQ_CONFIG --- Requesting config for network %llx, please wait a few seconds...\n", msg->network->nwid); |
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_ACCESS_DENIED) { |
||||
printf("ZTS_EVENT_NETWORK_ACCESS_DENIED --- Access to virtual network %llx has been denied. Did you authorize the node yet?\n", |
||||
msg->network->nwid); |
||||
} |
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP6) { |
||||
printf("ZTS_EVENT_NETWORK_READY_IP6 --- Network config received. IPv6 traffic can now be sent over network %llx\n", |
||||
msg->network->nwid); |
||||
networkReady = true; |
||||
} |
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_DOWN) { |
||||
printf("ZTS_EVENT_NETWORK_DOWN --- %llx\n", msg->network->nwid); |
||||
} |
||||
if (msg->eventCode == ZTS_EVENT_ADDR_ADDED_IP4) { |
||||
char ipstr[ZTS_INET_ADDRSTRLEN]; |
||||
struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)&(msg->addr->addr); |
||||
zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), ipstr, ZTS_INET_ADDRSTRLEN); |
||||
printf("ZTS_EVENT_ADDR_NEW_IP4 --- Join %llx and ping me at %s\n",
|
||||
msg->addr->nwid, ipstr); |
||||
} |
||||
if (msg->eventCode == ZTS_EVENT_ADDR_ADDED_IP6) { |
||||
char ipstr[ZTS_INET6_ADDRSTRLEN]; |
||||
struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(msg->addr->addr); |
||||
zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN); |
||||
printf("ZTS_EVENT_ADDR_NEW_IP6 --- Join %llx and ping me at %s\n",
|
||||
msg->addr->nwid, ipstr); |
||||
} |
||||
// Don't worry if you don't recognize a peer ID, it's most likely our infrastructure
|
||||
if (msg->eventCode == ZTS_EVENT_PEER_DIRECT) { |
||||
printf("ZTS_EVENT_PEER_DIRECT --- There is now a direct path to peer %llx\n", |
||||
msg->peer->address); |
||||
} |
||||
if (msg->eventCode == ZTS_EVENT_PEER_RELAY) { |
||||
printf("ZTS_EVENT_PEER_RELAY --- No direct path to peer %llx\n", |
||||
msg->peer->address); |
||||
} |
||||
} |
||||
|
||||
int main(int argc, char **argv)
|
||||
{ |
||||
if (argc != 3) { |
||||
printf("\nlibzt example\n"); |
||||
printf("earthtest <config_file_path> <ztServicePort>\n"); |
||||
exit(0); |
||||
} |
||||
int ztServicePort = atoi(argv[2]); // Port ZT uses to send encrypted UDP packets to peers (try something like 9994)
|
||||
|
||||
int err = ZTS_ERR_OK; |
||||
zts_allow_network_caching(false); |
||||
|
||||
if((err = zts_start(argv[1], &myZeroTierEventCallback, ztServicePort)) != ZTS_ERR_OK) { |
||||
printf("Unable to start service, error = %d. Exiting.\n", err); |
||||
exit(1); |
||||
} |
||||
printf("Waiting for node to come online...\n"); |
||||
while (!nodeReady) { zts_delay_ms(50); } |
||||
printf("This node's identity is stored in %s\n", argv[1]); |
||||
|
||||
uint64_t nwid = 0x8056c2e21c000001; |
||||
|
||||
if((err = zts_join(nwid)) != ZTS_ERR_OK) { |
||||
printf("Unable to join network, error = %d. Exiting.\n", err); |
||||
exit(1); |
||||
} |
||||
printf("Joining network %llx\n", nwid); |
||||
while (!networkReady) { zts_delay_ms(50); } |
||||
|
||||
// Idle and just show callback events, stack statistics, etc
|
||||
|
||||
printf("Node will now idle...\n"); |
||||
while (true) { zts_delay_ms(1000); } |
||||
|
||||
// Shut down service and stack threads
|
||||
|
||||
zts_stop(); |
||||
return 0; |
||||
} |
||||
@ -0,0 +1,247 @@
|
||||
/** |
||||
* libzt API example |
||||
* |
||||
* Specify location of zt.framework and link to standard C++ library: |
||||
* |
||||
* clang -lc++ -framework Foundation -F . -framework zt adhoc.m -o adhoc; |
||||
* |
||||
* Pingable node joined to controller-less adhoc network with a 6PLANE addressing scheme |
||||
*/ |
||||
|
||||
#import <Foundation/Foundation.h> |
||||
|
||||
#import <zt/ZeroTier.h> |
||||
|
||||
#include <arpa/inet.h> |
||||
|
||||
/** |
||||
* |
||||
* IDENTITIES and AUTHORIZATION: |
||||
* |
||||
* - Upon the first execution of this code, a new identity will be generated and placed in |
||||
* the location given in the first argument to zts_start(path, ...). If you accidentally |
||||
* duplicate the identity files and use them simultaneously in a different node instance |
||||
* you will experience undefined behavior and it is likely nothing will work. |
||||
* |
||||
* - You must authorize the node ID provided by the ZTS_EVENT_NODE_ONLINE callback to join |
||||
* your network, otherwise nothing will happen. This can be done manually or via |
||||
* our web API: https://my.zerotier.com/help/api |
||||
* |
||||
* - An exception to the above rule is if you are using an Ad-hoc network, it has no |
||||
* controller and therefore requires no authorization. |
||||
* |
||||
* |
||||
* ESTABLISHING A CONNECTION: |
||||
* |
||||
* - Creating a standard socket connection generally works the same as it would using |
||||
* an ordinary socket interface, however with libzt there is a subtle difference in |
||||
* how connections are established which may cause confusion: |
||||
* |
||||
* The underlying virtual ZT layer creates what are called "transport-triggered links" |
||||
* between nodes. That is, links are not established until an attempt to communicate |
||||
* with a peer has taken place. The side effect is that the first few packets sent from |
||||
* a libzt instance are usually relayed via our free infrastructure and it isn't until a |
||||
* root server has passed contact information to both peers that a direct connection will be |
||||
* established. Therefore, it is required that multiple connection attempts be undertaken |
||||
* when initially communicating with a peer. After a transport-triggered link is |
||||
* established libzt will inform you via ZTS_EVENT_PEER_P2P for a specific peer ID. No |
||||
* action is required on your part for this callback event. |
||||
* |
||||
* Note: In these initial moments before ZTS_EVENT_PEER_P2P has been received for a |
||||
* specific peer, traffic may be slow, jittery and there may be high packet loss. |
||||
* This will subside within a couple of seconds. |
||||
* |
||||
* |
||||
* ERROR HANDLING: |
||||
* |
||||
* - libzt's API is actually composed of two categories of functions with slightly |
||||
* different error reporting mechanisms. |
||||
* |
||||
* Category 1: Control functions (zts_start, zts_join, zts_get_peer_status, etc). Errors |
||||
* returned by these functions can be any of the following: |
||||
* |
||||
* [ 0] ZTS_ERR_OK - No error. |
||||
* [-1] ZTS_ERR - Error (see zts_errno for more information). |
||||
* [-2] ZTS_ERR_INVALID_ARG - An argument provided is invalid. |
||||
* [-3] ZTS_ERR_SERVICE - ZT is not yet initialized. Try again. |
||||
* [-4] ZTS_ERR_INVALID_OP - Operation is not permitted (Doesn't make sense in this state). |
||||
* [-5] ZTS_ERR_NO_RESULT - Call succeeded but no result was available. Not always an error. |
||||
* [-6] ZTS_ERR_GENERAL - General internal failure. Consider filing a bug report. |
||||
* |
||||
* Category 2: Sockets (zts_socket, zts_bind, zts_connect, zts_listen, etc). |
||||
* Errors returned by these functions can be the same as the above. With |
||||
* the added possibility of zts_errno being set. Much like standard |
||||
* errno this will provide a more specific reason for an error's occurrence. |
||||
* These error values are defined in: libzt/ext/lwip/src/include/lwip/errno.h |
||||
* and closely map to standard Linux error values. |
||||
* |
||||
* |
||||
* API COMPATIBILITY WITH HOST OS: |
||||
* |
||||
* - Since libzt re-implements a socket API probably very similar to your host OS's own |
||||
* API it may be tempting to mix and match host OS structures and functions with those |
||||
* of libzt. This may work on occasion, but you are tempting fate, so here are a few |
||||
* guidelines: |
||||
* |
||||
* If you are calling a zts_* function, use the appropriate ZTS_* constants: |
||||
* |
||||
* zts_socket(ZTS_AF_INET6, ZTS_SOCK_DGRAM, 0); (CORRECT) |
||||
* zts_socket(AF_INET6, SOCK_DGRAM, 0); (INCORRECT) |
||||
* |
||||
* If you are calling a zts_* function, use the appropriate zts_* structure: |
||||
* |
||||
* struct zts_sockaddr_in in4; <------ Note the zts_* prefix |
||||
* ... |
||||
* zts_bind(fd, (struct sockaddr *)&in4, sizeof(struct zts_sockaddr_in)) < 0) |
||||
* |
||||
* If you are calling a host OS function, use your host OS's constants (and structures!): |
||||
* |
||||
* inet_ntop(AF_INET6, &(in6->sin6_addr), ...); (CORRECT) |
||||
* inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ...); (INCORRECT) |
||||
* |
||||
* If you are calling a host OS function but passing a zts_* structure, this can |
||||
* work sometimes but you should take care to pass the correct host OS constants: |
||||
* |
||||
* struct zts_sockaddr_in6 in6; |
||||
* ... |
||||
* inet_ntop(AF_INET6, &(in6->sin6_addr), dstStr, INET6_ADDRSTRLEN); |
||||
*/ |
||||
|
||||
void delay_ms(long ms) { usleep(ms*1000); } |
||||
|
||||
bool nodeReady = false; |
||||
bool networkReady = false; |
||||
|
||||
// Example callbacks |
||||
void myZeroTierEventCallback(struct zts_callback_msg *msg) |
||||
{ |
||||
// Node events |
||||
if (msg->eventCode == ZTS_EVENT_NODE_ONLINE) { |
||||
NSLog(@"ZTS_EVENT_NODE_ONLINE --- This node's ID is %llx\n", msg->node->address); |
||||
nodeReady = true; |
||||
} |
||||
if (msg->eventCode == ZTS_EVENT_NODE_OFFLINE) { |
||||
NSLog(@"ZTS_EVENT_NODE_OFFLINE --- Check your physical Internet connection, router, firewall, etc. What ports are you blocking?\n"); |
||||
nodeReady = false; |
||||
} |
||||
// Virtual network events |
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_NOT_FOUND) { |
||||
NSLog(@"ZTS_EVENT_NETWORK_NOT_FOUND --- Are you sure %llx is a valid network?\n", |
||||
msg->network->nwid); |
||||
} |
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_REQUESTING_CONFIG) { |
||||
NSLog(@"ZTS_EVENT_NETWORK_REQUESTING_CONFIG --- Requesting config for network %llx, please wait a few seconds...\n", msg->network->nwid); |
||||
} |
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_ACCESS_DENIED) { |
||||
NSLog(@"ZTS_EVENT_NETWORK_ACCESS_DENIED --- Access to virtual network %llx has been denied. Did you authorize the node yet?\n", |
||||
msg->network->nwid); |
||||
} |
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP6) { |
||||
NSLog(@"ZTS_EVENT_NETWORK_READY_IP6 --- Network config received. IPv6 traffic can now be sent over network %llx\n", |
||||
msg->network->nwid); |
||||
networkReady = true; |
||||
} |
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_DOWN) { |
||||
NSLog(@"ZTS_EVENT_NETWORK_DOWN --- %llx\n", msg->network->nwid); |
||||
} |
||||
// Network stack events |
||||
if (msg->eventCode == ZTS_EVENT_NETIF_UP) { |
||||
NSLog(@"ZTS_EVENT_NETIF_UP --- network=%llx, mac=%llx, mtu=%d\n", |
||||
msg->netif->nwid, |
||||
msg->netif->mac, |
||||
msg->netif->mtu); |
||||
networkReady = true; |
||||
} |
||||
if (msg->eventCode == ZTS_EVENT_NETIF_DOWN) { |
||||
NSLog(@"ZTS_EVENT_NETIF_DOWN --- network=%llx, mac=%llx\n", |
||||
msg->netif->nwid, |
||||
msg->netif->mac); |
||||
|
||||
networkReady = true; |
||||
} |
||||
// Address events |
||||
if (msg->eventCode == ZTS_EVENT_ADDR_ADDED_IP6) { |
||||
char ipstr[INET6_ADDRSTRLEN]; |
||||
struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(msg->addr->addr); |
||||
inet_ntop(AF_INET6, &(in6->sin6_addr), ipstr, INET6_ADDRSTRLEN); |
||||
NSLog(@"ZTS_EVENT_ADDR_NEW_IP6 --- Join %llx and ping me at %s\n", |
||||
msg->addr->nwid, ipstr); |
||||
} |
||||
// Peer events |
||||
// If you don't recognize the peer ID, don't panic, this is most likely one of our root servers |
||||
if (msg->eventCode == ZTS_EVENT_PEER_P2P) { |
||||
NSLog(@"ZTS_EVENT_PEER_P2P --- There is now a direct path to peer %llx\n", |
||||
msg->peer->address); |
||||
} |
||||
if (msg->eventCode == ZTS_EVENT_PEER_RELAY) { |
||||
NSLog(@"ZTS_EVENT_PEER_RELAY --- No direct path to peer %llx\n", |
||||
msg->peer->address); |
||||
} |
||||
} |
||||
|
||||
/* |
||||
|
||||
Ad-hoc Network: |
||||
|
||||
ffSSSSEEEE000000 |
||||
| | | | |
||||
| | | Reserved for future use, must be 0 |
||||
| | End of port range (hex) |
||||
| Start of port range (hex) |
||||
Reserved ZeroTier address prefix indicating a controller-less network. |
||||
|
||||
Ad-hoc networks are public (no access control) networks that have no network controller. Instead |
||||
their configuration and other credentials are generated locally. Ad-hoc networks permit only IPv6 |
||||
UDP and TCP unicast traffic (no multicast or broadcast) using 6plane format NDP-emulated IPv6 |
||||
addresses. In addition an ad-hoc network ID encodes an IP port range. UDP packets and TCP SYN |
||||
(connection open) packets are only allowed to destination ports within the encoded range. |
||||
|
||||
For example ff00160016000000 is an ad-hoc network allowing only SSH, while ff0000ffff000000 is an |
||||
ad-hoc network allowing any UDP or TCP port. |
||||
|
||||
Keep in mind that these networks are public and anyone in the entire world can join them. Care must |
||||
be taken to avoid exposing vulnerable services or sharing unwanted files or other resources. |
||||
|
||||
*/ |
||||
|
||||
int main(int argc, char **argv) |
||||
{ |
||||
if (argc != 5) { |
||||
NSLog(@"\nlibzt example\n"); |
||||
NSLog(@"adhoc <config_file_path> <adhocStartPort> <adhocEndPort> <ztServicePort>\n"); |
||||
exit(0); |
||||
} |
||||
int adhocStartPort = atoi(argv[2]); // Start of port range your application will use |
||||
int adhocEndPort = atoi(argv[3]); // End of port range your application will use |
||||
int ztServicePort = atoi(argv[4]); // Port ZT uses to send encrypted UDP packets to peers (try something like 9994) |
||||
|
||||
uint64_t adhoc_nwid = zts_generate_adhoc_nwid_from_range(adhocStartPort, adhocEndPort); |
||||
int err = ZTS_ERR_OK; |
||||
|
||||
zts_set_network_caching(false); |
||||
|
||||
if((err = zts_start(argv[1], &myZeroTierEventCallback, ztServicePort)) != ZTS_ERR_OK) { |
||||
NSLog(@"Unable to start service, error = %d. Exiting.\n", err); |
||||
exit(1); |
||||
} |
||||
NSLog(@"Waiting for node to come online...\n"); |
||||
while (!nodeReady) { delay_ms(50); } |
||||
NSLog(@"This node's identity is stored in %s\n", argv[1]); |
||||
|
||||
if((err = zts_join(adhoc_nwid)) != ZTS_ERR_OK) { |
||||
NSLog(@"Unable to join network, error = %d. Exiting.\n", err); |
||||
exit(1); |
||||
} |
||||
NSLog(@"Joining network %llx\n", adhoc_nwid); |
||||
while (!networkReady) { delay_ms(50); } |
||||
|
||||
// Idle and just show callback events, stack statistics, etc |
||||
|
||||
NSLog(@"Node will now idle...\n"); |
||||
while (true) { delay_ms(1000); } |
||||
|
||||
// Shut down service and stack threads |
||||
|
||||
zts_stop(); |
||||
return 0; |
||||
} |
||||
@ -0,0 +1,143 @@
|
||||
/** |
||||
* libzt Swift example |
||||
* |
||||
* swiftc -lc++ -import-objc-header ../../include/ZeroTierSockets.h -L. -lzt main.swift -o main; |
||||
* ./main |
||||
*/ |
||||
|
||||
import Swift |
||||
import Foundation |
||||
|
||||
var nodeReady:Bool = false |
||||
var networkReady:Bool = false |
||||
|
||||
let myZeroTierEventCallback : @convention(c) (UnsafeMutableRawPointer?) -> Void = |
||||
{ |
||||
(msgPtr) -> Void in |
||||
let msg = msgPtr?.bindMemory(to: zts_callback_msg.self, capacity: 1) |
||||
|
||||
var eventCode = msg!.pointee.eventCode |
||||
|
||||
let node = msg?.pointee.node; |
||||
let network = msg?.pointee.network; |
||||
|
||||
switch Int32(eventCode) |
||||
{ |
||||
case ZTS_EVENT_NODE_ONLINE: |
||||
let nodeId:UInt64 = node!.pointee.address |
||||
print(String(format: "ZTS_EVENT_NODE_ONLINE (%llx)", nodeId)) |
||||
nodeReady = true; |
||||
|
||||
case ZTS_EVENT_NODE_OFFLINE: |
||||
print("ZTS_EVENT_NODE_OFFLINE\n") |
||||
nodeReady = false; |
||||
|
||||
case ZTS_EVENT_NODE_NORMAL_TERMINATION: |
||||
print("ZTS_EVENT_NODE_NORMAL_TERMINATION\n") |
||||
|
||||
case ZTS_EVENT_NETWORK_NOT_FOUND: |
||||
let networkId:UInt64 = network!.pointee.nwid |
||||
print(String(format: "ZTS_EVENT_NETWORK_NOT_FOUND (%llx)", networkId)) |
||||
|
||||
case ZTS_EVENT_NETWORK_REQUESTING_CONFIG: |
||||
let networkId:UInt64 = network!.pointee.nwid |
||||
print(String(format: "ZTS_EVENT_NETWORK_REQUESTING_CONFIG (%llx)", networkId)) |
||||
|
||||
case ZTS_EVENT_NETWORK_ACCESS_DENIED: |
||||
let networkId:UInt64 = network!.pointee.nwid |
||||
print(String(format: "ZTS_EVENT_NETWORK_ACCESS_DENIED (%llx)", networkId)) |
||||
|
||||
case ZTS_EVENT_NETWORK_READY_IP4: |
||||
let networkId:UInt64 = network!.pointee.nwid |
||||
print(String(format: "ZTS_EVENT_NETWORK_READY_IP4 (%llx)", networkId)) |
||||
networkReady = true; |
||||
|
||||
case ZTS_EVENT_NETWORK_READY_IP6: |
||||
let networkId:UInt64 = network!.pointee.nwid |
||||
print(String(format: "ZTS_EVENT_NETWORK_READY_IP6 (%llx)", networkId)) |
||||
networkReady = true; |
||||
|
||||
case ZTS_EVENT_NETWORK_DOWN: |
||||
let networkId:UInt64 = network!.pointee.nwid |
||||
print(String(format: "ZTS_EVENT_NETWORK_DOWN (%llx)", networkId)) |
||||
|
||||
/* |
||||
// Network stack events |
||||
case ZTS_EVENT_NETIF_UP: |
||||
print("ZTS_EVENT_NETIF_UP --- network=%llx, mac=%llx, mtu=%d\n", |
||||
msg.netif->nwid, |
||||
msg.netif->mac, |
||||
msg.netif->mtu) |
||||
//networkReady = true; |
||||
|
||||
case ZTS_EVENT_NETIF_DOWN: |
||||
print("ZTS_EVENT_NETIF_DOWN --- network=%llx, mac=%llx\n", |
||||
msg.netif->nwid, |
||||
msg.netif->mac) |
||||
//networkReady = true; |
||||
|
||||
// Address events |
||||
case ZTS_EVENT_ADDR_ADDED_IP4: |
||||
print("ZTS_EVENT_ADDR_ADDED_IP4") |
||||
/* |
||||
char ipstr[INET_ADDRSTRLEN]; |
||||
struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)&(msg.addr->addr); |
||||
inet_ntop(AF_INET, &(in4->sin_addr), ipstr, INET_ADDRSTRLEN); |
||||
print("ZTS_EVENT_ADDR_NEW_IP4 --- This node's virtual address on network %llx is %s\n", |
||||
msg.addr->nwid, ipstr) |
||||
*/ |
||||
|
||||
case ZTS_EVENT_ADDR_ADDED_IP6: |
||||
print("ZTS_EVENT_ADDR_ADDED_IP6") |
||||
/* |
||||
char ipstr[INET6_ADDRSTRLEN]; |
||||
struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(msg.addr->addr); |
||||
inet_ntop(AF_INET6, &(in6->sin6_addr), ipstr, INET6_ADDRSTRLEN); |
||||
print("ZTS_EVENT_ADDR_NEW_IP6 --- This node's virtual address on network %llx is %s\n", |
||||
msg.addr->nwid, ipstr) |
||||
*/ |
||||
|
||||
case ZTS_EVENT_ADDR_REMOVED_IP4: |
||||
print("ZTS_EVENT_ADDR_REMOVED_IP4") |
||||
/* |
||||
char ipstr[INET_ADDRSTRLEN]; |
||||
struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)&(msg.addr->addr); |
||||
inet_ntop(AF_INET, &(in4->sin_addr), ipstr, INET_ADDRSTRLEN); |
||||
print("ZTS_EVENT_ADDR_REMOVED_IP4 --- The virtual address %s for this node on network %llx has been removed.\n", |
||||
ipstr, msg.addr->nwid) |
||||
*/ |
||||
|
||||
case ZTS_EVENT_ADDR_REMOVED_IP6: |
||||
print("ZTS_EVENT_ADDR_REMOVED_IP6") |
||||
/* |
||||
char ipstr[INET6_ADDRSTRLEN]; |
||||
struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(msg.addr->addr); |
||||
inet_ntop(AF_INET6, &(in6->sin6_addr), ipstr, INET6_ADDRSTRLEN); |
||||
print("ZTS_EVENT_ADDR_REMOVED_IP6 --- The virtual address %s for this node on network %llx has been removed.\n", |
||||
ipstr, msg.addr->nwid) |
||||
*/ |
||||
// Peer events |
||||
case ZTS_EVENT_PEER_P2P: |
||||
print("ZTS_EVENT_PEER_P2P --- node=%llx\n", msg.peer->address) |
||||
case ZTS_EVENT_PEER_RELAY: |
||||
print("ZTS_EVENT_PEER_RELAY --- node=%llx\n", msg.peer->address) |
||||
|
||||
|
||||
*/ |
||||
default: |
||||
print("UNKNOWN_EVENT") |
||||
} |
||||
} |
||||
|
||||
func main() |
||||
{ |
||||
print("waiting for node to come online...") |
||||
zts_start("../../config_path_a", myZeroTierEventCallback, 0) |
||||
while(!nodeReady) { |
||||
sleep(1) |
||||
} |
||||
print("Joining network") |
||||
|
||||
} |
||||
|
||||
main() |
||||
@ -1 +1 @@
|
||||
Subproject commit 95d6387123171d812552cd6213034c823a7e8631 |
||||
Subproject commit 32708c0a8b140efb545cc35101ee5fdeca6d6489 |
||||
@ -0,0 +1,4 @@
|
||||
ZeroTier Socket API |
||||
====== |
||||
|
||||
This is the externally facing plain C API. It provides a platform-agnostic ZeroTier-based socket interface. |
||||
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright (c)2013-2020 ZeroTier, Inc. |
||||
* |
||||
* Use of this software is governed by the Business Source License included |
||||
* in the LICENSE.TXT file in the project's root directory. |
||||
* |
||||
* Change Date: 2024-01-01 |
||||
* |
||||
* On the date above, in accordance with the Business Source License, use |
||||
* of this software will be governed by version 2.0 of the Apache License. |
||||
*/ |
||||
/****/ |
||||
|
||||
/**
|
||||
* @file |
||||
* |
||||
* ZeroTier socket API |
||||
*/ |
||||
|
||||
#ifndef LIBZT_BRIDGING_HEADER_H |
||||
#define LIBZT_BRIDGING_HEADER_H |
||||
|
||||
#include <sys/socket.h> |
||||
#include "ZeroTier.h" |
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Service Controls //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int zts_start(const char *path, void *callbackFunc, int port); |
||||
void zts_stop(); |
||||
int zts_join(uint64_t nwid); |
||||
int zts_leave(uint64_t nwid); |
||||
uint64_t zts_get_node_id(); |
||||
uint64_t zts_get_node_status(); |
||||
int get_peer_status(uint64_t peerId); |
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Socket API //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int zts_socket(int socket_family, int socket_type, int protocol); |
||||
int zts_connect(int fd, const struct sockaddr *addr, socklen_t addrlen); |
||||
int zts_bind(int fd, const struct sockaddr *addr, socklen_t addrlen); |
||||
int zts_listen(int fd, int backlog); |
||||
int zts_accept(int fd, struct sockaddr *addr, socklen_t *addrlen); |
||||
int zts_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen); |
||||
int zts_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen); |
||||
int zts_read(int fd, void *buf, size_t len); |
||||
int zts_write(int fd, const void *buf, size_t len); |
||||
ssize_t zts_send(int fd, const void *buf, size_t len, int flags); |
||||
ssize_t zts_sendto(int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen); |
||||
ssize_t zts_sendmsg(int fd, const struct msghdr *msg, int flags); |
||||
ssize_t zts_recv(int fd, void *buf, size_t len, int flags); |
||||
ssize_t zts_recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen); |
||||
ssize_t zts_recvmsg(int fd, struct msghdr *msg,int flags); |
||||
int zts_shutdown(int fd, int how); |
||||
int zts_close(int fd); |
||||
int zts_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen); |
||||
int zts_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen); |
||||
int zts_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); |
||||
int zts_fcntl(int fd, int cmd, int flags); |
||||
int zts_ioctl(int fd, unsigned long request, void *argp); |
||||
|
||||
#endif // _H
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,251 +0,0 @@
|
||||
/*
|
||||
* Copyright (c)2013-2020 ZeroTier, Inc. |
||||
* |
||||
* Use of this software is governed by the Business Source License included |
||||
* in the LICENSE.TXT file in the project's root directory. |
||||
* |
||||
* Change Date: 2024-01-01 |
||||
* |
||||
* On the date above, in accordance with the Business Source License, use |
||||
* of this software will be governed by version 2.0 of the Apache License. |
||||
*/ |
||||
/****/ |
||||
|
||||
/**
|
||||
* @file |
||||
* |
||||
* Common constants used throughout the SDK |
||||
*/ |
||||
|
||||
#ifndef ZEROTIER_CONSTANTS_H |
||||
#define ZEROTIER_CONSTANTS_H |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
// Custom errno to prevent conflicts with platform's own errno
|
||||
extern int zts_errno; |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Control API error codes //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// No error.
|
||||
#define ZTS_ERR_OK 0 |
||||
// Error (see zts_errno for more info)
|
||||
#define ZTS_ERR -1 |
||||
// A argument provided is invalid (e.g. out of range, NULL, etc)
|
||||
#define ZTS_ERR_INVALID_ARG -2 |
||||
// The service isn't initialized or is currently unavailable. Try again.
|
||||
#define ZTS_ERR_SERVICE -3 |
||||
// This API operation is not permitted or doesn't make sense at this time.
|
||||
#define ZTS_ERR_INVALID_OP -4 |
||||
// The call succeeded, but no object or relevant result was available.
|
||||
#define ZTS_ERR_NO_RESULT -5 |
||||
// General internal failure. Consider filing a bug report.
|
||||
#define ZTS_ERR_GENERAL -6 |
||||
|
||||
/**
|
||||
* The system port upon which ZT traffic is sent and received |
||||
*/ |
||||
#define ZTS_DEFAULT_PORT 9994 |
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Control API event codes //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define ZTS_EVENT_NONE -1 |
||||
#define ZTS_EVENT_NODE_UP 0 |
||||
// Standard node events
|
||||
#define ZTS_EVENT_NODE_OFFLINE 1 |
||||
#define ZTS_EVENT_NODE_ONLINE 2 |
||||
#define ZTS_EVENT_NODE_DOWN 3 |
||||
#define ZTS_EVENT_NODE_IDENTITY_COLLISION 4 |
||||
#define ZTS_EVENT_NODE_UNRECOVERABLE_ERROR 16 |
||||
#define ZTS_EVENT_NODE_NORMAL_TERMINATION 17 |
||||
// Network events
|
||||
#define ZTS_EVENT_NETWORK_NOT_FOUND 32 |
||||
#define ZTS_EVENT_NETWORK_CLIENT_TOO_OLD 33 |
||||
#define ZTS_EVENT_NETWORK_REQUESTING_CONFIG 34 |
||||
#define ZTS_EVENT_NETWORK_OK 35 |
||||
#define ZTS_EVENT_NETWORK_ACCESS_DENIED 36 |
||||
#define ZTS_EVENT_NETWORK_READY_IP4 37 |
||||
#define ZTS_EVENT_NETWORK_READY_IP6 38 |
||||
#define ZTS_EVENT_NETWORK_READY_IP4_IP6 39 |
||||
#define ZTS_EVENT_NETWORK_DOWN 40 |
||||
// Network Stack events
|
||||
#define ZTS_EVENT_STACK_UP 48 |
||||
#define ZTS_EVENT_STACK_DOWN 49 |
||||
// lwIP netif events
|
||||
#define ZTS_EVENT_NETIF_UP 64 |
||||
#define ZTS_EVENT_NETIF_DOWN 65 |
||||
#define ZTS_EVENT_NETIF_REMOVED 66 |
||||
#define ZTS_EVENT_NETIF_LINK_UP 67 |
||||
#define ZTS_EVENT_NETIF_LINK_DOWN 68 |
||||
// Peer events
|
||||
#define ZTS_EVENT_PEER_P2P 96 |
||||
#define ZTS_EVENT_PEER_RELAY 97 |
||||
#define ZTS_EVENT_PEER_UNREACHABLE 98 |
||||
// Path events
|
||||
#define ZTS_EVENT_PATH_DISCOVERED 112 |
||||
#define ZTS_EVENT_PATH_ALIVE 113 |
||||
#define ZTS_EVENT_PATH_DEAD 114 |
||||
// Route events
|
||||
#define ZTS_EVENT_ROUTE_ADDED 128 |
||||
#define ZTS_EVENT_ROUTE_REMOVED 129 |
||||
// Address events
|
||||
#define ZTS_EVENT_ADDR_ADDED_IP4 144 |
||||
#define ZTS_EVENT_ADDR_REMOVED_IP4 145 |
||||
#define ZTS_EVENT_ADDR_ADDED_IP6 146 |
||||
#define ZTS_EVENT_ADDR_REMOVED_IP6 147 |
||||
|
||||
// Macros for legacy behaviour
|
||||
#define NODE_EVENT_TYPE(code) code >= ZTS_EVENT_NODE_UP && code <= ZTS_EVENT_NODE_NORMAL_TERMINATION |
||||
#define NETWORK_EVENT_TYPE(code) code >= ZTS_EVENT_NETWORK_NOT_FOUND && code <= ZTS_EVENT_NETWORK_DOWN |
||||
#define STACK_EVENT_TYPE(code) code >= ZTS_EVENT_STACK_UP && code <= ZTS_EVENT_STACK_DOWN |
||||
#define NETIF_EVENT_TYPE(code) code >= ZTS_EVENT_NETIF_UP && code <= ZTS_EVENT_NETIF_LINK_DOWN |
||||
#define PEER_EVENT_TYPE(code) code >= ZTS_EVENT_PEER_P2P && code <= ZTS_EVENT_PEER_UNREACHABLE |
||||
#define PATH_EVENT_TYPE(code) code >= ZTS_EVENT_PATH_DISCOVERED && code <= ZTS_EVENT_PATH_DEAD |
||||
#define ROUTE_EVENT_TYPE(code) code >= ZTS_EVENT_ROUTE_ADDED && code <= ZTS_EVENT_ROUTE_REMOVED |
||||
#define ADDR_EVENT_TYPE(code) code >= ZTS_EVENT_ADDR_ADDED_IP4 && code <= ZTS_EVENT_ADDR_REMOVED_IP6 |
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Common definitions and structures for interacting with the ZT socket API //
|
||||
// This is a subset of lwip/sockets.h, lwip/arch.h, and lwip/inet.h //
|
||||
// //
|
||||
// These re-definitions exist here so that the user application's usage //
|
||||
// of the API is internally consistent with the underlying network stack. //
|
||||
// They have an attached prefix so that they can co-exist with the native //
|
||||
// platform's own definitions and structures. //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Socket protocol types
|
||||
#define ZTS_SOCK_STREAM 0x0001 |
||||
#define ZTS_SOCK_DGRAM 0x0002 |
||||
#define ZTS_SOCK_RAW 0x0003 |
||||
// Socket family types
|
||||
#define ZTS_AF_UNSPEC 0x0000 |
||||
#define ZTS_AF_INET 0x0002 |
||||
#define ZTS_AF_INET6 0x000a |
||||
#define ZTS_PF_INET ZTS_AF_INET |
||||
#define ZTS_PF_INET6 ZTS_AF_INET6 |
||||
#define ZTS_PF_UNSPEC ZTS_AF_UNSPEC |
||||
// Protocol command types
|
||||
#define ZTS_IPPROTO_IP 0x0000 |
||||
#define ZTS_IPPROTO_ICMP 0x0001 |
||||
#define ZTS_IPPROTO_TCP 0x0006 |
||||
#define ZTS_IPPROTO_UDP 0x0011 |
||||
#define ZTS_IPPROTO_IPV6 0x0029 |
||||
#define ZTS_IPPROTO_ICMPV6 0x003a |
||||
#define ZTS_IPPROTO_UDPLITE 0x0088 |
||||
#define ZTS_IPPROTO_RAW 0x00ff |
||||
// send() and recv() flags
|
||||
#define ZTS_MSG_PEEK 0x0001 |
||||
#define ZTS_MSG_WAITALL 0x0002 // NOT YET SUPPORTED
|
||||
#define ZTS_MSG_OOB 0x0004 // NOT YET SUPPORTED
|
||||
#define ZTS_MSG_DONTWAIT 0x0008 |
||||
#define ZTS_MSG_MORE 0x0010 |
||||
// fnctl() commands
|
||||
#define ZTS_F_GETFL 0x0003 |
||||
#define ZTS_F_SETFL 0x0004 |
||||
// fnctl() flags
|
||||
#define ZTS_O_NONBLOCK 0x0001 |
||||
#define ZTS_O_NDELAY 0x0001 |
||||
// Shutdown commands
|
||||
#define ZTS_SHUT_RD 0x0000 |
||||
#define ZTS_SHUT_WR 0x0001 |
||||
#define ZTS_SHUT_RDWR 0x0002 |
||||
// Socket level option number
|
||||
#define ZTS_SOL_SOCKET 0x0fff |
||||
// Socket options
|
||||
#define ZTS_SO_DEBUG 0x0001 // NOT YET SUPPORTED
|
||||
#define ZTS_SO_ACCEPTCONN 0x0002 |
||||
#define ZTS_SO_REUSEADDR 0x0004 |
||||
#define ZTS_SO_KEEPALIVE 0x0008 |
||||
#define ZTS_SO_DONTROUTE 0x0010 // NOT YET SUPPORTED
|
||||
#define ZTS_SO_BROADCAST 0x0020 |
||||
#define ZTS_SO_USELOOPBACK 0x0040 // NOT YET SUPPORTED
|
||||
#define ZTS_SO_LINGER 0x0080 |
||||
#define ZTS_SO_DONTLINGER ((int)(~ZTS_SO_LINGER)) |
||||
#define ZTS_SO_OOBINLINE 0x0100 // NOT YET SUPPORTED
|
||||
#define ZTS_SO_REUSEPORT 0x0200 // NOT YET SUPPORTED
|
||||
#define ZTS_SO_SNDBUF 0x1001 // NOT YET SUPPORTED
|
||||
#define ZTS_SO_RCVBUF 0x1002 |
||||
#define ZTS_SO_SNDLOWAT 0x1003 // NOT YET SUPPORTED
|
||||
#define ZTS_SO_RCVLOWAT 0x1004 // NOT YET SUPPORTED
|
||||
#define ZTS_SO_SNDTIMEO 0x1005 |
||||
#define ZTS_SO_RCVTIMEO 0x1006 |
||||
#define ZTS_SO_ERROR 0x1007 |
||||
#define ZTS_SO_TYPE 0x1008 |
||||
#define ZTS_SO_CONTIMEO 0x1009 |
||||
#define ZTS_SO_NO_CHECK 0x100a |
||||
// IPPROTO_IP options
|
||||
#define ZTS_IP_TOS 0x0001 |
||||
#define ZTS_IP_TTL 0x0002 |
||||
// IPPROTO_TCP options
|
||||
#define ZTS_TCP_NODELAY 0x0001 |
||||
#define ZTS_TCP_KEEPALIVE 0x0002 |
||||
#define ZTS_TCP_KEEPIDLE 0x0003 |
||||
#define ZTS_TCP_KEEPINTVL 0x0004 |
||||
#define ZTS_TCP_KEEPCNT 0x0005 |
||||
// IPPROTO_IPV6 options
|
||||
#define ZTS_IPV6_CHECKSUM 0x0007 // RFC3542
|
||||
#define ZTS_IPV6_V6ONLY 0x001b // RFC3493
|
||||
// Macro's for defining ioctl() command values
|
||||
#define ZTS_IOCPARM_MASK 0x7fU |
||||
#define ZTS_IOC_VOID 0x20000000UL |
||||
#define ZTS_IOC_OUT 0x40000000UL |
||||
#define ZTS_IOC_IN 0x80000000UL |
||||
#define ZTS_IOC_INOUT (ZTS_IOC_IN | ZTS_IOC_OUT) |
||||
#define ZTS_IO(x,y) (ZTS_IOC_VOID | ((x)<<8)|(y)) |
||||
#define ZTS_IOR(x,y,t) (ZTS_IOC_OUT | (((long)sizeof(t) & ZTS_IOCPARM_MASK)<<16) | ((x)<<8) | (y)) |
||||
#define ZTS_IOW(x,y,t) (ZTS_IOC_IN | (((long)sizeof(t) & ZTS_IOCPARM_MASK)<<16) | ((x)<<8) | (y)) |
||||
// ioctl() commands
|
||||
#define ZTS_FIONREAD ZTS_IOR('f', 127, unsigned long) |
||||
#define ZTS_FIONBIO ZTS_IOW('f', 126, unsigned long) |
||||
|
||||
/* FD_SET used for lwip_select */ |
||||
|
||||
#ifndef ZTS_FD_SET |
||||
#undef ZTS_FD_SETSIZE |
||||
// Make FD_SETSIZE match NUM_SOCKETS in socket.c
|
||||
#define ZTS_FD_SETSIZE MEMP_NUM_NETCONN |
||||
#define ZTS_FDSETSAFESET(n, code) do { \ |
||||
if (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0)) { \
|
||||
code; }} while(0) |
||||
#define ZTS_FDSETSAFEGET(n, code) (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0) ?\ |
||||
(code) : 0) |
||||
#define ZTS_FD_SET(n, p) ZTS_FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] |= (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) |
||||
#define ZTS_FD_CLR(n, p) ZTS_FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] &= ~(1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) |
||||
#define ZTS_FD_ISSET(n,p) ZTS_FDSETSAFEGET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] & (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) |
||||
#define ZTS_FD_ZERO(p) memset((void*)(p), 0, sizeof(*(p))) |
||||
|
||||
#elif LWIP_SOCKET_OFFSET |
||||
#error LWIP_SOCKET_OFFSET does not work with external FD_SET! |
||||
#elif ZTS_FD_SETSIZE < MEMP_NUM_NETCONN |
||||
#error "external ZTS_FD_SETSIZE too small for number of sockets" |
||||
#endif // FD_SET
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Statistics //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define ZTS_STATS_PROTOCOL_LINK 0 |
||||
#define ZTS_STATS_PROTOCOL_ETHARP 1 |
||||
#define ZTS_STATS_PROTOCOL_IP 2 |
||||
#define ZTS_STATS_PROTOCOL_UDP 3 |
||||
#define ZTS_STATS_PROTOCOL_TCP 4 |
||||
#define ZTS_STATS_PROTOCOL_ICMP 5 |
||||
#define ZTS_STATS_PROTOCOL_IP_FRAG 6 |
||||
#define ZTS_STATS_PROTOCOL_IP6 7 |
||||
#define ZTS_STATS_PROTOCOL_ICMP6 8 |
||||
#define ZTS_STATS_PROTOCOL_IP6_FRAG 9 |
||||
|
||||
//#if defined(_USING_LWIP_DEFINITIONS_)
|
||||
|
||||
#endif // ZEROTIER_CONSTANTS_H
|
||||
@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright (c)2013-2020 ZeroTier, Inc. |
||||
* |
||||
* Use of this software is governed by the Business Source License included |
||||
* in the LICENSE.TXT file in the project's root directory. |
||||
* |
||||
* Change Date: 2024-01-01 |
||||
* |
||||
* On the date above, in accordance with the Business Source License, use |
||||
* of this software will be governed by version 2.0 of the Apache License. |
||||
*/ |
||||
/****/ |
||||
|
||||
/**
|
||||
* @file |
||||
* |
||||
* Header for ZeroTier service controls |
||||
*/ |
||||
|
||||
#ifndef LIBZT_CONTROLS_HPP |
||||
#define LIBZT_CONTROLS_HPP |
||||
|
||||
#ifdef _WIN32 |
||||
#include <Windows.h> |
||||
#endif |
||||
|
||||
namespace ZeroTier { |
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// ZeroTier Internal Service Controls //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Add a callback event message to the queue. This can be safely called |
||||
* from other threads since a lock-free queue is used. |
||||
* |
||||
* @param eventCode The event ID for this event |
||||
* @param msg Pointer to a structure of pointers to other message-relevant |
||||
* data structures. |
||||
*/ |
||||
void postEvent(int eventCode, void *arg); |
||||
|
||||
/**
|
||||
* Add a callback event message to the queue. This can be safely called |
||||
* from other threads since a lock-free queue is used. Note: For use in |
||||
* situations when no additional information needs to be conveyed to the |
||||
* user application. |
||||
* |
||||
* @param eventCode The event ID for this event |
||||
*/ |
||||
void postEvent(int eventCode); |
||||
|
||||
/**
|
||||
* Free whatever was allocated to contain the callback message |
||||
* |
||||
* @param msg Message to be freed |
||||
*/ |
||||
void freeEvent(struct zts_callback_msg *msg); |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Starts a ZeroTier service in the background |
||||
* |
||||
* @usage For internal use only. |
||||
* @param |
||||
* @return |
||||
*/ |
||||
#if defined(_WIN32) |
||||
DWORD WINAPI _zts_run_service(LPVOID thread_id); |
||||
#else |
||||
void *_zts_run_service(void *thread_id); |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief [Should not be called from user application] This function must be surrounded by
|
||||
* ZT service locks. It will determine if it is currently safe and allowed to operate on
|
||||
* the service. |
||||
* @usage Can be called at any time |
||||
* @return 1 or 0 |
||||
*/ |
||||
int _zts_can_perform_service_operation(); |
||||
|
||||
/**
|
||||
* @brief [Should not be called from user application] Returns whether or not the node is
|
||||
* online. |
||||
* @usage Can be called at any time |
||||
* @return 1 or 0 |
||||
*/ |
||||
int _zts_node_online(); |
||||
|
||||
/**
|
||||
* @brief [Should not be called from user application] Adjusts the delay multiplier for the |
||||
* network stack driver thread. |
||||
* @usage Can be called at any time |
||||
*/ |
||||
void _hibernate_if_needed(); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif // _H
|
||||
@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Copyright (c)2013-2020 ZeroTier, Inc. |
||||
* |
||||
* Use of this software is governed by the Business Source License included |
||||
* in the LICENSE.TXT file in the project's root directory. |
||||
* |
||||
* Change Date: 2024-01-01 |
||||
* |
||||
* On the date above, in accordance with the Business Source License, use |
||||
* of this software will be governed by version 2.0 of the Apache License. |
||||
*/ |
||||
/****/ |
||||
|
||||
/**
|
||||
* @file |
||||
* |
||||
* Callback event processing logic |
||||
*/ |
||||
|
||||
#include "concurrentqueue.h" |
||||
|
||||
#ifdef SDK_JNI |
||||
#include <jni.h> |
||||
#endif |
||||
|
||||
#include "Node.hpp" |
||||
#include "OSUtils.hpp" |
||||
|
||||
#include "Debug.hpp" |
||||
#include "Events.hpp" |
||||
#include "ZeroTierSockets.h" |
||||
#include "NodeService.hpp" |
||||
|
||||
#define NODE_EVENT_TYPE(code) code >= ZTS_EVENT_NODE_UP && code <= ZTS_EVENT_NODE_NORMAL_TERMINATION |
||||
#define NETWORK_EVENT_TYPE(code) code >= ZTS_EVENT_NETWORK_NOT_FOUND && code <= ZTS_EVENT_NETWORK_DOWN |
||||
#define STACK_EVENT_TYPE(code) code >= ZTS_EVENT_STACK_UP && code <= ZTS_EVENT_STACK_DOWN |
||||
#define NETIF_EVENT_TYPE(code) code >= ZTS_EVENT_NETIF_UP && code <= ZTS_EVENT_NETIF_LINK_DOWN |
||||
#define PEER_EVENT_TYPE(code) code >= ZTS_EVENT_PEER_DIRECT && code <= ZTS_EVENT_PEER_UNREACHABLE |
||||
#define PATH_EVENT_TYPE(code) code >= ZTS_EVENT_PATH_DISCOVERED && code <= ZTS_EVENT_PATH_DEAD |
||||
#define ROUTE_EVENT_TYPE(code) code >= ZTS_EVENT_ROUTE_ADDED && code <= ZTS_EVENT_ROUTE_REMOVED |
||||
#define ADDR_EVENT_TYPE(code) code >= ZTS_EVENT_ADDR_ADDED_IP4 && code <= ZTS_EVENT_ADDR_REMOVED_IP6 |
||||
|
||||
namespace ZeroTier { |
||||
|
||||
extern NodeService *service; |
||||
|
||||
// Global state variable shared between Socket, Control, Event and NodeService logic.
|
||||
uint8_t _serviceStateFlags; |
||||
|
||||
// Lock to guard access to callback function pointers.
|
||||
Mutex _callbackLock; |
||||
|
||||
void (*_userEventCallbackFunc)(void *); |
||||
|
||||
moodycamel::ConcurrentQueue<struct ::zts_callback_msg*> _callbackMsgQueue; |
||||
|
||||
void _enqueueEvent(int16_t eventCode, void *arg) |
||||
{ |
||||
struct ::zts_callback_msg *msg = new ::zts_callback_msg(); |
||||
|
||||
msg->node = NULL; |
||||
msg->network = NULL; |
||||
msg->netif = NULL; |
||||
msg->route = NULL; |
||||
msg->path = NULL; |
||||
msg->peer = NULL; |
||||
msg->addr = NULL; |
||||
|
||||
msg->eventCode = eventCode; |
||||
|
||||
if (NODE_EVENT_TYPE(eventCode)) { |
||||
msg->node = (struct zts_node_details*)arg; |
||||
} if (NETWORK_EVENT_TYPE(eventCode)) { |
||||
msg->network = (struct zts_network_details*)arg; |
||||
} if (NETIF_EVENT_TYPE(eventCode)) { |
||||
msg->netif = (struct zts_netif_details*)arg; |
||||
} if (ROUTE_EVENT_TYPE(eventCode)) { |
||||
msg->route = (struct zts_virtual_network_route*)arg; |
||||
} if (PATH_EVENT_TYPE(eventCode)) { |
||||
msg->path = (struct zts_physical_path*)arg; |
||||
} if (PEER_EVENT_TYPE(eventCode)) { |
||||
msg->peer = (struct zts_peer_details*)arg; |
||||
} if (ADDR_EVENT_TYPE(eventCode)) { |
||||
msg->addr = (struct zts_addr_details*)arg; |
||||
} |
||||
_callbackMsgQueue.enqueue(msg); |
||||
} |
||||
|
||||
void _freeEvent(struct ::zts_callback_msg *msg) |
||||
{ |
||||
if (!msg) { |
||||
return; |
||||
} |
||||
if (msg->node) { delete msg->node; } |
||||
if (msg->network) { delete msg->network; } |
||||
if (msg->netif) { delete msg->netif; } |
||||
if (msg->route) { delete msg->route; } |
||||
if (msg->path) { delete msg->path; } |
||||
if (msg->peer) { delete msg->peer; } |
||||
if (msg->addr) { delete msg->addr; } |
||||
} |
||||
|
||||
void _passDequeuedEventToUser(struct ::zts_callback_msg *msg) |
||||
{ |
||||
#ifdef SDK_JNI |
||||
if(_userCallbackMethodRef) { |
||||
JNIEnv *env; |
||||
#if defined(__ANDROID__) |
||||
jint rs = jvm->AttachCurrentThread(&env, NULL); |
||||
#else |
||||
jint rs = jvm->AttachCurrentThread((void **)&env, NULL); |
||||
#endif |
||||
assert (rs == JNI_OK); |
||||
uint64_t arg = 0; |
||||
uint64_t id = 0; |
||||
if (NODE_EVENT_TYPE(msg->eventCode)) { |
||||
id = msg->node ? msg->node->address : 0; |
||||
} |
||||
if (NETWORK_EVENT_TYPE(msg->eventCode)) { |
||||
id = msg->network ? msg->network->nwid : 0; |
||||
} |
||||
if (PEER_EVENT_TYPE(msg->eventCode)) { |
||||
id = msg->peer ? msg->peer->address : 0; |
||||
} |
||||
env->CallVoidMethod(objRef, _userCallbackMethodRef, id, msg->eventCode); |
||||
_freeEvent(msg); |
||||
} |
||||
#else |
||||
if (_userEventCallbackFunc) { |
||||
_userEventCallbackFunc(msg); |
||||
_freeEvent(msg); |
||||
} |
||||
#endif |
||||
} |
||||
|
||||
bool _isCallbackRegistered() |
||||
{ |
||||
_callbackLock.lock(); |
||||
bool retval = false; |
||||
#ifdef SDK_JNI |
||||
retval = (jvm && objRef && _userCallbackMethodRef); |
||||
#else |
||||
retval = _userEventCallbackFunc; |
||||
#endif |
||||
_callbackLock.unlock(); |
||||
return retval; |
||||
} |
||||
|
||||
void _clearRegisteredCallback() |
||||
{ |
||||
_callbackLock.lock(); |
||||
#ifdef SDK_JNI |
||||
objRef = NULL; |
||||
_userCallbackMethodRef = NULL; |
||||
#else |
||||
_userEventCallbackFunc = NULL; |
||||
#endif |
||||
_callbackLock.unlock(); |
||||
} |
||||
|
||||
int _canPerformServiceOperation() |
||||
{ |
||||
return service |
||||
&& service->isRunning() |
||||
&& service->getNode() |
||||
&& service->getNode()->online() |
||||
&& !_getState(ZTS_STATE_FREE_CALLED); |
||||
} |
||||
|
||||
#define RESET_FLAGS( ) _serviceStateFlags = 0; |
||||
#define SET_FLAGS(f) _serviceStateFlags |= f; |
||||
#define CLR_FLAGS(f) _serviceStateFlags &= ~f; |
||||
#define GET_FLAGS(f) ((_serviceStateFlags & f) > 0) |
||||
|
||||
void _setState(uint8_t newFlags) |
||||
{ |
||||
if ((newFlags ^ _serviceStateFlags) & ZTS_STATE_NET_SERVICE_RUNNING) { |
||||
return; // No effect. Not allowed to set this flag manually
|
||||
} |
||||
SET_FLAGS(newFlags); |
||||
if ( GET_FLAGS(ZTS_STATE_NODE_RUNNING) |
||||
&& GET_FLAGS(ZTS_STATE_STACK_RUNNING) |
||||
&& !(GET_FLAGS(ZTS_STATE_FREE_CALLED))) |
||||
{ |
||||
SET_FLAGS(ZTS_STATE_NET_SERVICE_RUNNING); |
||||
} |
||||
else { |
||||
CLR_FLAGS(ZTS_STATE_NET_SERVICE_RUNNING); |
||||
} |
||||
} |
||||
|
||||
void _clrState(uint8_t newFlags) |
||||
{ |
||||
if (newFlags & ZTS_STATE_NET_SERVICE_RUNNING) { |
||||
return; // No effect. Not allowed to set this flag manually
|
||||
} |
||||
CLR_FLAGS(newFlags); |
||||
if ( GET_FLAGS(ZTS_STATE_NODE_RUNNING) |
||||
&& GET_FLAGS(ZTS_STATE_STACK_RUNNING) |
||||
&& !(GET_FLAGS(ZTS_STATE_FREE_CALLED))) |
||||
{ |
||||
SET_FLAGS(ZTS_STATE_NET_SERVICE_RUNNING); |
||||
} |
||||
else { |
||||
CLR_FLAGS(ZTS_STATE_NET_SERVICE_RUNNING); |
||||
} |
||||
} |
||||
|
||||
bool _getState(uint8_t testFlags) |
||||
{ |
||||
return testFlags & _serviceStateFlags; |
||||
} |
||||
|
||||
#if defined(__WINDOWS__) |
||||
DWORD WINAPI _runCallbacks(LPVOID thread_id) |
||||
#else |
||||
void *_runCallbacks(void *thread_id) |
||||
#endif |
||||
{ |
||||
#if defined(__APPLE__) |
||||
pthread_setname_np(ZTS_EVENT_CALLBACK_THREAD_NAME); |
||||
#endif |
||||
while (_getState(ZTS_STATE_CALLBACKS_RUNNING) || _callbackMsgQueue.size_approx() > 0) |
||||
{ |
||||
struct ::zts_callback_msg *msg; |
||||
size_t sz = _callbackMsgQueue.size_approx(); |
||||
for (size_t j = 0; j < sz; j++) { |
||||
if (_callbackMsgQueue.try_dequeue(msg)) { |
||||
_callbackLock.lock(); |
||||
_passDequeuedEventToUser(msg); |
||||
_callbackLock.unlock(); |
||||
delete msg; |
||||
} |
||||
} |
||||
zts_delay_ms(ZTS_CALLBACK_PROCESSING_INTERVAL); |
||||
} |
||||
#if SDK_JNI |
||||
JNIEnv *env; |
||||
jint rs = jvm->DetachCurrentThread(); |
||||
pthread_exit(0); |
||||
#endif |
||||
return NULL; |
||||
} |
||||
|
||||
} // namespace ZeroTier
|
||||
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c)2013-2020 ZeroTier, Inc. |
||||
* |
||||
* Use of this software is governed by the Business Source License included |
||||
* in the LICENSE.TXT file in the project's root directory. |
||||
* |
||||
* Change Date: 2024-01-01 |
||||
* |
||||
* On the date above, in accordance with the Business Source License, use |
||||
* of this software will be governed by version 2.0 of the Apache License. |
||||
*/ |
||||
/****/ |
||||
|
||||
/**
|
||||
* @file |
||||
* |
||||
* Header for callback event processing logic |
||||
*/ |
||||
|
||||
#ifndef ZT_EVENTS_HPP |
||||
#define ZT_EVENTS_HPP |
||||
|
||||
#include <string> |
||||
|
||||
#include "ZeroTierSockets.h" |
||||
|
||||
#ifdef SDK_JNI |
||||
#include <jni.h> |
||||
#endif |
||||
namespace ZeroTier { |
||||
|
||||
#define ZTS_STATE_NODE_RUNNING 0x01 |
||||
#define ZTS_STATE_STACK_RUNNING 0x02 |
||||
#define ZTS_STATE_NET_SERVICE_RUNNING 0x04 |
||||
#define ZTS_STATE_CALLBACKS_RUNNING 0x08 |
||||
#define ZTS_STATE_FREE_CALLED 0x10 |
||||
|
||||
#ifdef SDK_JNI |
||||
// References to JNI objects and VM kept for future callbacks
|
||||
extern JavaVM *jvm; |
||||
extern jobject objRef; |
||||
extern jmethodID _userCallbackMethodRef; |
||||
#endif |
||||
|
||||
/**
|
||||
* How often callback messages are assembled and/or sent |
||||
*/ |
||||
#define ZTS_CALLBACK_PROCESSING_INTERVAL 25 |
||||
|
||||
/**
|
||||
* Enqueue an event to be sent to the user application |
||||
*/ |
||||
void _enqueueEvent(int16_t eventCode, void *arg); |
||||
|
||||
/**
|
||||
* Send callback message to user application |
||||
*/ |
||||
void _passDequeuedEventToUser(struct ::zts_callback_msg *msg); |
||||
|
||||
/**
|
||||
* Free memory occupied by callback structures |
||||
*/ |
||||
void _freeEvent(struct ::zts_callback_msg *msg); |
||||
|
||||
/**
|
||||
* Return whether a callback method has been set |
||||
*/ |
||||
bool _isCallbackRegistered(); |
||||
|
||||
/**
|
||||
* Clear pointer reference to user-provided callback function |
||||
*/ |
||||
void _clearRegisteredCallback(); |
||||
|
||||
/**
|
||||
* Return whether service operation can be performed at this time |
||||
*/ |
||||
int _canPerformServiceOperation(); |
||||
|
||||
/**
|
||||
* Set internal state flags |
||||
*/ |
||||
void _setState(uint8_t newFlags); |
||||
|
||||
/**
|
||||
* Clear internal state flags |
||||
*/ |
||||
void _clrState(uint8_t newFlags); |
||||
|
||||
/**
|
||||
* Get internal state flags |
||||
*/ |
||||
bool _getState(uint8_t testFlags); |
||||
|
||||
#ifdef __WINDOWS__ |
||||
DWORD WINAPI _runCallbacks(LPVOID thread_id); |
||||
#else |
||||
/**
|
||||
* Event callback thread |
||||
*/ |
||||
void *_runCallbacks(void *thread_id); |
||||
#endif |
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif // _H
|
||||
@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright (c)2013-2020 ZeroTier, Inc. |
||||
* |
||||
* Use of this software is governed by the Business Source License included |
||||
* in the LICENSE.TXT file in the project's root directory. |
||||
* |
||||
* Change Date: 2024-01-01 |
||||
* |
||||
* On the date above, in accordance with the Business Source License, use |
||||
* of this software will be governed by version 2.0 of the Apache License. |
||||
*/ |
||||
/****/ |
||||
|
||||
#ifndef LIBZT_OPTIONS_H |
||||
#define LIBZT_OPTIONS_H |
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Callbacks //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* The maximum number of un-processed callback messages |
||||
*/ |
||||
#define ZTS_CALLBACK_MSG_QUEUE_LEN 256 |
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Timing //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* How often callback messages are assembled and/or sent |
||||
*/ |
||||
#define ZTS_CALLBACK_PROCESSING_INTERVAL 25 |
||||
|
||||
/**
|
||||
* Polling interval (in ms) for fds wrapped in the Phy I/O loop |
||||
*/ |
||||
#define ZTS_TAP_THREAD_POLLING_INTERVAL 50 |
||||
|
||||
#define ZTS_HOUSEKEEPING_INTERVAL 50 |
||||
|
||||
/**
|
||||
* By how much thread I/O and callback loop delays are multiplied (unitless) |
||||
*/ |
||||
#define ZTS_HIBERNATION_MULTIPLIER 50 |
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Threading //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define SERVICE_THREAD_NICENESS 0 // -10
|
||||
#define CALLBACK_THREAD_NICENESS 0 // 10
|
||||
#define LWIP_DRIVER_THREAD_NICENESS 0 // 10
|
||||
#define TCPIP_THREAD_NICENESS 0 // -10
|
||||
#define TAP_THREAD_NICENESS 0 // 10
|
||||
|
||||
#define ZTS_SERVICE_THREAD_NAME "ZeroTierServiceThread" |
||||
#define ZTS_EVENT_CALLBACK_THREAD_NAME "ZeroTierEventCallbackThread" |
||||
#define ZTS_LWIP_DRIVER_THREAD_NAME "lwipDriver" |
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// lwIP behaviour (tcpip driver) //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* How many frames are handled per call from core |
||||
*/ |
||||
#define LWIP_FRAMES_HANDLED_PER_CORE_CALL 16 |
||||
|
||||
/**
|
||||
* How often the lwIP tcpip thread callback checks for incoming frames |
||||
*/ |
||||
#define LWIP_DRIVER_LOOP_INTERVAL 250 |
||||
|
||||
/**
|
||||
* Number of packets that can be queued for ingress into the lwIP core |
||||
*/ |
||||
#define ZTS_LWIP_MAX_RX_QUEUE_LEN 1024 |
||||
|
||||
#endif |
||||
@ -1,535 +0,0 @@
|
||||
/*
|
||||
* Copyright (c)2013-2020 ZeroTier, Inc. |
||||
* |
||||
* Use of this software is governed by the Business Source License included |
||||
* in the LICENSE.TXT file in the project's root directory. |
||||
* |
||||
* Change Date: 2024-01-01 |
||||
* |
||||
* On the date above, in accordance with the Business Source License, use |
||||
* of this software will be governed by version 2.0 of the Apache License. |
||||
*/ |
||||
/****/ |
||||
|
||||
/**
|
||||
* @file |
||||
* |
||||
* lwIP network stack driver |
||||
*/ |
||||
|
||||
#include <queue> |
||||
|
||||
#include "MAC.hpp" |
||||
#include "Mutex.hpp" |
||||
|
||||
#include "netif/ethernet.h" |
||||
#include "lwip/netif.h" |
||||
#include "lwip/etharp.h" |
||||
#include "lwip/tcpip.h" |
||||
#include "lwip/mem.h" |
||||
#include "lwip/memp.h" |
||||
#include "lwip/sys.h" |
||||
#include "lwip/tcp.h" |
||||
#include "lwip/timeouts.h" |
||||
#include "lwip/stats.h" |
||||
#include "lwip/ethip6.h" |
||||
#include "lwip/ip_addr.h" |
||||
#include "lwip/nd6.h" |
||||
#include "lwip/netifapi.h" |
||||
|
||||
#ifdef LWIP_STATS |
||||
#include "lwip/stats.h" |
||||
#endif |
||||
|
||||
#include "VirtualTap.hpp" |
||||
#include "lwipDriver.hpp" |
||||
#include "ZeroTier.h" |
||||
#include "Controls.hpp" |
||||
|
||||
extern void postEvent(uint64_t eventCode, void *arg); |
||||
extern void postEvent(uint64_t eventCode); |
||||
|
||||
#if defined(_WIN32) |
||||
#include <time.h> |
||||
#endif |
||||
|
||||
/**
|
||||
* Length of human-readable MAC address string |
||||
*/ |
||||
#define ZTS_MAC_ADDRSTRLEN 18 |
||||
|
||||
#ifndef htonll |
||||
#define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32)) |
||||
#endif |
||||
|
||||
namespace ZeroTier { |
||||
|
||||
bool _has_exited = false; |
||||
int hibernationDelayMultiplier = 1; |
||||
int netifCount = 0; |
||||
extern bool _run_lwip_tcpip; |
||||
Mutex lwip_driver_m; |
||||
|
||||
void lwip_sleep(long ms) |
||||
{ |
||||
#if defined(_WIN32) |
||||
Sleep(ms*hibernationDelayMultiplier); |
||||
#else |
||||
usleep(ms*1000*hibernationDelayMultiplier); |
||||
#endif |
||||
} |
||||
|
||||
void lwip_hibernate_driver() |
||||
{ |
||||
hibernationDelayMultiplier = ZTS_HIBERNATION_MULTIPLIER; |
||||
} |
||||
|
||||
void lwip_wake_driver() |
||||
{ |
||||
hibernationDelayMultiplier = 1; |
||||
} |
||||
|
||||
// Callback for when the TCPIP thread has been successfully started
|
||||
static void tcpip_init_done(void *arg) |
||||
{ |
||||
sys_sem_t *sem; |
||||
sem = (sys_sem_t *)arg; |
||||
_run_lwip_tcpip = true; |
||||
postEvent(ZTS_EVENT_STACK_UP); |
||||
sys_sem_signal(sem); |
||||
} |
||||
|
||||
static void main_lwip_driver_loop(void *arg) |
||||
{ |
||||
#if defined(__linux__) |
||||
pthread_setname_np(pthread_self(), ZTS_LWIP_DRIVER_THREAD_NAME); |
||||
#endif |
||||
#if defined(__APPLE__) |
||||
pthread_setname_np(ZTS_LWIP_DRIVER_THREAD_NAME); |
||||
#endif |
||||
sys_sem_t sem; |
||||
LWIP_UNUSED_ARG(arg); |
||||
if (sys_sem_new(&sem, 0) != ERR_OK) { |
||||
DEBUG_ERROR("failed to create semaphore"); |
||||
} |
||||
tcpip_init(tcpip_init_done, &sem); |
||||
sys_sem_wait(&sem); |
||||
// Main loop
|
||||
while(_run_lwip_tcpip) { |
||||
lwip_sleep(LWIP_DRIVER_LOOP_INTERVAL); |
||||
} |
||||
_has_exited = true; |
||||
postEvent(ZTS_EVENT_STACK_DOWN); |
||||
} |
||||
|
||||
bool lwip_is_up() |
||||
{ |
||||
Mutex::Lock _l(lwip_driver_m); |
||||
return _run_lwip_tcpip; |
||||
} |
||||
|
||||
bool lwip_has_previously_shutdown() |
||||
{ |
||||
Mutex::Lock _l(lwip_driver_m); |
||||
return _has_exited; |
||||
} |
||||
|
||||
void lwip_driver_init() |
||||
{ |
||||
if (lwip_is_up()) { |
||||
return; |
||||
} |
||||
if (lwip_has_previously_shutdown()) { |
||||
return; |
||||
} |
||||
Mutex::Lock _l(lwip_driver_m); |
||||
#if defined(_WIN32) |
||||
sys_init(); // Required for win32 init of critical sections
|
||||
#endif |
||||
sys_thread_new(ZTS_LWIP_DRIVER_THREAD_NAME, main_lwip_driver_loop, |
||||
NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO); |
||||
} |
||||
|
||||
void lwip_driver_shutdown() |
||||
{ |
||||
if (lwip_has_previously_shutdown()) { |
||||
return; |
||||
} |
||||
Mutex::Lock _l(lwip_driver_m); |
||||
// Set flag to stop sending frames into the core
|
||||
_run_lwip_tcpip = false; |
||||
// Wait until the main lwIP thread has exited
|
||||
while (!_has_exited) { lwip_sleep(LWIP_DRIVER_LOOP_INTERVAL); } |
||||
/*
|
||||
if (tcpip_shutdown() == ERR_OK) { |
||||
sys_timeouts_free(); |
||||
} |
||||
*/ |
||||
} |
||||
|
||||
void lwip_remove_netif(void *netif) |
||||
{ |
||||
if (!netif) { |
||||
return; |
||||
} |
||||
struct netif *n = (struct netif*)netif; |
||||
LOCK_TCPIP_CORE(); |
||||
netif_remove(n); |
||||
netif_set_down(n); |
||||
netif_set_link_down(n); |
||||
UNLOCK_TCPIP_CORE(); |
||||
} |
||||
|
||||
err_t lwip_eth_tx(struct netif *n, struct pbuf *p) |
||||
{ |
||||
if (!n) { |
||||
return ERR_IF; |
||||
} |
||||
struct pbuf *q; |
||||
char buf[ZT_MAX_MTU+32]; |
||||
char *bufptr; |
||||
int totalLength = 0; |
||||
|
||||
VirtualTap *tap = (VirtualTap*)n->state; |
||||
bufptr = buf; |
||||
for (q = p; q != NULL; q = q->next) { |
||||
memcpy(bufptr, q->payload, q->len); |
||||
bufptr += q->len; |
||||
totalLength += q->len; |
||||
} |
||||
struct eth_hdr *ethhdr; |
||||
ethhdr = (struct eth_hdr *)buf; |
||||
|
||||
MAC src_mac; |
||||
MAC dest_mac; |
||||
src_mac.setTo(ethhdr->src.addr, 6); |
||||
dest_mac.setTo(ethhdr->dest.addr, 6); |
||||
|
||||
char *data = buf + sizeof(struct eth_hdr); |
||||
int len = totalLength - sizeof(struct eth_hdr); |
||||
int proto = Utils::ntoh((uint16_t)ethhdr->type); |
||||
tap->_handler(tap->_arg, NULL, tap->_nwid, src_mac, dest_mac, proto, 0, data, len); |
||||
if (ZT_MSG_TRANSFER == true) { |
||||
char flagbuf[32]; |
||||
memset(&flagbuf, 0, 32); |
||||
char macBuf[ZTS_MAC_ADDRSTRLEN], nodeBuf[16]; |
||||
snprintf(macBuf, ZTS_MAC_ADDRSTRLEN, "%02x:%02x:%02x:%02x:%02x:%02x", |
||||
ethhdr->dest.addr[0], ethhdr->dest.addr[1], ethhdr->dest.addr[2],
|
||||
ethhdr->dest.addr[3], ethhdr->dest.addr[4], ethhdr->dest.addr[5]); |
||||
MAC mac; |
||||
mac.setTo(ethhdr->dest.addr, 6); |
||||
mac.toAddress(tap->_nwid).toString(nodeBuf); |
||||
/*
|
||||
DEBUG_TRANS("len=%5d dst=%s [%s TX <-- %s] ethertype=0x%04x %s", totalLength, macBuf, nodeBuf, tap->nodeId().c_str(), |
||||
Utils::ntoh(ethhdr->type), flagbuf); |
||||
*/ |
||||
} |
||||
return ERR_OK; |
||||
} |
||||
|
||||
void lwip_eth_rx(VirtualTap *tap, const MAC &from, const MAC &to, unsigned int etherType, |
||||
const void *data, unsigned int len) |
||||
{ |
||||
#ifdef LWIP_STATS |
||||
stats_display(); |
||||
#endif |
||||
if (!_run_lwip_tcpip) { |
||||
return; |
||||
} |
||||
struct pbuf *p,*q; |
||||
struct eth_hdr ethhdr; |
||||
from.copyTo(ethhdr.src.addr, 6); |
||||
to.copyTo(ethhdr.dest.addr, 6); |
||||
ethhdr.type = Utils::hton((uint16_t)etherType); |
||||
|
||||
if (ZT_MSG_TRANSFER == true) { |
||||
char flagbuf[32]; |
||||
memset(&flagbuf, 0, 32); |
||||
char macBuf[ZTS_MAC_ADDRSTRLEN], nodeBuf[16]; |
||||
snprintf(macBuf, ZTS_MAC_ADDRSTRLEN, "%02x:%02x:%02x:%02x:%02x:%02x", |
||||
ethhdr.dest.addr[0], ethhdr.dest.addr[1], ethhdr.dest.addr[2], |
||||
ethhdr.dest.addr[3], ethhdr.dest.addr[4], ethhdr.dest.addr[5]); |
||||
MAC mac; |
||||
mac.setTo(ethhdr.src.addr, 6); |
||||
mac.toAddress(tap->_nwid).toString(nodeBuf); |
||||
/*
|
||||
DEBUG_TRANS("len=%5d dst=%s [%s RX --> %s] ethertype=0x%04x %s", len, macBuf, nodeBuf, tap->nodeId().c_str(), |
||||
Utils::ntoh(ethhdr.type), flagbuf); |
||||
*/ |
||||
} |
||||
|
||||
p = pbuf_alloc(PBUF_RAW, (uint16_t)len+sizeof(struct eth_hdr), PBUF_RAM); |
||||
if (!p) { |
||||
DEBUG_ERROR("dropped packet: unable to allocate memory for pbuf"); |
||||
return; |
||||
} |
||||
// First pbuf gets ethernet header at start
|
||||
q = p; |
||||
if (q->len < sizeof(ethhdr)) { |
||||
pbuf_free(p); |
||||
p = NULL; |
||||
DEBUG_ERROR("dropped packet: first pbuf smaller than ethernet header"); |
||||
return; |
||||
} |
||||
// Copy frame data into pbuf
|
||||
const char *dataptr = reinterpret_cast<const char *>(data); |
||||
memcpy(q->payload,ðhdr,sizeof(ethhdr)); |
||||
int remainingPayloadSpace = q->len - sizeof(ethhdr); |
||||
memcpy((char*)q->payload + sizeof(ethhdr),dataptr,remainingPayloadSpace); |
||||
dataptr += remainingPayloadSpace; |
||||
// Remaining pbufs (if any) get rest of data
|
||||
while ((q = q->next)) { |
||||
memcpy(q->payload,dataptr,q->len); |
||||
dataptr += q->len; |
||||
} |
||||
// Feed packet into stack
|
||||
int err; |
||||
|
||||
if (Utils::ntoh(ethhdr.type) == 0x800 || Utils::ntoh(ethhdr.type) == 0x806) { |
||||
if ((err = ((struct netif *)tap->netif4)->input(p, (struct netif *)tap->netif4)) != ERR_OK) { |
||||
DEBUG_ERROR("packet input error (%d)", err); |
||||
pbuf_free(p); |
||||
} |
||||
} |
||||
if (Utils::ntoh(ethhdr.type) == 0x86DD) { |
||||
if ((err = ((struct netif *)tap->netif6)->input(p, (struct netif *)tap->netif6)) != ERR_OK) { |
||||
DEBUG_ERROR("packet input error (%d)", err); |
||||
pbuf_free(p); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/*
|
||||
static void print_netif_info(struct netif *n) { |
||||
DEBUG_INFO("n=%p, %c%c, %d, o=%p, o6=%p, mc=%x:%x:%x:%x:%x:%x, hwln=%d, st=%p, flgs=%d\n", |
||||
n, |
||||
n->name[0], |
||||
n->name[1], |
||||
n->mtu, |
||||
n->output, |
||||
n->output_ip6, |
||||
n->hwaddr[0], |
||||
n->hwaddr[1], |
||||
n->hwaddr[2], |
||||
n->hwaddr[3], |
||||
n->hwaddr[4], |
||||
n->hwaddr[5], |
||||
n->hwaddr_len, |
||||
n->state, |
||||
n->flags |
||||
); |
||||
} |
||||
*/ |
||||
|
||||
bool lwip_is_netif_up(void *n) |
||||
{ |
||||
if (!n) { |
||||
return false; |
||||
} |
||||
LOCK_TCPIP_CORE(); |
||||
bool result = netif_is_up((struct netif*)n); |
||||
UNLOCK_TCPIP_CORE(); |
||||
return result; |
||||
} |
||||
|
||||
/**
|
||||
* Called when a netif is removed (ZTS_EVENT_NETIF_INTERFACE_REMOVED) |
||||
*/ |
||||
#if LWIP_NETIF_REMOVE_CALLBACK |
||||
static void netif_remove_callback(struct netif *n) |
||||
{ |
||||
// Called from core, no need to lock
|
||||
if (!n || !n->state) { |
||||
return; |
||||
} |
||||
VirtualTap *tap = (VirtualTap *)n->state; |
||||
uint64_t mac = 0; |
||||
memcpy(&mac, n->hwaddr, n->hwaddr_len); |
||||
struct zts_netif_details *ifd = new zts_netif_details; |
||||
ifd->nwid = tap->_nwid; |
||||
memcpy(&(ifd->mac), n->hwaddr, n->hwaddr_len); |
||||
ifd->mac = lwip_htonl(ifd->mac) >> 16; |
||||
postEvent(ZTS_EVENT_NETIF_REMOVED, (void*)ifd); |
||||
} |
||||
#endif |
||||
|
||||
/**
|
||||
* Called when a link is brought up or down (ZTS_EVENT_NETIF_LINK_UP, ZTS_EVENT_NETIF_LINK_DOWN) |
||||
*/ |
||||
#if LWIP_NETIF_LINK_CALLBACK |
||||
static void netif_link_callback(struct netif *n) |
||||
{ |
||||
// Called from core, no need to lock
|
||||
if (!n || !n->state) { |
||||
return; |
||||
} |
||||
VirtualTap *tap = (VirtualTap *)n->state; |
||||
uint64_t mac = 0; |
||||
memcpy(&mac, n->hwaddr, n->hwaddr_len); |
||||
if (n->flags & NETIF_FLAG_LINK_UP) { |
||||
struct zts_netif_details *ifd = new zts_netif_details; |
||||
ifd->nwid = tap->_nwid; |
||||
memcpy(&(ifd->mac), n->hwaddr, n->hwaddr_len); |
||||
ifd->mac = lwip_htonl(ifd->mac) >> 16; |
||||
postEvent(ZTS_EVENT_NETIF_LINK_UP, (void*)ifd); |
||||
} |
||||
if (n->flags & NETIF_FLAG_LINK_UP) { |
||||
struct zts_netif_details *ifd = new zts_netif_details; |
||||
ifd->nwid = tap->_nwid; |
||||
memcpy(&(ifd->mac), n->hwaddr, n->hwaddr_len); |
||||
ifd->mac = lwip_htonl(ifd->mac) >> 16; |
||||
postEvent(ZTS_EVENT_NETIF_LINK_DOWN, (void*)ifd); |
||||
} |
||||
} |
||||
#endif |
||||
|
||||
void lwip_set_callbacks(struct netif *n) |
||||
{ |
||||
if (!n) { |
||||
return; |
||||
} |
||||
#if LWIP_NETIF_STATUS_CALLBACK |
||||
// Not currently used
|
||||
netif_set_status_callback(n, netif_status_callback); |
||||
#endif |
||||
#if LWIP_NETIF_REMOVE_CALLBACK |
||||
netif_set_remove_callback(n, netif_remove_callback); |
||||
#endif |
||||
#if LWIP_NETIF_LINK_CALLBACK |
||||
netif_set_link_callback(n, netif_link_callback); |
||||
#endif |
||||
} |
||||
|
||||
static struct zts_netif_details *lwip_prepare_netif_status_msg(struct netif *n) |
||||
{ |
||||
if (!n || !n->state) { |
||||
return NULL; |
||||
} |
||||
VirtualTap *tap = (VirtualTap*)(n->state); |
||||
struct zts_netif_details *ifd = new zts_netif_details; |
||||
ifd->nwid = tap->_nwid; |
||||
ifd->mtu = n->mtu; |
||||
memcpy(&(ifd->mac), n->hwaddr, n->hwaddr_len); |
||||
ifd->mac = htonll(ifd->mac) >> 16; |
||||
return ifd; |
||||
} |
||||
|
||||
static err_t netif_init(struct netif *n) |
||||
{ |
||||
if (!n || !n->state) { |
||||
return ERR_IF; |
||||
} |
||||
// Called from netif code, no need to lock
|
||||
n->hwaddr_len = 6; |
||||
n->name[0] = '4'; |
||||
n->name[1] = 'a'+netifCount; |
||||
n->linkoutput = lwip_eth_tx; |
||||
n->output = etharp_output; |
||||
n->mtu = LWIP_MTU < ZT_MAX_MTU ? LWIP_MTU : ZT_MAX_MTU; |
||||
n->flags = NETIF_FLAG_BROADCAST |
||||
| NETIF_FLAG_ETHARP |
||||
| NETIF_FLAG_ETHERNET |
||||
| NETIF_FLAG_IGMP |
||||
| NETIF_FLAG_MLD6 |
||||
| NETIF_FLAG_LINK_UP |
||||
| NETIF_FLAG_UP; |
||||
n->hwaddr_len = sizeof(n->hwaddr); |
||||
VirtualTap *tap = (VirtualTap*)(n->state); |
||||
tap->_mac.copyTo(n->hwaddr, n->hwaddr_len); |
||||
return ERR_OK; |
||||
} |
||||
|
||||
static err_t netif_init6(struct netif *n) |
||||
{ |
||||
if (!n || !n->state) { |
||||
return ERR_IF; |
||||
} |
||||
n->hwaddr_len = sizeof(n->hwaddr); |
||||
VirtualTap *tap = (VirtualTap*)(n->state); |
||||
tap->_mac.copyTo(n->hwaddr, n->hwaddr_len); |
||||
// Called from netif code, no need to lock
|
||||
n->hwaddr_len = 6; |
||||
n->name[0] = '6'; |
||||
n->name[1] = 'a'+netifCount; |
||||
n->linkoutput = lwip_eth_tx; |
||||
n->output_ip6 = ethip6_output; |
||||
n->mtu = LWIP_MTU < ZT_MAX_MTU ? LWIP_MTU : ZT_MAX_MTU; |
||||
n->flags = NETIF_FLAG_BROADCAST |
||||
| NETIF_FLAG_ETHARP |
||||
| NETIF_FLAG_ETHERNET |
||||
| NETIF_FLAG_IGMP |
||||
| NETIF_FLAG_MLD6 |
||||
| NETIF_FLAG_LINK_UP |
||||
| NETIF_FLAG_UP; |
||||
return ERR_OK; |
||||
} |
||||
|
||||
void lwip_init_interface(void *tapref, const InetAddress &ip) |
||||
{ |
||||
char ipbuf[INET6_ADDRSTRLEN]; |
||||
char macbuf[ZTS_MAC_ADDRSTRLEN]; |
||||
|
||||
VirtualTap *vtap = (VirtualTap*)tapref; |
||||
struct netif *n = NULL; |
||||
bool isNewNetif = false; |
||||
|
||||
if (ip.isV4()) { |
||||
if (vtap->netif4) { |
||||
n = (struct netif*)vtap->netif4; |
||||
} |
||||
else { |
||||
n = new struct netif; |
||||
isNewNetif = true; |
||||
netifCount++; |
||||
} |
||||
char nmbuf[INET6_ADDRSTRLEN]; |
||||
static ip4_addr_t ip4, netmask, gw; |
||||
IP4_ADDR(&gw,127,0,0,1); |
||||
ip4.addr = *((u32_t *)ip.rawIpData()); |
||||
netmask.addr = *((u32_t *)ip.netmask().rawIpData()); |
||||
LOCK_TCPIP_CORE(); |
||||
netif_add(n, &ip4, &netmask, &gw, (void*)vtap, netif_init, tcpip_input); |
||||
vtap->netif4 = (void*)n; |
||||
postEvent(ZTS_EVENT_NETIF_UP, (void*)lwip_prepare_netif_status_msg(n)); |
||||
UNLOCK_TCPIP_CORE(); |
||||
snprintf(macbuf, ZTS_MAC_ADDRSTRLEN, "%02x:%02x:%02x:%02x:%02x:%02x", |
||||
n->hwaddr[0], n->hwaddr[1], n->hwaddr[2], |
||||
n->hwaddr[3], n->hwaddr[4], n->hwaddr[5]); |
||||
DEBUG_INFO("initialized netif=%p as [mac=%s, addr=%s, nm=%s, tap=%p]",n, |
||||
macbuf, ip.toString(ipbuf), ip.netmask().toString(nmbuf), vtap); |
||||
} |
||||
if (ip.isV6()) { |
||||
if (vtap->netif6) { |
||||
n = (struct netif*)vtap->netif6; |
||||
} |
||||
else { |
||||
n = new struct netif; |
||||
isNewNetif = true; |
||||
netifCount++; |
||||
} |
||||
static ip6_addr_t ip6; |
||||
memcpy(&(ip6.addr), ip.rawIpData(), sizeof(ip6.addr)); |
||||
LOCK_TCPIP_CORE(); |
||||
if (isNewNetif) { |
||||
vtap->netif6 = (void*)n; |
||||
netif_add(n, NULL, NULL, NULL, (void*)vtap, netif_init6, ethernet_input); |
||||
n->ip6_autoconfig_enabled = 1; |
||||
vtap->_mac.copyTo(n->hwaddr, n->hwaddr_len); |
||||
netif_create_ip6_linklocal_address(n, 1); |
||||
netif_set_link_up(n); |
||||
netif_set_up(n); |
||||
netif_set_default(n); |
||||
} |
||||
netif_add_ip6_address(n,&ip6,NULL); |
||||
n->output_ip6 = ethip6_output; |
||||
UNLOCK_TCPIP_CORE(); |
||||
postEvent(ZTS_EVENT_NETIF_UP, (void*)lwip_prepare_netif_status_msg(n)); |
||||
snprintf(macbuf, ZTS_MAC_ADDRSTRLEN, "%02x:%02x:%02x:%02x:%02x:%02x", |
||||
n->hwaddr[0], n->hwaddr[1], n->hwaddr[2], |
||||
n->hwaddr[3], n->hwaddr[4], n->hwaddr[5]); |
||||
DEBUG_INFO("initialized netif=%p as [mac=%s, addr=%s, tap=%p]", n, |
||||
macbuf, ip.toString(ipbuf), vtap); |
||||
} |
||||
} |
||||
|
||||
} // namespace ZeroTier
|
||||
@ -1,173 +0,0 @@
|
||||
/*
|
||||
* Copyright (c)2013-2020 ZeroTier, Inc. |
||||
* |
||||
* Use of this software is governed by the Business Source License included |
||||
* in the LICENSE.TXT file in the project's root directory. |
||||
* |
||||
* Change Date: 2024-01-01 |
||||
* |
||||
* On the date above, in accordance with the Business Source License, use |
||||
* of this software will be governed by version 2.0 of the Apache License. |
||||
*/ |
||||
/****/ |
||||
|
||||
/**
|
||||
* @file |
||||
* |
||||
* lwIP network stack driver |
||||
*/ |
||||
|
||||
#ifndef LIBZT_LWIP_DRIVER_HPP |
||||
#define LIBZT_LWIP_DRIVER_HPP |
||||
|
||||
#include "Debug.hpp" |
||||
#include "lwip/err.h" |
||||
|
||||
namespace ZeroTier { |
||||
|
||||
class MAC; |
||||
class Mutex; |
||||
class VirtualTap; |
||||
struct InetAddress; |
||||
|
||||
/**
|
||||
* @brief Structure used to associate packets with interfaces. |
||||
*/ |
||||
struct zts_sorted_packet |
||||
{ |
||||
// lwIP pbuf containing packet (originally encapsulated by ZT packet)
|
||||
struct pbuf *p; |
||||
// ZT VirtualTap from which this packet originates
|
||||
VirtualTap *vtap; |
||||
// lwIP netif we should accept this packet on
|
||||
struct netif *n; |
||||
}; |
||||
|
||||
/**
|
||||
* @brief Return whether a given netif's NETIF_FLAG_UP flag is set |
||||
* |
||||
* @usage This is a convenience function to encapsulate a macro |
||||
*/ |
||||
bool lwip_is_netif_up(void *netif); |
||||
|
||||
/**
|
||||
* @brief Increase the delay multiplier for the main driver loop |
||||
* |
||||
* @usage This should be called when we know the stack won't be used by any virtual taps |
||||
*/ |
||||
void lwip_hibernate_driver(); |
||||
|
||||
/**
|
||||
* @brief Decrease the delay multiplier for the main driver loop |
||||
* |
||||
* @usage This should be called when at least one virtual tap is active |
||||
*/ |
||||
void lwip_wake_driver(); |
||||
|
||||
/**
|
||||
* Returns whether the lwIP network stack is up and ready to process traffic |
||||
*/ |
||||
bool lwip_is_up(); |
||||
|
||||
/**
|
||||
* @brief Initialize network stack semaphores, threads, and timers. |
||||
* |
||||
* @usage This is called during the initial setup of each VirtualTap but is only allowed to execute once |
||||
* @return |
||||
*/ |
||||
void lwip_driver_init(); |
||||
|
||||
/**
|
||||
* @brief Shutdown the stack as completely as possible (not officially supported by lwIP) |
||||
* |
||||
* @usage This is to be called after it is determined that no further network activity will take place. |
||||
* The tcpip thread will be stopped, all interfaces will be brought down and all resources will
|
||||
* be deallocated. A full application restart will be required to bring the stack back online. |
||||
* @return |
||||
*/ |
||||
void lwip_driver_shutdown(); |
||||
|
||||
/**
|
||||
* @brief Requests that a netif be brought down and removed. |
||||
* |
||||
* @return |
||||
*/ |
||||
void lwip_remove_netif(void *netif); |
||||
|
||||
/**
|
||||
* @brief Initialize and start the DNS client |
||||
* |
||||
* @usage Called after lwip_driver_init() |
||||
* @return |
||||
*/ |
||||
void lwip_dns_init(); |
||||
|
||||
/**
|
||||
* @brief Starts DHCP timers |
||||
* |
||||
* @usage lwip_driver_init() |
||||
* @return |
||||
*/ |
||||
void lwip_start_dhcp(void *netif); |
||||
|
||||
/**
|
||||
* @brief Called when the status of a netif changes: |
||||
* - Interface is up/down (ZTS_EVENT_NETIF_UP, ZTS_EVENT_NETIF_DOWN) |
||||
* - Address changes while up (ZTS_EVENT_NETIF_NEW_ADDRESS) |
||||
*/ |
||||
#if LWIP_NETIF_STATUS_CALLBACK |
||||
static void netif_status_callback(struct netif *netif); |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Called when a netif is removed (ZTS_EVENT_NETIF_INTERFACE_REMOVED) |
||||
*/ |
||||
#if LWIP_NETIF_REMOVE_CALLBACK |
||||
static void netif_remove_callback(struct netif *netif); |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Called when a link is brought up or down (ZTS_EVENT_NETIF_LINK_UP, ZTS_EVENT_NETIF_LINK_DOWN) |
||||
*/ |
||||
#if LWIP_NETIF_LINK_CALLBACK |
||||
static void netif_link_callback(struct netif *netif); |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Set up an interface in the network stack for the VirtualTap. |
||||
* |
||||
* @param |
||||
* @param tapref Reference to VirtualTap that will be responsible for sending and receiving data |
||||
* @param ip Virtual IP address for this ZeroTier VirtualTap interface |
||||
* @return |
||||
*/ |
||||
void lwip_init_interface(void *tapref, const InetAddress &ip); |
||||
|
||||
/**
|
||||
* @brief Called from the stack, outbound ethernet frames from the network stack enter the ZeroTier virtual wire here. |
||||
* |
||||
* @usage This shall only be called from the stack or the stack driver. Not the application thread. |
||||
* @param netif Transmits an outgoing Ethernet fram from the network stack onto the ZeroTier virtual wire |
||||
* @param p A pointer to the beginning of a chain pf struct pbufs |
||||
* @return |
||||
*/ |
||||
err_t lwip_eth_tx(struct netif *netif, struct pbuf *p); |
||||
|
||||
/**
|
||||
* @brief Receives incoming Ethernet frames from the ZeroTier virtual wire |
||||
* |
||||
* @usage This shall be called from the VirtualTap's I/O thread (via VirtualTap::put()) |
||||
* @param tap Pointer to VirtualTap from which this data comes |
||||
* @param from Origin address (virtual ZeroTier hardware address) |
||||
* @param to Intended destination address (virtual ZeroTier hardware address) |
||||
* @param etherType Protocol type |
||||
* @param data Pointer to Ethernet frame |
||||
* @param len Length of Ethernet frame |
||||
* @return |
||||
*/ |
||||
void lwip_eth_rx(VirtualTap *tap, const MAC &from, const MAC &to, unsigned int etherType, |
||||
const void *data, unsigned int len); |
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif // _H
|
||||
Loading…
Reference in new issue