mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-01-20 03:36:40 +00:00
Going once... going twice!
This commit is contained in:
parent
9934a856dd
commit
bb53ee9567
@ -20,6 +20,15 @@
|
||||
|
||||
#include "../../include/ZeroTierCore.h"
|
||||
|
||||
#if __has_include("../../version.h")
|
||||
#include "../../version.h"
|
||||
#else
|
||||
#define ZEROTIER_ONE_VERSION_MAJOR 255
|
||||
#define ZEROTIER_ONE_VERSION_MINOR 255
|
||||
#define ZEROTIER_ONE_VERSION_REVISION 255
|
||||
#define ZEROTIER_ONE_VERSION_BUILD 255
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/* A pointer to an instance of EthernetTap */
|
||||
|
@ -38,7 +38,7 @@ func (a Address) String() string {
|
||||
|
||||
// MarshalJSON marshals this Address as a string
|
||||
func (a Address) MarshalJSON() ([]byte, error) {
|
||||
return []byte(a.String()), nil
|
||||
return []byte("\"" + a.String() + "\""), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals this Address from a string
|
||||
|
@ -1,109 +0,0 @@
|
||||
/*
|
||||
* 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 (
|
||||
"bytes"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// Base62Alphabet is the alphabet used for LF's Base62 encoding.
|
||||
const Base62Alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
var base62Encoding, _ = newBaseXEncoding(Base62Alphabet)
|
||||
|
||||
type baseXEncoding struct {
|
||||
base int
|
||||
alphabet []rune
|
||||
alphabetMap map[rune]int
|
||||
}
|
||||
|
||||
func newBaseXEncoding(alphabet string) (*baseXEncoding, error) {
|
||||
runes := []rune(alphabet)
|
||||
runeMap := make(map[rune]int)
|
||||
for i := 0; i < len(runes); i++ {
|
||||
if _, ok := runeMap[runes[i]]; ok {
|
||||
return nil, errors.New("bad alphabet")
|
||||
}
|
||||
runeMap[runes[i]] = i
|
||||
}
|
||||
return &baseXEncoding{
|
||||
base: len(runes),
|
||||
alphabet: runes,
|
||||
alphabetMap: runeMap,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (e *baseXEncoding) encode(source []byte) string {
|
||||
if len(source) == 0 {
|
||||
return ""
|
||||
}
|
||||
digits := []int{0}
|
||||
for i := 0; i < len(source); i++ {
|
||||
carry := int(source[i])
|
||||
for j := 0; j < len(digits); j++ {
|
||||
carry += digits[j] << 8
|
||||
digits[j] = carry % e.base
|
||||
carry = carry / e.base
|
||||
}
|
||||
for carry > 0 {
|
||||
digits = append(digits, carry%e.base)
|
||||
carry = carry / e.base
|
||||
}
|
||||
}
|
||||
var res bytes.Buffer
|
||||
for k := 0; source[k] == 0 && k < len(source)-1; k++ {
|
||||
res.WriteRune(e.alphabet[0])
|
||||
}
|
||||
for q := len(digits) - 1; q >= 0; q-- {
|
||||
res.WriteRune(e.alphabet[digits[q]])
|
||||
}
|
||||
return res.String()
|
||||
}
|
||||
|
||||
func (e *baseXEncoding) decode(source string) []byte {
|
||||
if len(source) == 0 {
|
||||
return nil
|
||||
}
|
||||
runes := []rune(source)
|
||||
bytes := []byte{0}
|
||||
for i := 0; i < len(source); i++ {
|
||||
value, ok := e.alphabetMap[runes[i]]
|
||||
if ok { // ignore non-base characters
|
||||
carry := int(value)
|
||||
for j := 0; j < len(bytes); j++ {
|
||||
carry += int(bytes[j]) * e.base
|
||||
bytes[j] = byte(carry & 0xff)
|
||||
carry >>= 8
|
||||
}
|
||||
for carry > 0 {
|
||||
bytes = append(bytes, byte(carry&0xff))
|
||||
carry >>= 8
|
||||
}
|
||||
}
|
||||
}
|
||||
for k := 0; runes[k] == e.alphabet[0] && k < len(runes)-1; k++ {
|
||||
bytes = append(bytes, 0)
|
||||
}
|
||||
for i, j := 0, len(bytes)-1; i < j; i, j = i+1, j-1 {
|
||||
bytes[i], bytes[j] = bytes[j], bytes[i]
|
||||
}
|
||||
return bytes
|
||||
}
|
||||
|
||||
// Base62Encode encodes a byte array in base62 form
|
||||
func Base62Encode(in []byte) string { return base62Encoding.encode(in) }
|
||||
|
||||
// Base62Decode decodes a base62 string into a byte array, ignoring non-base62 characters
|
||||
func Base62Decode(in string) []byte { return base62Encoding.decode(in) }
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
// This is copied from the LF code base to make JSON blob encoding uniform
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// Blob is a byte array that serializes to a string or a base62 string prefixed by \b (binary)
|
||||
type Blob []byte
|
||||
|
||||
// MarshalJSON returns this blob marshaled as a string using \b<base62> for non-UTF8 binary data.
|
||||
func (b Blob) MarshalJSON() ([]byte, error) {
|
||||
if utf8.Valid(b) {
|
||||
return json.Marshal(string(b))
|
||||
}
|
||||
return []byte("\"\\b" + Base62Encode(b) + "\""), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals this blob from a string or byte array.
|
||||
func (b *Blob) UnmarshalJSON(j []byte) error {
|
||||
var s string
|
||||
err := json.Unmarshal(j, &s)
|
||||
if err == nil {
|
||||
if len(s) == 0 {
|
||||
*b = nil
|
||||
} else if s[0] == '\b' {
|
||||
*b = Base62Decode(s[1:])
|
||||
return nil
|
||||
}
|
||||
*b = []byte(s)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Byte arrays are also accepted
|
||||
var bb []byte
|
||||
if json.Unmarshal(j, &bb) != nil {
|
||||
return err
|
||||
}
|
||||
*b = bb
|
||||
return nil
|
||||
}
|
@ -14,8 +14,8 @@
|
||||
package zerotier
|
||||
|
||||
import (
|
||||
"encoding/base32"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
@ -36,15 +36,9 @@ const (
|
||||
|
||||
// Identity is precisely what it sounds like: the address and associated keys for a ZeroTier node
|
||||
type Identity struct {
|
||||
// Address is this identity's 40-bit short address
|
||||
Address Address
|
||||
|
||||
// Type is either IdentityTypeC25519 or IdentityTypeP384
|
||||
Type int
|
||||
|
||||
// PublicKey is this identity's public key bytes
|
||||
PublicKey Blob
|
||||
|
||||
address Address
|
||||
idtype int
|
||||
publicKey []byte
|
||||
privateKey []byte
|
||||
}
|
||||
|
||||
@ -58,23 +52,23 @@ func NewIdentityFromString(s string) (*Identity, error) {
|
||||
|
||||
var err error
|
||||
var id Identity
|
||||
id.Address, err = NewAddressFromString(ss[0])
|
||||
id.address, err = NewAddressFromString(ss[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if ss[1] == "0" {
|
||||
id.Type = 0
|
||||
id.idtype = 0
|
||||
} else if ss[1] == "1" {
|
||||
id.Type = 1
|
||||
id.idtype = 1
|
||||
} else {
|
||||
return nil, ErrUncrecognizedIdentityType
|
||||
}
|
||||
|
||||
switch id.Type {
|
||||
switch id.idtype {
|
||||
|
||||
case 0:
|
||||
id.PublicKey, err = hex.DecodeString(ss[2])
|
||||
id.publicKey, err = hex.DecodeString(ss[2])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -86,15 +80,15 @@ func NewIdentityFromString(s string) (*Identity, error) {
|
||||
}
|
||||
|
||||
case 1:
|
||||
id.PublicKey, err = base32.StdEncoding.DecodeString(ss[2])
|
||||
id.publicKey, err = base32StdLowerCase.DecodeString(ss[2])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(id.PublicKey) != IdentityTypeP384PublicKeySize {
|
||||
if len(id.publicKey) != IdentityTypeP384PublicKeySize {
|
||||
return nil, ErrInvalidKey
|
||||
}
|
||||
if len(ss) >= 4 {
|
||||
id.privateKey, err = base32.StdEncoding.DecodeString(ss[3])
|
||||
id.privateKey, err = base32StdLowerCase.DecodeString(ss[3])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -113,9 +107,15 @@ func (id *Identity) HasPrivate() bool { return len(id.privateKey) > 0 }
|
||||
|
||||
// PrivateKeyString returns the full identity.secret if the private key is set, or an empty string if no private key is set.
|
||||
func (id *Identity) PrivateKeyString() string {
|
||||
if len(id.privateKey) == 64 {
|
||||
s := fmt.Sprintf("%.10x:0:%x:%x", id.Address, id.PublicKey, id.privateKey)
|
||||
return s
|
||||
switch id.idtype {
|
||||
case IdentityTypeC25519:
|
||||
if len(id.publicKey) == IdentityTypeC25519PublicKeySize && len(id.privateKey) == IdentityTypeC25519PrivateKeySize {
|
||||
return fmt.Sprintf("%.10x:0:%x:%x", uint64(id.address), id.publicKey, id.privateKey)
|
||||
}
|
||||
case IdentityTypeP384:
|
||||
if len(id.publicKey) == IdentityTypeP384PublicKeySize && len(id.privateKey) == IdentityTypeP384PrivateKeySize {
|
||||
return fmt.Sprintf("%.10x:1:%s:%s", uint64(id.address), base32StdLowerCase.EncodeToString(id.publicKey), base32StdLowerCase.EncodeToString(id.privateKey))
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@ -123,9 +123,26 @@ func (id *Identity) PrivateKeyString() string {
|
||||
// PublicKeyString returns the address and public key (identity.public contents).
|
||||
// An empty string is returned if this identity is invalid or not initialized.
|
||||
func (id *Identity) String() string {
|
||||
if len(id.PublicKey) == 64 {
|
||||
s := fmt.Sprintf("%.10x:0:%x", id.Address, id.PublicKey)
|
||||
if len(id.publicKey) == IdentityTypeC25519PublicKeySize {
|
||||
s := fmt.Sprintf("%.10x:0:%x", id.address, id.publicKey)
|
||||
return s
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// MarshalJSON marshals this Identity in its string format (private key is never included)
|
||||
func (id *Identity) MarshalJSON() ([]byte, error) {
|
||||
return []byte("\"" + id.String() + "\""), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals this Identity from a string
|
||||
func (id *Identity) UnmarshalJSON(j []byte) error {
|
||||
var s string
|
||||
err := json.Unmarshal(j, &s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nid, err := NewIdentityFromString(s)
|
||||
*id = *nid
|
||||
return err
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ func (m MAC) String() string {
|
||||
|
||||
// MarshalJSON marshals this MAC as a string
|
||||
func (m MAC) MarshalJSON() ([]byte, error) {
|
||||
return []byte(m.String()), nil
|
||||
return []byte("\"" + m.String() + "\""), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals this MAC from a string
|
||||
|
@ -13,7 +13,12 @@
|
||||
|
||||
package zerotier
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"encoding/base32"
|
||||
"time"
|
||||
)
|
||||
|
||||
var base32StdLowerCase = base32.NewEncoding("abcdefghijklmnopqrstuvwxyz234567")
|
||||
|
||||
// TimeMs returns the time in milliseconds since epoch.
|
||||
func TimeMs() int64 { return int64(time.Now().UnixNano()) / int64(1000000) }
|
||||
|
@ -1,157 +0,0 @@
|
||||
/*
|
||||
* 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"
|
||||
"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
|
||||
multicastGroupHandlers []func(bool, *MulticastGroup)
|
||||
multicastGroupHandlersLock sync.Mutex
|
||||
}
|
||||
|
||||
// Type returns a human-readable description of this tap implementation
|
||||
func (t *nativeTap) Type() string {
|
||||
return "native"
|
||||
}
|
||||
|
||||
// Error gets this tap device's error status
|
||||
func (t *nativeTap) Error() (int, string) {
|
||||
return 0, ""
|
||||
}
|
||||
|
||||
// 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, C.int(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, C.int(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, C.int(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, C.int(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 := int(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 ""
|
||||
}
|
||||
|
||||
// AddMulticastGroupChangeHandler adds a function to be called when the tap subscribes or unsubscribes to a multicast group.
|
||||
func (t *nativeTap) AddMulticastGroupChangeHandler(handler func(bool, *MulticastGroup)) {
|
||||
t.multicastGroupHandlersLock.Lock()
|
||||
t.multicastGroupHandlers = append(t.multicastGroupHandlers, handler)
|
||||
t.multicastGroupHandlersLock.Unlock()
|
||||
}
|
@ -1,224 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
// These are exported callbacks that are called from the C++ code in GoGlue.cpp
|
||||
|
||||
//#cgo CFLAGS: -O3
|
||||
//#define ZT_CGO 1
|
||||
//#include <stdint.h>
|
||||
//#include <stdlib.h>
|
||||
//#include <string.h>
|
||||
//#include "../../native/GoGlue.h"
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"net"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
afInet int = C.AF_INET
|
||||
afInet6 int = C.AF_INET6
|
||||
|
||||
networkStatusRequestingConfiguration = C.ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION
|
||||
networkStatusOK = C.ZT_NETWORK_STATUS_OK
|
||||
networkStatusAccessDenied = C.ZT_NETWORK_STATUS_ACCESS_DENIED
|
||||
networkStatusNotFound = C.ZT_NETWORK_STATUS_NOT_FOUND
|
||||
networkStatusPortError = C.ZT_NETWORK_STATUS_PORT_ERROR
|
||||
networkStatusClientTooOld = C.ZT_NETWORK_STATUS_CLIENT_TOO_OLD
|
||||
)
|
||||
|
||||
var (
|
||||
nodesByUserPtr map[uintptr]*Node
|
||||
nodesByUserPtrLock sync.RWMutex
|
||||
)
|
||||
|
||||
//export goPathCheckFunc
|
||||
func goPathCheckFunc(gn unsafe.Pointer, ztAddress C.uint64_t, af C.int, ip unsafe.Pointer, port C.int) C.int {
|
||||
nodesByUserPtrLock.RLock()
|
||||
node := nodesByUserPtr[uintptr(gn)]
|
||||
nodesByUserPtrLock.RUnlock()
|
||||
if node != nil && node.pathCheck(uint64(ztAddress), int(af), nil, int(port)) {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
//export goPathLookupFunc
|
||||
func goPathLookupFunc(gn unsafe.Pointer, ztAddress C.uint64_t, desiredAddressFamily int, familyP, ipP, portP unsafe.Pointer) C.int {
|
||||
nodesByUserPtrLock.RLock()
|
||||
node := nodesByUserPtr[uintptr(gn)]
|
||||
nodesByUserPtrLock.RUnlock()
|
||||
if node == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
ip, port := node.pathLookup(uint64(ztAddress))
|
||||
if len(ip) > 0 && port > 0 && port <= 65535 {
|
||||
ip4 := ip.To4()
|
||||
if len(ip4) == 4 {
|
||||
*((*C.int)(familyP)) = C.int(afInet)
|
||||
copy((*[4]byte)(ipP)[:], ip4)
|
||||
*((*C.int)(portP)) = C.int(port)
|
||||
return 1
|
||||
} else if len(ip) == 16 {
|
||||
*((*C.int)(familyP)) = C.int(afInet6)
|
||||
copy((*[16]byte)(ipP)[:], ip)
|
||||
*((*C.int)(portP)) = C.int(port)
|
||||
return 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
//export goStateObjectPutFunc
|
||||
func goStateObjectPutFunc(gn unsafe.Pointer, objType C.int, id, data unsafe.Pointer, len C.int) {
|
||||
nodesByUserPtrLock.RLock()
|
||||
node := nodesByUserPtr[uintptr(gn)]
|
||||
nodesByUserPtrLock.RUnlock()
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
if len < 0 {
|
||||
node.stateObjectDelete(int(objType), *((*[2]uint64)(id)))
|
||||
} else {
|
||||
node.stateObjectPut(int(objType), *((*[2]uint64)(id)), C.GoBytes(data, len))
|
||||
}
|
||||
}
|
||||
|
||||
//export goStateObjectGetFunc
|
||||
func goStateObjectGetFunc(gn unsafe.Pointer, objType C.int, id, data unsafe.Pointer, bufSize C.uint) C.int {
|
||||
nodesByUserPtrLock.RLock()
|
||||
node := nodesByUserPtr[uintptr(gn)]
|
||||
nodesByUserPtrLock.RUnlock()
|
||||
if node == nil {
|
||||
return -1
|
||||
}
|
||||
tmp, found := node.stateObjectGet(int(objType), *((*[2]uint64)(id)))
|
||||
if found && len(tmp) < int(bufSize) {
|
||||
if len(tmp) > 0 {
|
||||
C.memcpy(data, unsafe.Pointer(&(tmp[0])), C.ulong(len(tmp)))
|
||||
}
|
||||
return C.int(len(tmp))
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
//export goDNSResolverFunc
|
||||
func goDNSResolverFunc(gn unsafe.Pointer, dnsRecordTypes unsafe.Pointer, numDNSRecordTypes C.int, name unsafe.Pointer, requestID C.uintptr_t) {
|
||||
nodesByUserPtrLock.RLock()
|
||||
node := nodesByUserPtr[uintptr(gn)]
|
||||
nodesByUserPtrLock.RUnlock()
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
|
||||
recordTypes := C.GoBytes(dnsRecordTypes, numDNSRecordTypes)
|
||||
recordName := C.GoString((*C.char)(name))
|
||||
|
||||
go func() {
|
||||
recordNameCStrCopy := C.CString(recordName)
|
||||
for _, rt := range recordTypes {
|
||||
switch rt {
|
||||
case C.ZT_DNS_RECORD_TXT:
|
||||
recs, _ := net.LookupTXT(recordName)
|
||||
for _, rec := range recs {
|
||||
if len(rec) > 0 {
|
||||
rnCS := C.CString(rec)
|
||||
C.ZT_Node_processDNSResult(unsafe.Pointer(node.zn), nil, requestID, recordNameCStrCopy, C.ZT_DNS_RECORD_TXT, unsafe.Pointer(rnCS), C.uint(len(rec)), 0)
|
||||
C.free(unsafe.Pointer(rnCS))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
C.ZT_Node_processDNSResult(unsafe.Pointer(node.zn), nil, requestID, recordNameCStrCopy, C.ZT_DNS_RECORD__END_OF_RESULTS, nil, 0, 0)
|
||||
C.free(unsafe.Pointer(recordNameCStrCopy))
|
||||
}()
|
||||
}
|
||||
|
||||
//export goVirtualNetworkConfigFunc
|
||||
func goVirtualNetworkConfigFunc(gn, tapP unsafe.Pointer, nwid C.uint64_t, op C.int, conf unsafe.Pointer) C.int {
|
||||
nodesByUserPtrLock.RLock()
|
||||
node := nodesByUserPtr[uintptr(gn)]
|
||||
nodesByUserPtrLock.RUnlock()
|
||||
if node == nil {
|
||||
return 255
|
||||
}
|
||||
return C.int(node.handleNetworkConfigUpdate(uint64(nwid), int(op), (*C.ZT_VirtualNetworkConfig)(conf)))
|
||||
}
|
||||
|
||||
//export goZtEvent
|
||||
func goZtEvent(gn unsafe.Pointer, eventType C.int, data unsafe.Pointer) {
|
||||
nodesByUserPtrLock.RLock()
|
||||
node := nodesByUserPtr[uintptr(gn)]
|
||||
nodesByUserPtrLock.RUnlock()
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
switch eventType {
|
||||
case C.ZT_EVENT_OFFLINE:
|
||||
atomic.StoreUint32(&node.online, 0)
|
||||
case C.ZT_EVENT_ONLINE:
|
||||
atomic.StoreUint32(&node.online, 1)
|
||||
case C.ZT_EVENT_TRACE:
|
||||
node.handleTrace(C.GoString((*C.char)(data)))
|
||||
case C.ZT_EVENT_USER_MESSAGE:
|
||||
um := (*C.ZT_UserMessage)(data)
|
||||
node.handleUserMessage(uint64(um.origin), uint64(um.typeId), C.GoBytes(um.data, C.int(um.length)))
|
||||
case C.ZT_EVENT_REMOTE_TRACE:
|
||||
rt := (*C.ZT_RemoteTrace)(data)
|
||||
node.handleRemoteTrace(uint64(rt.origin), C.GoBytes(unsafe.Pointer(rt.data), C.int(rt.len)))
|
||||
}
|
||||
}
|
||||
|
||||
// These are really part of nativeTap
|
||||
|
||||
func handleTapMulticastGroupChange(gn unsafe.Pointer, nwid, mac C.uint64_t, adi C.uint32_t, added bool) {
|
||||
nodesByUserPtrLock.RLock()
|
||||
node := nodesByUserPtr[uintptr(gn)]
|
||||
nodesByUserPtrLock.RUnlock()
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
|
||||
node.networksLock.RLock()
|
||||
network := node.networks[uint64(nwid)]
|
||||
node.networksLock.RUnlock()
|
||||
|
||||
network.tapLock.Lock()
|
||||
tap, _ := network.tap.(*nativeTap)
|
||||
network.tapLock.Unlock()
|
||||
|
||||
if tap != nil {
|
||||
mg := &MulticastGroup{MAC: MAC(mac), ADI: uint32(adi)}
|
||||
tap.multicastGroupHandlersLock.Lock()
|
||||
defer tap.multicastGroupHandlersLock.Unlock()
|
||||
for _, h := range tap.multicastGroupHandlers {
|
||||
h(added, mg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//export goHandleTapAddedMulticastGroup
|
||||
func goHandleTapAddedMulticastGroup(gn, tapP unsafe.Pointer, nwid, mac C.uint64_t, adi C.uint32_t) {
|
||||
handleTapMulticastGroupChange(gn, nwid, mac, adi, true)
|
||||
}
|
||||
|
||||
//export goHandleTapRemovedMulticastGroup
|
||||
func goHandleTapRemovedMulticastGroup(gn, tapP unsafe.Pointer, nwid, mac C.uint64_t, adi C.uint32_t) {
|
||||
handleTapMulticastGroupChange(gn, nwid, mac, adi, false)
|
||||
}
|
@ -13,6 +13,12 @@
|
||||
|
||||
package zerotier
|
||||
|
||||
//#cgo CFLAGS: -O3
|
||||
//#cgo LDFLAGS: ${SRCDIR}/../../../build/node/libzt_core.a ${SRCDIR}/../../../build/osdep/libzt_osdep.a ${SRCDIR}/../../../build/go/native/libzt_go_native.a -lc++ -lpthread
|
||||
//#define ZT_CGO 1
|
||||
//#include "../../native/GoGlue.h"
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -28,15 +34,6 @@ import (
|
||||
acl "github.com/hectane/go-acl"
|
||||
)
|
||||
|
||||
//#cgo CFLAGS: -O3
|
||||
//#cgo LDFLAGS: ${SRCDIR}/../../../build/node/libzt_core.a ${SRCDIR}/../../../build/osdep/libzt_osdep.a ${SRCDIR}/../../../build/go/native/libzt_go_native.a -lc++ -lpthread
|
||||
//#define ZT_CGO 1
|
||||
//#include <stdint.h>
|
||||
//#include <stdlib.h>
|
||||
//#include <string.h>
|
||||
//#include "../../native/GoGlue.h"
|
||||
import "C"
|
||||
|
||||
// Network status states
|
||||
const (
|
||||
NetworkStatusRequestConfiguration int = C.ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION
|
||||
@ -45,6 +42,26 @@ const (
|
||||
NetworkStatusNotFound int = C.ZT_NETWORK_STATUS_NOT_FOUND
|
||||
NetworkStatusPortError int = C.ZT_NETWORK_STATUS_PORT_ERROR
|
||||
NetworkStatusClientTooOld int = C.ZT_NETWORK_STATUS_CLIENT_TOO_OLD
|
||||
|
||||
// CoreVersionMajor is the major version of the ZeroTier core
|
||||
CoreVersionMajor int = C.ZEROTIER_ONE_VERSION_MAJOR
|
||||
|
||||
// CoreVersionMinor is the minor version of the ZeroTier core
|
||||
CoreVersionMinor int = C.ZEROTIER_ONE_VERSION_MINOR
|
||||
|
||||
// CoreVersionRevision is the revision of the ZeroTier core
|
||||
CoreVersionRevision int = C.ZEROTIER_ONE_VERSION_REVISION
|
||||
|
||||
// CoreVersionBuild is the build version of the ZeroTier core
|
||||
CoreVersionBuild int = C.ZEROTIER_ONE_VERSION_BUILD
|
||||
|
||||
afInet int = C.AF_INET
|
||||
afInet6 int = C.AF_INET6
|
||||
)
|
||||
|
||||
var (
|
||||
nodesByUserPtr map[uintptr]*Node
|
||||
nodesByUserPtrLock sync.RWMutex
|
||||
)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -225,6 +242,314 @@ func (n *Node) handleUserMessage(originAddress, messageTypeID uint64, data []byt
|
||||
func (n *Node) handleRemoteTrace(originAddress uint64, dictData []byte) {
|
||||
}
|
||||
|
||||
func (n *Node) handleNetworkConfigUpdate(nwid uint64, op int, config *C.ZT_VirtualNetworkConfig) int {
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//export goPathCheckFunc
|
||||
func goPathCheckFunc(gn unsafe.Pointer, ztAddress C.uint64_t, af C.int, ip unsafe.Pointer, port C.int) C.int {
|
||||
nodesByUserPtrLock.RLock()
|
||||
node := nodesByUserPtr[uintptr(gn)]
|
||||
nodesByUserPtrLock.RUnlock()
|
||||
if node != nil && node.pathCheck(uint64(ztAddress), int(af), nil, int(port)) {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
//export goPathLookupFunc
|
||||
func goPathLookupFunc(gn unsafe.Pointer, ztAddress C.uint64_t, desiredAddressFamily int, familyP, ipP, portP unsafe.Pointer) C.int {
|
||||
nodesByUserPtrLock.RLock()
|
||||
node := nodesByUserPtr[uintptr(gn)]
|
||||
nodesByUserPtrLock.RUnlock()
|
||||
if node == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
ip, port := node.pathLookup(uint64(ztAddress))
|
||||
if len(ip) > 0 && port > 0 && port <= 65535 {
|
||||
ip4 := ip.To4()
|
||||
if len(ip4) == 4 {
|
||||
*((*C.int)(familyP)) = C.int(afInet)
|
||||
copy((*[4]byte)(ipP)[:], ip4)
|
||||
*((*C.int)(portP)) = C.int(port)
|
||||
return 1
|
||||
} else if len(ip) == 16 {
|
||||
*((*C.int)(familyP)) = C.int(afInet6)
|
||||
copy((*[16]byte)(ipP)[:], ip)
|
||||
*((*C.int)(portP)) = C.int(port)
|
||||
return 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
//export goStateObjectPutFunc
|
||||
func goStateObjectPutFunc(gn unsafe.Pointer, objType C.int, id, data unsafe.Pointer, len C.int) {
|
||||
nodesByUserPtrLock.RLock()
|
||||
node := nodesByUserPtr[uintptr(gn)]
|
||||
nodesByUserPtrLock.RUnlock()
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
if len < 0 {
|
||||
node.stateObjectDelete(int(objType), *((*[2]uint64)(id)))
|
||||
} else {
|
||||
node.stateObjectPut(int(objType), *((*[2]uint64)(id)), C.GoBytes(data, len))
|
||||
}
|
||||
}
|
||||
|
||||
//export goStateObjectGetFunc
|
||||
func goStateObjectGetFunc(gn unsafe.Pointer, objType C.int, id, data unsafe.Pointer, bufSize C.uint) C.int {
|
||||
nodesByUserPtrLock.RLock()
|
||||
node := nodesByUserPtr[uintptr(gn)]
|
||||
nodesByUserPtrLock.RUnlock()
|
||||
if node == nil {
|
||||
return -1
|
||||
}
|
||||
tmp, found := node.stateObjectGet(int(objType), *((*[2]uint64)(id)))
|
||||
if found && len(tmp) < int(bufSize) {
|
||||
if len(tmp) > 0 {
|
||||
C.memcpy(data, unsafe.Pointer(&(tmp[0])), C.ulong(len(tmp)))
|
||||
}
|
||||
return C.int(len(tmp))
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
//export goDNSResolverFunc
|
||||
func goDNSResolverFunc(gn unsafe.Pointer, dnsRecordTypes unsafe.Pointer, numDNSRecordTypes C.int, name unsafe.Pointer, requestID C.uintptr_t) {
|
||||
nodesByUserPtrLock.RLock()
|
||||
node := nodesByUserPtr[uintptr(gn)]
|
||||
nodesByUserPtrLock.RUnlock()
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
|
||||
recordTypes := C.GoBytes(dnsRecordTypes, numDNSRecordTypes)
|
||||
recordName := C.GoString((*C.char)(name))
|
||||
|
||||
go func() {
|
||||
recordNameCStrCopy := C.CString(recordName)
|
||||
for _, rt := range recordTypes {
|
||||
switch rt {
|
||||
case C.ZT_DNS_RECORD_TXT:
|
||||
recs, _ := net.LookupTXT(recordName)
|
||||
for _, rec := range recs {
|
||||
if len(rec) > 0 {
|
||||
rnCS := C.CString(rec)
|
||||
C.ZT_Node_processDNSResult(unsafe.Pointer(node.zn), nil, requestID, recordNameCStrCopy, C.ZT_DNS_RECORD_TXT, unsafe.Pointer(rnCS), C.uint(len(rec)), 0)
|
||||
C.free(unsafe.Pointer(rnCS))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
C.ZT_Node_processDNSResult(unsafe.Pointer(node.zn), nil, requestID, recordNameCStrCopy, C.ZT_DNS_RECORD__END_OF_RESULTS, nil, 0, 0)
|
||||
C.free(unsafe.Pointer(recordNameCStrCopy))
|
||||
}()
|
||||
}
|
||||
|
||||
//export goVirtualNetworkConfigFunc
|
||||
func goVirtualNetworkConfigFunc(gn, tapP unsafe.Pointer, nwid C.uint64_t, op C.int, conf unsafe.Pointer) C.int {
|
||||
nodesByUserPtrLock.RLock()
|
||||
node := nodesByUserPtr[uintptr(gn)]
|
||||
nodesByUserPtrLock.RUnlock()
|
||||
if node == nil {
|
||||
return 255
|
||||
}
|
||||
node.networksLock.RLock()
|
||||
network := node.networks[uint64(nwid)]
|
||||
node.networksLock.RUnlock()
|
||||
if network != nil {
|
||||
}
|
||||
//return C.int(node.handleNetworkConfigUpdate(uint64(nwid), int(op), (*C.ZT_VirtualNetworkConfig)(conf)))
|
||||
}
|
||||
|
||||
//export goZtEvent
|
||||
func goZtEvent(gn unsafe.Pointer, eventType C.int, data unsafe.Pointer) {
|
||||
nodesByUserPtrLock.RLock()
|
||||
node := nodesByUserPtr[uintptr(gn)]
|
||||
nodesByUserPtrLock.RUnlock()
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
switch eventType {
|
||||
case C.ZT_EVENT_OFFLINE:
|
||||
atomic.StoreUint32(&node.online, 0)
|
||||
case C.ZT_EVENT_ONLINE:
|
||||
atomic.StoreUint32(&node.online, 1)
|
||||
case C.ZT_EVENT_TRACE:
|
||||
node.handleTrace(C.GoString((*C.char)(data)))
|
||||
case C.ZT_EVENT_USER_MESSAGE:
|
||||
um := (*C.ZT_UserMessage)(data)
|
||||
node.handleUserMessage(uint64(um.origin), uint64(um.typeId), C.GoBytes(um.data, C.int(um.length)))
|
||||
case C.ZT_EVENT_REMOTE_TRACE:
|
||||
rt := (*C.ZT_RemoteTrace)(data)
|
||||
node.handleRemoteTrace(uint64(rt.origin), C.GoBytes(unsafe.Pointer(rt.data), C.int(rt.len)))
|
||||
}
|
||||
}
|
||||
|
||||
// These are really part of nativeTap
|
||||
|
||||
func handleTapMulticastGroupChange(gn unsafe.Pointer, nwid, mac C.uint64_t, adi C.uint32_t, added bool) {
|
||||
nodesByUserPtrLock.RLock()
|
||||
node := nodesByUserPtr[uintptr(gn)]
|
||||
nodesByUserPtrLock.RUnlock()
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
|
||||
node.networksLock.RLock()
|
||||
network := node.networks[uint64(nwid)]
|
||||
node.networksLock.RUnlock()
|
||||
|
||||
network.tapLock.Lock()
|
||||
tap, _ := network.tap.(*nativeTap)
|
||||
network.tapLock.Unlock()
|
||||
|
||||
if tap != nil {
|
||||
mg := &MulticastGroup{MAC: MAC(mac), ADI: uint32(adi)}
|
||||
tap.multicastGroupHandlersLock.Lock()
|
||||
defer tap.multicastGroupHandlersLock.Unlock()
|
||||
for _, h := range tap.multicastGroupHandlers {
|
||||
h(added, mg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//export goHandleTapAddedMulticastGroup
|
||||
func goHandleTapAddedMulticastGroup(gn, tapP unsafe.Pointer, nwid, mac C.uint64_t, adi C.uint32_t) {
|
||||
handleTapMulticastGroupChange(gn, nwid, mac, adi, true)
|
||||
}
|
||||
|
||||
//export goHandleTapRemovedMulticastGroup
|
||||
func goHandleTapRemovedMulticastGroup(gn, tapP unsafe.Pointer, nwid, mac C.uint64_t, adi C.uint32_t) {
|
||||
handleTapMulticastGroupChange(gn, nwid, mac, adi, false)
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// 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
|
||||
multicastGroupHandlers []func(bool, *MulticastGroup)
|
||||
multicastGroupHandlersLock sync.Mutex
|
||||
}
|
||||
|
||||
// Type returns a human-readable description of this tap implementation
|
||||
func (t *nativeTap) Type() string {
|
||||
return "native"
|
||||
}
|
||||
|
||||
// Error gets this tap device's error status
|
||||
func (t *nativeTap) Error() (int, string) {
|
||||
return 0, ""
|
||||
}
|
||||
|
||||
// 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, C.int(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, C.int(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, C.int(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, C.int(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 := int(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 ""
|
||||
}
|
||||
|
||||
// AddMulticastGroupChangeHandler adds a function to be called when the tap subscribes or unsubscribes to a multicast group.
|
||||
func (t *nativeTap) AddMulticastGroupChangeHandler(handler func(bool, *MulticastGroup)) {
|
||||
t.multicastGroupHandlersLock.Lock()
|
||||
t.multicastGroupHandlers = append(t.multicastGroupHandlers, handler)
|
||||
t.multicastGroupHandlersLock.Unlock()
|
||||
}
|
||||
|
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
//#if __has_include("../../../version.h")
|
||||
//#include "../../../version.h"
|
||||
//#else
|
||||
//#define ZEROTIER_ONE_VERSION_MAJOR 255
|
||||
//#define ZEROTIER_ONE_VERSION_MINOR 255
|
||||
//#define ZEROTIER_ONE_VERSION_REVISION 255
|
||||
//#define ZEROTIER_ONE_VERSION_BUILD 255
|
||||
//#endif
|
||||
import "C"
|
||||
|
||||
const (
|
||||
// CoreVersionMajor is the major version of the ZeroTier core
|
||||
CoreVersionMajor int = C.ZEROTIER_ONE_VERSION_MAJOR
|
||||
|
||||
// CoreVersionMinor is the minor version of the ZeroTier core
|
||||
CoreVersionMinor int = C.ZEROTIER_ONE_VERSION_MINOR
|
||||
|
||||
// CoreVersionRevision is the revision of the ZeroTier core
|
||||
CoreVersionRevision int = C.ZEROTIER_ONE_VERSION_REVISION
|
||||
|
||||
// CoreVersionBuild is the build version of the ZeroTier core
|
||||
CoreVersionBuild int = C.ZEROTIER_ONE_VERSION_BUILD
|
||||
)
|
@ -1156,19 +1156,6 @@ typedef struct
|
||||
* Routes (excluding those implied by assigned addresses and their masks)
|
||||
*/
|
||||
ZT_VirtualNetworkRoute routes[ZT_MAX_NETWORK_ROUTES];
|
||||
|
||||
/**
|
||||
* Number of multicast groups subscribed
|
||||
*/
|
||||
unsigned int multicastSubscriptionCount;
|
||||
|
||||
/**
|
||||
* Multicast groups to which this network's device is subscribed
|
||||
*/
|
||||
struct {
|
||||
uint64_t mac; /* MAC in lower 48 bits */
|
||||
uint32_t adi; /* Additional distinguishing information, usually zero except for IPv4 ARP groups */
|
||||
} multicastSubscriptions[ZT_MAX_MULTICAST_SUBSCRIPTIONS];
|
||||
} ZT_VirtualNetworkConfig;
|
||||
|
||||
/**
|
||||
|
@ -1366,12 +1366,6 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
|
||||
memset(&(ec->routes[i]),0,sizeof(ZT_VirtualNetworkRoute));
|
||||
}
|
||||
}
|
||||
|
||||
ec->multicastSubscriptionCount = (unsigned int)_myMulticastGroups.size();
|
||||
for(unsigned long i=0;i<(unsigned long)_myMulticastGroups.size();++i) {
|
||||
ec->multicastSubscriptions[i].mac = _myMulticastGroups[i].mac().toInt();
|
||||
ec->multicastSubscriptions[i].adi = _myMulticastGroups[i].adi();
|
||||
}
|
||||
}
|
||||
|
||||
void Network::_announceMulticastGroups(void *tPtr,bool force)
|
||||
|
@ -306,7 +306,7 @@ int Utils::b32e(const uint8_t *data,int length,char *result,int bufSize)
|
||||
}
|
||||
int index = 0x1F & (buffer >> (bitsLeft - 5));
|
||||
bitsLeft -= 5;
|
||||
result[count++] = "abcdefghijklmnopqrstuvwxyZ234567"[index];
|
||||
result[count++] = "abcdefghijklmnopqrstuvwxyz234567"[index];
|
||||
}
|
||||
}
|
||||
if (count < bufSize) {
|
||||
|
Loading…
Reference in New Issue
Block a user