mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-12-19 04:57:53 +00:00
Moar Go
This commit is contained in:
parent
b34aa10bf8
commit
02a6b15e6b
@ -575,24 +575,24 @@ extern "C" void ZT_GoTap_setEnabled(ZT_GoTap *tap,int enabled)
|
||||
reinterpret_cast<EthernetTap *>(tap)->setEnabled(enabled != 0);
|
||||
}
|
||||
|
||||
extern "C" int ZT_GoTap_addIp(ZT_GoTap *tap,int af,const void *ip,int port)
|
||||
extern "C" int ZT_GoTap_addIp(ZT_GoTap *tap,int af,const void *ip,int netmaskBits)
|
||||
{
|
||||
switch(af) {
|
||||
case AF_INET:
|
||||
return (reinterpret_cast<EthernetTap *>(tap)->addIp(InetAddress(ip,4,(unsigned int)port)) ? 1 : 0);
|
||||
return (reinterpret_cast<EthernetTap *>(tap)->addIp(InetAddress(ip,4,(unsigned int)netmaskBits)) ? 1 : 0);
|
||||
case AF_INET6:
|
||||
return (reinterpret_cast<EthernetTap *>(tap)->addIp(InetAddress(ip,16,(unsigned int)port)) ? 1 : 0);
|
||||
return (reinterpret_cast<EthernetTap *>(tap)->addIp(InetAddress(ip,16,(unsigned int)netmaskBits)) ? 1 : 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int ZT_GoTap_removeIp(ZT_GoTap *tap,int af,const void *ip,int port)
|
||||
extern "C" int ZT_GoTap_removeIp(ZT_GoTap *tap,int af,const void *ip,int netmaskBits)
|
||||
{
|
||||
switch(af) {
|
||||
case AF_INET:
|
||||
return (reinterpret_cast<EthernetTap *>(tap)->removeIp(InetAddress(ip,4,(unsigned int)port)) ? 1 : 0);
|
||||
return (reinterpret_cast<EthernetTap *>(tap)->removeIp(InetAddress(ip,4,(unsigned int)netmaskBits)) ? 1 : 0);
|
||||
case AF_INET6:
|
||||
return (reinterpret_cast<EthernetTap *>(tap)->removeIp(InetAddress(ip,16,(unsigned int)port)) ? 1 : 0);
|
||||
return (reinterpret_cast<EthernetTap *>(tap)->removeIp(InetAddress(ip,16,(unsigned int)netmaskBits)) ? 1 : 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -603,25 +603,22 @@ extern "C" int ZT_GoTap_ips(ZT_GoTap *tap,void *buf,unsigned int bufSize)
|
||||
unsigned int p = 0;
|
||||
uint8_t *const b = reinterpret_cast<uint8_t *>(buf);
|
||||
for(auto ip=ips.begin();ip!=ips.end();++ip) {
|
||||
if ((p + 7) > bufSize)
|
||||
if ((p + 6) > bufSize)
|
||||
break;
|
||||
const uint8_t *const ipd = reinterpret_cast<const uint8_t *>(ip->rawIpData());
|
||||
const unsigned int port = ip->port();
|
||||
if (ip->isV4()) {
|
||||
b[p++] = AF_INET;
|
||||
b[p++] = ipd[0];
|
||||
b[p++] = ipd[1];
|
||||
b[p++] = ipd[2];
|
||||
b[p++] = ipd[3];
|
||||
b[p++] = (uint8_t)((port >> 8) & 0xff);
|
||||
b[p++] = (uint8_t)(port & 0xff);
|
||||
b[p++] = (uint8_t)ip->netmaskBits();
|
||||
} else if (ip->isV6()) {
|
||||
if ((p + 19) <= bufSize) {
|
||||
if ((p + 18) <= bufSize) {
|
||||
b[p++] = AF_INET6;
|
||||
for(int j=0;j<16;++j)
|
||||
b[p++] = ipd[j];
|
||||
b[p++] = (uint8_t)((port >> 8) & 0xff);
|
||||
b[p++] = (uint8_t)(port & 0xff);
|
||||
b[p++] = (uint8_t)ip->netmaskBits();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -62,14 +62,14 @@ void ZT_GoNode_leave(ZT_GoNode *gn,uint64_t nwid);
|
||||
|
||||
void ZT_GoTap_setEnabled(ZT_GoTap *tap,int enabled);
|
||||
|
||||
int ZT_GoTap_addIp(ZT_GoTap *tap,int af,const void *ip,int port);
|
||||
int ZT_GoTap_addIp(ZT_GoTap *tap,int af,const void *ip,int netmaskBits);
|
||||
|
||||
int ZT_GoTap_removeIp(ZT_GoTap *tap,int af,const void *ip,int port);
|
||||
int ZT_GoTap_removeIp(ZT_GoTap *tap,int af,const void *ip,int netmaskBits);
|
||||
|
||||
/* The buf buffer is filled with tuplies of:
|
||||
* uint8_t family
|
||||
* uint8_t ip[4 or 16]
|
||||
* uint16_t port (big-endian byte order)
|
||||
* uint8_t netmask bits (up to 32 for ipv4, 128 for ipv6)
|
||||
*
|
||||
* This function returns the number of such tuples in the result.
|
||||
* If the buffer isn't big enough results are incomplete.
|
||||
|
54
go/pkg/zerotier/address.go
Normal file
54
go/pkg/zerotier/address.go
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c)2019 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: 2023-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.
|
||||
*/
|
||||
/****/
|
||||
|
||||
package zerotier
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Address represents a 40-bit short ZeroTier address
|
||||
type Address uint64
|
||||
|
||||
// NewAddressFromString parses a 10-digit ZeroTier address
|
||||
func NewAddressFromString(s string) (Address, error) {
|
||||
if len(s) != 10 {
|
||||
return Address(0), ErrInvalidZeroTierAddress
|
||||
}
|
||||
a, err := strconv.ParseUint(s, 16, 64)
|
||||
return Address(a & 0xffffffffff), err
|
||||
}
|
||||
|
||||
// String returns this address's 10-digit hex identifier
|
||||
func (a Address) String() string {
|
||||
return fmt.Sprintf("%.10x", uint64(a))
|
||||
}
|
||||
|
||||
// MarshalJSON marshals this Address as a string
|
||||
func (a Address) MarshalJSON() ([]byte, error) {
|
||||
return []byte(a.String()), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals this Address from a string
|
||||
func (a *Address) UnmarshalJSON(j []byte) error {
|
||||
var s string
|
||||
err := json.Unmarshal(j, &s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tmp, err := NewAddressFromString(s)
|
||||
*a = tmp
|
||||
return err
|
||||
}
|
@ -20,6 +20,7 @@ func (e Err) Error() string { return (string)(e) }
|
||||
|
||||
// Simple ZeroTier Errors
|
||||
const (
|
||||
ErrInvalidMACAddress Err = "invalid MAC address"
|
||||
ErrInvalidParameter Err = "invalid parameter"
|
||||
ErrInvalidMACAddress Err = "invalid MAC address"
|
||||
ErrInvalidZeroTierAddress Err = "invalid ZeroTier address"
|
||||
ErrInvalidParameter Err = "invalid parameter"
|
||||
)
|
||||
|
@ -43,7 +43,7 @@ func NewMACFromString(s string) (MAC, error) {
|
||||
|
||||
// String returns this MAC address in canonical human-readable form
|
||||
func (m MAC) String() string {
|
||||
return fmt.Sprintf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", (m>>40)&0xff, (m>>32)&0xff, (m>>24)&0xff, (m>>16)&0xff, (m>>8)&0xff, m&0xff)
|
||||
return fmt.Sprintf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", (uint64(m)>>40)&0xff, (uint64(m)>>32)&0xff, (uint64(m)>>24)&0xff, (uint64(m)>>16)&0xff, (uint64(m)>>8)&0xff, uint64(m)&0xff)
|
||||
}
|
||||
|
||||
// MarshalJSON marshals this MAC as a string
|
||||
|
137
go/pkg/zerotier/nativetap.go
Normal file
137
go/pkg/zerotier/nativetap.go
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c)2019 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: 2023-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.
|
||||
*/
|
||||
/****/
|
||||
|
||||
package zerotier
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//#cgo CFLAGS: -O3
|
||||
//#define ZT_CGO 1
|
||||
//#include <stdint.h>
|
||||
//#include <stdlib.h>
|
||||
//#include <string.h>
|
||||
//#include "../../native/GoGlue.h"
|
||||
import "C"
|
||||
|
||||
// nativeTap is a Tap implementation that wraps a native C++ interface to a system tun/tap device
|
||||
type nativeTap struct {
|
||||
tap unsafe.Pointer
|
||||
networkStatus uint32
|
||||
enabled uint32
|
||||
}
|
||||
|
||||
// SetEnabled sets this tap's enabled state
|
||||
func (t *nativeTap) SetEnabled(enabled bool) {
|
||||
if enabled && atomic.SwapUint32(&t.enabled, 1) == 0 {
|
||||
C.ZT_GoTap_setEnabled(t.tap, 1)
|
||||
} else if !enabled && atomic.SwapUint32(&t.enabled, 0) == 1 {
|
||||
C.ZT_GoTap_setEnabled(t.tap, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// Enabled returns true if this tap is currently processing packets
|
||||
func (t *nativeTap) Enabled() bool {
|
||||
return atomic.LoadUint32(&t.enabled) != 0
|
||||
}
|
||||
|
||||
// AddIP adds an IP address (with netmask) to this tap
|
||||
func (t *nativeTap) AddIP(ip net.IPNet) error {
|
||||
bits, _ := ip.Mask.Size()
|
||||
if len(ip.IP) == 16 {
|
||||
if bits > 128 || bits < 0 {
|
||||
return ErrInvalidParameter
|
||||
}
|
||||
C.ZT_GoTap_addIp(t.tap, afInet6, unsafe.Pointer(&ip.IP[0]), C.int(bits))
|
||||
} else if len(ip.IP) == 4 {
|
||||
if bits > 32 || bits < 0 {
|
||||
return ErrInvalidParameter
|
||||
}
|
||||
C.ZT_GoTap_addIp(t.tap, afInet, unsafe.Pointer(&ip.IP[0]), C.int(bits))
|
||||
}
|
||||
return ErrInvalidParameter
|
||||
}
|
||||
|
||||
// RemoveIP removes this IP address (with netmask) from this tap
|
||||
func (t *nativeTap) RemoveIP(ip net.IPNet) error {
|
||||
bits, _ := ip.Mask.Size()
|
||||
if len(ip.IP) == 16 {
|
||||
if bits > 128 || bits < 0 {
|
||||
return ErrInvalidParameter
|
||||
}
|
||||
C.ZT_GoTap_removeIp(t.tap, afInet6, unsafe.Pointer(&ip.IP[0]), C.int(bits))
|
||||
return nil
|
||||
}
|
||||
if len(ip.IP) == 4 {
|
||||
if bits > 32 || bits < 0 {
|
||||
return ErrInvalidParameter
|
||||
}
|
||||
C.ZT_GoTap_removeIp(t.tap, afInet, unsafe.Pointer(&ip.IP[0]), C.int(bits))
|
||||
return nil
|
||||
}
|
||||
return ErrInvalidParameter
|
||||
}
|
||||
|
||||
// IPs returns IPs currently assigned to this tap (including externally or system-assigned IPs)
|
||||
func (t *nativeTap) IPs() (ips []net.IPNet, err error) {
|
||||
defer func() {
|
||||
e := recover()
|
||||
if e != nil {
|
||||
err = fmt.Errorf("%v", e)
|
||||
}
|
||||
}()
|
||||
var ipbuf [16384]byte
|
||||
count := int(C.ZT_GoTap_ips(t.tap, unsafe.Pointer(&ipbuf[0]), 16384))
|
||||
ipptr := 0
|
||||
for i := 0; i < count; i++ {
|
||||
af := ipbuf[ipptr]
|
||||
ipptr++
|
||||
switch af {
|
||||
case afInet:
|
||||
var ip [4]byte
|
||||
for j := 0; j < 4; j++ {
|
||||
ip[j] = ipbuf[ipptr]
|
||||
ipptr++
|
||||
}
|
||||
bits := ipbuf[ipptr]
|
||||
ipptr++
|
||||
ips = append(ips, net.IPNet{IP: net.IP(ip[:]), Mask: net.CIDRMask(int(bits), 32)})
|
||||
case afInet6:
|
||||
var ip [16]byte
|
||||
for j := 0; j < 16; j++ {
|
||||
ip[j] = ipbuf[ipptr]
|
||||
ipptr++
|
||||
}
|
||||
bits := ipbuf[ipptr]
|
||||
ipptr++
|
||||
ips = append(ips, net.IPNet{IP: net.IP(ip[:]), Mask: net.CIDRMask(int(bits), 128)})
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeviceName gets this tap's OS-specific device name
|
||||
func (t *nativeTap) DeviceName() string {
|
||||
var dn [256]byte
|
||||
C.ZT_GoTap_deviceName(t.tap, (*C.char)(unsafe.Pointer(&dn[0])))
|
||||
for i, b := range dn {
|
||||
if b == 0 {
|
||||
return string(dn[0:i])
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
@ -14,15 +14,52 @@
|
||||
package zerotier
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync/atomic"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// NetworkID is a network's 64-bit unique ID
|
||||
type NetworkID uint64
|
||||
|
||||
// NewNetworkIDFromString parses a network ID in string form
|
||||
func NewNetworkIDFromString(s string) (NetworkID, error) {
|
||||
if len(s) != 16 {
|
||||
return NetworkID(0), ErrInvalidZeroTierAddress
|
||||
}
|
||||
n, err := strconv.ParseUint(s, 16, 64)
|
||||
return NetworkID(n), err
|
||||
}
|
||||
|
||||
// String returns this network ID's 16-digit hex identifier
|
||||
func (n NetworkID) String() string {
|
||||
return fmt.Sprintf("%.16x", uint64(n))
|
||||
}
|
||||
|
||||
// MarshalJSON marshals this NetworkID as a string
|
||||
func (n NetworkID) MarshalJSON() ([]byte, error) {
|
||||
return []byte(n.String()), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals this NetworkID from a string
|
||||
func (n *NetworkID) UnmarshalJSON(j []byte) error {
|
||||
var s string
|
||||
err := json.Unmarshal(j, &s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tmp, err := NewNetworkIDFromString(s)
|
||||
*n = tmp
|
||||
return err
|
||||
}
|
||||
|
||||
// NetworkConfig represents the network's current state
|
||||
type NetworkConfig struct {
|
||||
// ID is this network's 64-bit globally unique identifier
|
||||
ID uint64
|
||||
ID NetworkID
|
||||
|
||||
// MAC is the Ethernet MAC address of this device on this network
|
||||
MAC MAC
|
||||
@ -57,8 +94,8 @@ type NetworkConfig struct {
|
||||
// MulticastSubscriptions are this device's current multicast subscriptions
|
||||
MulticastSubscriptions []MulticastGroup
|
||||
|
||||
// PortType is a human-readable description of this port's implementation type or name
|
||||
PortType string
|
||||
// PortDeviceType is a human-readable description of this port's implementation type or name
|
||||
PortDeviceType string
|
||||
|
||||
// PortDeviceName is the OS-specific device name (e.g. tun0 or feth1856) for this network's virtual port
|
||||
PortDeviceName string
|
||||
@ -69,6 +106,15 @@ type NetworkConfig struct {
|
||||
|
||||
// Network is a currently joined network
|
||||
type Network struct {
|
||||
config atomic.Value
|
||||
tap atomic.Value
|
||||
config NetworkConfig
|
||||
configLock sync.RWMutex
|
||||
tap *Tap
|
||||
tapLock sync.Mutex
|
||||
}
|
||||
|
||||
// Config returns a copy of this network's current configuration
|
||||
func (n *Network) Config() NetworkConfig {
|
||||
n.configLock.RLock()
|
||||
defer n.configLock.RUnlock()
|
||||
return n.config
|
||||
}
|
||||
|
@ -13,6 +13,14 @@
|
||||
|
||||
package zerotier
|
||||
|
||||
import (
|
||||
"net"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//#cgo CFLAGS: -O3
|
||||
//#cgo LDFLAGS: ${SRCDIR}/../../../build/node/libzt_core.a ${SRCDIR}/../../../build/go/native/libzt_go_native.a -lc++
|
||||
//#define ZT_CGO 1
|
||||
@ -27,13 +35,6 @@ package zerotier
|
||||
//#define ZEROTIER_ONE_VERSION_BUILD 255
|
||||
//#endif
|
||||
import "C"
|
||||
import (
|
||||
"net"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// CoreVersionMajor is the major version of the ZeroTier core
|
||||
@ -49,19 +50,13 @@ const (
|
||||
CoreVersionBuild int = C.ZEROTIER_ONE_VERSION_BUILD
|
||||
)
|
||||
|
||||
// Tap is an instance of an EthernetTap object
|
||||
type Tap struct {
|
||||
tap *C.ZT_GoTap
|
||||
networkStatus uint32
|
||||
}
|
||||
|
||||
// Node is an instance of a ZeroTier node
|
||||
type Node struct {
|
||||
gn *C.ZT_GoNode
|
||||
zn *C.ZT_Node
|
||||
|
||||
taps map[uint64]*Tap
|
||||
tapsLock sync.RWMutex
|
||||
networks map[uint64]*Network
|
||||
networksLock sync.RWMutex
|
||||
|
||||
online uint32
|
||||
running uint32
|
||||
@ -70,6 +65,7 @@ type Node struct {
|
||||
// NewNode creates and initializes a new instance of the ZeroTier node service
|
||||
func NewNode() *Node {
|
||||
n := new(Node)
|
||||
n.networks = make(map[uint64]*Network)
|
||||
|
||||
gnRawAddr := uintptr(unsafe.Pointer(n.gn))
|
||||
nodesByUserPtrLock.Lock()
|
||||
|
26
go/pkg/zerotier/tap.go
Normal file
26
go/pkg/zerotier/tap.go
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c)2019 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: 2023-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.
|
||||
*/
|
||||
/****/
|
||||
|
||||
package zerotier
|
||||
|
||||
import "net"
|
||||
|
||||
// Tap represents an Ethernet tap connecting a virtual network to a device or something else "real"
|
||||
type Tap interface {
|
||||
SetEnabled(enabled bool)
|
||||
Enabled() bool
|
||||
AddIP(ip net.IPNet) error
|
||||
RemoveIP(ip net.IPNet) error
|
||||
IPs() ([]net.IPNet, error)
|
||||
DeviceName() string
|
||||
}
|
Loading…
Reference in New Issue
Block a user