mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-23 18:33:34 +00:00
Gogogogogogogo
This commit is contained in:
parent
b44bd19c53
commit
b6175bd408
32
go/cmd/zerotier/zerotier.go
Normal file
32
go/cmd/zerotier/zerotier.go
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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 main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func nodeStart() {
|
||||
osSignalChannel := make(chan os.Signal, 2)
|
||||
signal.Notify(osSignalChannel, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT, syscall.SIGBUS)
|
||||
signal.Ignore(syscall.SIGUSR1, syscall.SIGUSR2)
|
||||
go func() {
|
||||
<-osSignalChannel
|
||||
}()
|
||||
}
|
||||
|
||||
func main() {
|
||||
}
|
@ -2,4 +2,7 @@ module zerotier
|
||||
|
||||
go 1.13
|
||||
|
||||
require github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95
|
||||
require (
|
||||
github.com/Microsoft/go-winio v0.4.14 // indirect
|
||||
github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95
|
||||
)
|
||||
|
11
go/go.sum
11
go/go.sum
@ -1,4 +1,15 @@
|
||||
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95 h1:S4qyfL2sEm5Budr4KVMyEniCy+PbS55651I/a+Kn/NQ=
|
||||
github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95/go.mod h1:QiyDdbZLaJ/mZP4Zwc9g2QsfaEA4o7XvvgZegSci5/E=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190529164535-6a60838ec259 h1:so6Hr/LodwSZ5UQDu/7PmQiDeS112WwtLvU3lpSPZTU=
|
||||
golang.org/x/sys v0.0.0-20190529164535-6a60838ec259/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -57,6 +57,7 @@
|
||||
#include <array>
|
||||
#include <set>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#define SETSOCKOPT_FLAG_TYPE BOOL
|
||||
@ -79,7 +80,7 @@ struct ZT_GoNodeThread
|
||||
std::string ip;
|
||||
int port;
|
||||
int af;
|
||||
std::atomic_bool run;
|
||||
std::atomic<bool> run;
|
||||
std::thread thr;
|
||||
};
|
||||
|
||||
@ -89,7 +90,7 @@ struct ZT_GoNode_Impl
|
||||
volatile int64_t nextBackgroundTaskDeadline;
|
||||
|
||||
std::string path;
|
||||
std::atomic_bool run;
|
||||
std::atomic<bool> run;
|
||||
|
||||
std::map< ZT_SOCKET,ZT_GoNodeThread > threads;
|
||||
std::mutex threads_l;
|
||||
|
@ -14,24 +14,32 @@
|
||||
package zerotier
|
||||
|
||||
import (
|
||||
secrand "crypto/rand"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
acl "github.com/hectane/go-acl"
|
||||
)
|
||||
|
||||
type apiStatus struct {
|
||||
Address Address
|
||||
Clock int64
|
||||
Config *LocalConfig
|
||||
Online bool
|
||||
Identity *Identity
|
||||
Version string
|
||||
VersionMajor int
|
||||
VersionMinor int
|
||||
VersionRevision int
|
||||
VersionBuild int
|
||||
Address Address
|
||||
Clock int64
|
||||
Config LocalConfig
|
||||
Online bool
|
||||
Identity *Identity
|
||||
InterfaceAddresses []net.IP
|
||||
MappedExternalAddresses []*InetAddress
|
||||
Version string
|
||||
VersionMajor int
|
||||
VersionMinor int
|
||||
VersionRevision int
|
||||
VersionBuild int
|
||||
}
|
||||
|
||||
type apiNetwork struct {
|
||||
@ -80,36 +88,119 @@ func apiReadObj(out http.ResponseWriter, req *http.Request, dest interface{}) (e
|
||||
return
|
||||
}
|
||||
|
||||
func apiCheckAuth(out http.ResponseWriter, req *http.Request, token string) bool {
|
||||
ah := req.Header.Get("X-ZT1-Auth")
|
||||
if len(ah) > 0 && strings.TrimSpace(ah) == token {
|
||||
return true
|
||||
}
|
||||
ah = req.Header.Get("Authorization")
|
||||
if len(ah) > 0 && strings.TrimSpace(ah) == ("bearer "+token) {
|
||||
return true
|
||||
}
|
||||
apiSendObj(out, req, http.StatusUnauthorized, nil)
|
||||
return false
|
||||
}
|
||||
|
||||
// createAPIServer creates and starts an HTTP server for a given node
|
||||
func createAPIServer(basePath string, node *Node) (*http.Server, error) {
|
||||
// Read authorization token, automatically generating one if it's missing
|
||||
var authToken string
|
||||
authTokenFile := path.Join(basePath, "authtoken.secret")
|
||||
authTokenB, err := ioutil.ReadFile(authTokenFile)
|
||||
if err != nil {
|
||||
var atb [20]byte
|
||||
_, err = secrand.Read(atb[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < 20; i++ {
|
||||
atb[i] = byte("abcdefghijklmnopqrstuvwxyz0123456789"[atb[i]%36])
|
||||
}
|
||||
err = ioutil.WriteFile(authTokenFile, atb[:], 0600)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
acl.Chmod(authTokenFile, 0600)
|
||||
authToken = string(atb[:])
|
||||
} else {
|
||||
authToken = strings.TrimSpace(string(authTokenB))
|
||||
}
|
||||
|
||||
smux := http.NewServeMux()
|
||||
|
||||
smux.HandleFunc("/config", func(out http.ResponseWriter, req *http.Request) {
|
||||
smux.HandleFunc("/status", func(out http.ResponseWriter, req *http.Request) {
|
||||
if !apiCheckAuth(out, req, authToken) {
|
||||
return
|
||||
}
|
||||
apiSetStandardHeaders(out)
|
||||
if req.Method == http.MethodGet || req.Method == http.MethodHead {
|
||||
apiSendObj(out, req, http.StatusOK, nil)
|
||||
apiSendObj(out, req, http.StatusOK, &apiStatus{
|
||||
Address: node.Address(),
|
||||
Clock: TimeMs(),
|
||||
Config: node.LocalConfig(),
|
||||
Online: node.Online(),
|
||||
Identity: node.Identity(),
|
||||
InterfaceAddresses: node.InterfaceAddresses(),
|
||||
MappedExternalAddresses: nil,
|
||||
Version: fmt.Sprintf("%d.%d.%d", CoreVersionMajor, CoreVersionMinor, CoreVersionRevision),
|
||||
VersionMajor: CoreVersionMajor,
|
||||
VersionMinor: CoreVersionMinor,
|
||||
VersionRevision: CoreVersionRevision,
|
||||
VersionBuild: CoreVersionBuild,
|
||||
})
|
||||
} else {
|
||||
out.Header().Set("Allow", "GET, HEAD")
|
||||
apiSendObj(out, req, http.StatusMethodNotAllowed, nil)
|
||||
}
|
||||
})
|
||||
|
||||
smux.HandleFunc("/status", func(out http.ResponseWriter, req *http.Request) {
|
||||
smux.HandleFunc("/config", func(out http.ResponseWriter, req *http.Request) {
|
||||
if !apiCheckAuth(out, req, authToken) {
|
||||
return
|
||||
}
|
||||
apiSetStandardHeaders(out)
|
||||
if req.Method == http.MethodGet || req.Method == http.MethodHead {
|
||||
var status apiStatus
|
||||
apiSendObj(out, req, http.StatusOK, &status)
|
||||
if req.Method == http.MethodPost || req.Method == http.MethodPut {
|
||||
var c LocalConfig
|
||||
if apiReadObj(out, req, &c) == nil {
|
||||
apiSendObj(out, req, http.StatusOK, node.LocalConfig())
|
||||
}
|
||||
} else if req.Method == http.MethodGet || req.Method == http.MethodHead {
|
||||
apiSendObj(out, req, http.StatusOK, node.LocalConfig())
|
||||
} else {
|
||||
out.Header().Set("Allow", "GET, HEAD")
|
||||
out.Header().Set("Allow", "GET, HEAD, PUT, POST")
|
||||
apiSendObj(out, req, http.StatusMethodNotAllowed, nil)
|
||||
}
|
||||
})
|
||||
|
||||
smux.HandleFunc("/peer/", func(out http.ResponseWriter, req *http.Request) {
|
||||
if !apiCheckAuth(out, req, authToken) {
|
||||
return
|
||||
}
|
||||
apiSetStandardHeaders(out)
|
||||
|
||||
var queriedID Address
|
||||
if len(req.URL.Path) > 6 {
|
||||
var err error
|
||||
queriedID, err = NewAddressFromString(req.URL.Path[6:])
|
||||
if err != nil {
|
||||
apiSendObj(out, req, http.StatusNotFound, nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if req.Method == http.MethodGet || req.Method == http.MethodHead {
|
||||
peers := node.Peers()
|
||||
apiSendObj(out, req, http.StatusOK, peers)
|
||||
if queriedID != 0 {
|
||||
p2 := make([]*Peer, 0, len(peers))
|
||||
for _, p := range peers {
|
||||
if p.Address == queriedID {
|
||||
p2 = append(p2, p)
|
||||
}
|
||||
}
|
||||
apiSendObj(out, req, http.StatusOK, p2)
|
||||
} else {
|
||||
apiSendObj(out, req, http.StatusOK, peers)
|
||||
}
|
||||
} else {
|
||||
out.Header().Set("Allow", "GET, HEAD")
|
||||
apiSendObj(out, req, http.StatusMethodNotAllowed, nil)
|
||||
@ -117,17 +208,67 @@ func createAPIServer(basePath string, node *Node) (*http.Server, error) {
|
||||
})
|
||||
|
||||
smux.HandleFunc("/network/", func(out http.ResponseWriter, req *http.Request) {
|
||||
if !apiCheckAuth(out, req, authToken) {
|
||||
return
|
||||
}
|
||||
apiSetStandardHeaders(out)
|
||||
if req.Method == http.MethodGet || req.Method == http.MethodHead {
|
||||
networks := node.Networks()
|
||||
apiSendObj(out, req, http.StatusOK, networks)
|
||||
|
||||
var queriedID NetworkID
|
||||
if len(req.URL.Path) > 9 {
|
||||
var err error
|
||||
queriedID, err = NewNetworkIDFromString(req.URL.Path[9:])
|
||||
if err != nil {
|
||||
apiSendObj(out, req, http.StatusNotFound, nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if req.Method == http.MethodPost || req.Method == http.MethodPut {
|
||||
if queriedID == 0 {
|
||||
apiSendObj(out, req, http.StatusBadRequest, nil)
|
||||
}
|
||||
} else if req.Method == http.MethodGet || req.Method == http.MethodHead {
|
||||
if queriedID == 0 { // no queried ID lists all networks
|
||||
networks := node.Networks()
|
||||
apiSendObj(out, req, http.StatusOK, networks)
|
||||
} else {
|
||||
}
|
||||
} else {
|
||||
out.Header().Set("Allow", "GET, HEAD")
|
||||
out.Header().Set("Allow", "GET, HEAD, PUT, POST")
|
||||
apiSendObj(out, req, http.StatusMethodNotAllowed, nil)
|
||||
}
|
||||
})
|
||||
|
||||
unixListener, err := net.Listen("unix", path.Join(basePath, "apisocket"))
|
||||
smux.HandleFunc("/root/", func(out http.ResponseWriter, req *http.Request) {
|
||||
if !apiCheckAuth(out, req, authToken) {
|
||||
return
|
||||
}
|
||||
apiSetStandardHeaders(out)
|
||||
|
||||
var queriedID Address
|
||||
if len(req.URL.Path) > 6 {
|
||||
var err error
|
||||
queriedID, err = NewAddressFromString(req.URL.Path[6:])
|
||||
if err != nil {
|
||||
apiSendObj(out, req, http.StatusNotFound, nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if req.Method == http.MethodPost || req.Method == http.MethodPut {
|
||||
if queriedID == 0 {
|
||||
apiSendObj(out, req, http.StatusBadRequest, nil)
|
||||
}
|
||||
} else if req.Method == http.MethodGet || req.Method == http.MethodHead {
|
||||
roots := node.Roots()
|
||||
apiSendObj(out, req, http.StatusOK, roots)
|
||||
} else {
|
||||
out.Header().Set("Allow", "GET, HEAD, PUT, POST")
|
||||
apiSendObj(out, req, http.StatusMethodNotAllowed, nil)
|
||||
}
|
||||
})
|
||||
|
||||
listener, err := createNamedSocketListener(basePath, "apisocket")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -139,7 +280,10 @@ func createAPIServer(basePath string, node *Node) (*http.Server, error) {
|
||||
WriteTimeout: 600 * time.Second,
|
||||
}
|
||||
httpServer.SetKeepAlivesEnabled(true)
|
||||
go httpServer.Serve(unixListener)
|
||||
go func() {
|
||||
httpServer.Serve(listener)
|
||||
listener.Close()
|
||||
}()
|
||||
|
||||
return httpServer, nil
|
||||
}
|
||||
|
123
go/pkg/zerotier/inetaddress.go
Normal file
123
go/pkg/zerotier/inetaddress.go
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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"
|
||||
"encoding/json"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// InetAddress implements net.Addr but has a ZeroTier-like string representation
|
||||
type InetAddress struct {
|
||||
IP net.IP
|
||||
Port int
|
||||
}
|
||||
|
||||
// Less returns true if this IP/port is lexicographically less than another
|
||||
func (i *InetAddress) Less(i2 *InetAddress) bool {
|
||||
c := bytes.Compare(i.IP, i2.IP)
|
||||
if c < 0 {
|
||||
return true
|
||||
}
|
||||
if c == 0 {
|
||||
return i.Port < i2.Port
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// NewInetAddressFromString parses an IP[/port] format address
|
||||
func NewInetAddressFromString(s string) *InetAddress {
|
||||
i := new(InetAddress)
|
||||
ss := strings.Split(s, "/")
|
||||
if len(ss) > 0 {
|
||||
i.IP = net.ParseIP(ss[0])
|
||||
i4 := i.IP.To4()
|
||||
if len(i4) == 4 { // down-convert IPv4-in-6 IPs to native IPv4 as this is what all our code expects
|
||||
i.IP = i4
|
||||
}
|
||||
if len(ss) > 1 {
|
||||
p64, _ := strconv.ParseUint(s, 10, 64)
|
||||
i.Port = int(p64 & 0xffff)
|
||||
}
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
// NewInetAddressFromSockaddr parses a sockaddr_in or sockaddr_in6 C structure (may crash if given something other than these!)
|
||||
// This is a convenience wrapper around the CGO functions in node.go.
|
||||
func NewInetAddressFromSockaddr(sa unsafe.Pointer) *InetAddress {
|
||||
i := new(InetAddress)
|
||||
if uintptr(sa) != 0 {
|
||||
ua := sockaddrStorageToUDPAddr2(sa)
|
||||
if ua != nil {
|
||||
i.IP = ua.IP
|
||||
i.Port = ua.Port
|
||||
}
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
// Network returns "udp" to implement net.Addr
|
||||
func (i *InetAddress) Network() string {
|
||||
return "udp"
|
||||
}
|
||||
|
||||
// String returns this address in ZeroTier-canonical IP/port format
|
||||
func (i *InetAddress) String() string {
|
||||
return i.IP.String() + "/" + strconv.FormatInt(int64(i.Port), 10)
|
||||
}
|
||||
|
||||
// Family returns the address family (AFInet etc.) or 0 if none
|
||||
func (i *InetAddress) Family() int {
|
||||
switch len(i.IP) {
|
||||
case 4:
|
||||
return AFInet
|
||||
case 16:
|
||||
return AFInet6
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Valid returns true if both the IP and port have valid values
|
||||
func (i *InetAddress) Valid() bool {
|
||||
return (len(i.IP) == 4 || len(i.IP) == 16) && (i.Port > 0 && i.Port < 65536)
|
||||
}
|
||||
|
||||
// MarshalJSON marshals this MAC as a string
|
||||
func (i *InetAddress) MarshalJSON() ([]byte, error) {
|
||||
s := i.String()
|
||||
return json.Marshal(&s)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals this MAC from a string
|
||||
func (i *InetAddress) UnmarshalJSON(j []byte) error {
|
||||
var s string
|
||||
err := json.Unmarshal(j, &s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*i = *NewInetAddressFromString(s)
|
||||
return nil
|
||||
}
|
||||
|
||||
// key returns a short array suitable for use as a map[] key for this IP
|
||||
func (i *InetAddress) key() (k [3]uint64) {
|
||||
copy(((*[16]byte)(unsafe.Pointer(&k[0])))[:], i.IP)
|
||||
k[2] = uint64(i.Port)
|
||||
return
|
||||
}
|
@ -17,42 +17,69 @@ import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
rand "math/rand"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// LocalConfigPhysicalPathConfiguration contains settings for physical paths
|
||||
type LocalConfigPhysicalPathConfiguration struct {
|
||||
Blacklist bool
|
||||
// Blacklist flags this path as unusable for ZeroTier traffic
|
||||
Blacklist bool
|
||||
|
||||
// TrustedPathID identifies a path for unencrypted/unauthenticated traffic
|
||||
TrustedPathID uint64
|
||||
}
|
||||
|
||||
// LocalConfigVirtualAddressConfiguration contains settings for virtual addresses
|
||||
type LocalConfigVirtualAddressConfiguration struct {
|
||||
Try []net.Addr
|
||||
// Try is a list of IPs/ports to try for this peer in addition to anything learned from roots or direct path push
|
||||
Try []*InetAddress
|
||||
}
|
||||
|
||||
// LocalConfigSettings contains node settings
|
||||
type LocalConfigSettings struct {
|
||||
PrimaryPort int
|
||||
SecondaryPort int
|
||||
TertiaryPort int
|
||||
PortMappingEnabled bool
|
||||
MuiltipathMode int
|
||||
// PrimaryPort is the main UDP port and must be set (defaults to 9993)
|
||||
PrimaryPort int
|
||||
|
||||
// SecondaryPort is the secondary UDP port, set to 0 to disbale (picked at random by default)
|
||||
SecondaryPort int
|
||||
|
||||
// TertiaryPort is a third UDP port, set to 0 to disable (picked at random by default)
|
||||
TertiaryPort int
|
||||
|
||||
// PortAutoSearch causes ZeroTier to try other ports automatically if it can't bind to configured ports
|
||||
PortAutoSearch bool
|
||||
|
||||
// PortMappingEnabled enables uPnP and NAT-PMP support
|
||||
PortMappingEnabled bool
|
||||
|
||||
// MultipathMode sets the multipath link aggregation mode
|
||||
MuiltipathMode int
|
||||
|
||||
// InterfacePrefixBlacklist are prefixes of physical network interface names that won't be used by ZeroTier (e.g. "lo" or "utun")
|
||||
InterfacePrefixBlacklist []string
|
||||
|
||||
// ExplicitAddresses are explicit IP/port addresses to advertise to other nodes, such as externally mapped ports on a router
|
||||
ExplicitAddresses []*InetAddress
|
||||
}
|
||||
|
||||
// LocalConfig is the local.conf file and stores local settings for the node.
|
||||
type LocalConfig struct {
|
||||
// Physical path configurations by CIDR IP/bits
|
||||
Physical map[string]*LocalConfigPhysicalPathConfiguration
|
||||
Virtual map[Address]*LocalConfigVirtualAddressConfiguration
|
||||
Network map[NetworkID]*NetworkLocalSettings
|
||||
|
||||
// Virtual node specific configurations by 10-digit hex ZeroTier address
|
||||
Virtual map[Address]*LocalConfigVirtualAddressConfiguration
|
||||
|
||||
// Network local configurations by 16-digit hex ZeroTier network ID
|
||||
Network map[NetworkID]*NetworkLocalSettings
|
||||
|
||||
// LocalConfigSettings contains other local settings for this node
|
||||
Settings LocalConfigSettings
|
||||
}
|
||||
|
||||
// Read this local config from a file, initializing to defaults if the file does not exist
|
||||
func (lc *LocalConfig) Read(p string) error {
|
||||
func (lc *LocalConfig) Read(p string, saveDefaultsIfNotExist bool) error {
|
||||
if lc.Physical == nil {
|
||||
lc.Physical = make(map[string]*LocalConfigPhysicalPathConfiguration)
|
||||
lc.Virtual = make(map[Address]*LocalConfigVirtualAddressConfiguration)
|
||||
@ -60,6 +87,7 @@ func (lc *LocalConfig) Read(p string) error {
|
||||
lc.Settings.PrimaryPort = 9993
|
||||
lc.Settings.SecondaryPort = 16384 + (rand.Int() % 16384)
|
||||
lc.Settings.TertiaryPort = 32768 + (rand.Int() % 16384)
|
||||
lc.Settings.PortAutoSearch = true
|
||||
lc.Settings.PortMappingEnabled = true
|
||||
lc.Settings.MuiltipathMode = 0
|
||||
switch runtime.GOOS {
|
||||
@ -75,10 +103,18 @@ func (lc *LocalConfig) Read(p string) error {
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile(p)
|
||||
if err != nil && err != os.ErrNotExist {
|
||||
return err
|
||||
if err != nil {
|
||||
if err != os.ErrNotExist {
|
||||
return err
|
||||
}
|
||||
if saveDefaultsIfNotExist {
|
||||
err = lc.Write(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return json.Unmarshal(data, lc)
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,9 @@
|
||||
|
||||
package zerotier
|
||||
|
||||
// This wraps the C++ Node implementation, C++ EthernetTap implementations,
|
||||
// and generally contains all the other CGO stuff.
|
||||
|
||||
//#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
|
||||
@ -20,14 +23,17 @@ package zerotier
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
rand "math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@ -61,8 +67,8 @@ const (
|
||||
// PlatformDefaultHomePath is the default location of ZeroTier's working path on this system
|
||||
PlatformDefaultHomePath string = C.GoString(C.ZT_PLATFORM_DEFAULT_HOMEPATH)
|
||||
|
||||
afInet = C.AF_INET
|
||||
afInet6 = C.AF_INET6
|
||||
AFInet = C.AF_INET
|
||||
AFInet6 = C.AF_INET6
|
||||
|
||||
defaultVirtualNetworkMTU = C.ZT_DEFAULT_MTU
|
||||
)
|
||||
@ -75,14 +81,14 @@ var (
|
||||
func sockaddrStorageToIPNet(ss *C.struct_sockaddr_storage) *net.IPNet {
|
||||
var a net.IPNet
|
||||
switch ss.ss_family {
|
||||
case afInet:
|
||||
case AFInet:
|
||||
sa4 := (*C.struct_sockaddr_in)(unsafe.Pointer(ss))
|
||||
var ip4 [4]byte
|
||||
copy(ip4[:], (*[4]byte)(unsafe.Pointer(&sa4.sin_addr))[:])
|
||||
a.IP = net.IP(ip4[:])
|
||||
a.Mask = net.CIDRMask(int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa4.sin_port)))[:])), 32)
|
||||
return &a
|
||||
case afInet6:
|
||||
case AFInet6:
|
||||
sa6 := (*C.struct_sockaddr_in6)(unsafe.Pointer(ss))
|
||||
var ip6 [16]byte
|
||||
copy(ip6[:], (*[16]byte)(unsafe.Pointer(&sa6.sin6_addr))[:])
|
||||
@ -96,14 +102,14 @@ func sockaddrStorageToIPNet(ss *C.struct_sockaddr_storage) *net.IPNet {
|
||||
func sockaddrStorageToUDPAddr(ss *C.struct_sockaddr_storage) *net.UDPAddr {
|
||||
var a net.UDPAddr
|
||||
switch ss.ss_family {
|
||||
case afInet:
|
||||
case AFInet:
|
||||
sa4 := (*C.struct_sockaddr_in)(unsafe.Pointer(ss))
|
||||
var ip4 [4]byte
|
||||
copy(ip4[:], (*[4]byte)(unsafe.Pointer(&sa4.sin_addr))[:])
|
||||
a.IP = net.IP(ip4[:])
|
||||
a.Port = int(binary.BigEndian.Uint16(((*[2]byte)(unsafe.Pointer(&sa4.sin_port)))[:]))
|
||||
return &a
|
||||
case afInet6:
|
||||
case AFInet6:
|
||||
sa6 := (*C.struct_sockaddr_in6)(unsafe.Pointer(ss))
|
||||
var ip6 [16]byte
|
||||
copy(ip6[:], (*[16]byte)(unsafe.Pointer(&sa6.sin6_addr))[:])
|
||||
@ -114,18 +120,22 @@ func sockaddrStorageToUDPAddr(ss *C.struct_sockaddr_storage) *net.UDPAddr {
|
||||
return nil
|
||||
}
|
||||
|
||||
func sockaddrStorageToUDPAddr2(ss unsafe.Pointer) *net.UDPAddr {
|
||||
return sockaddrStorageToUDPAddr((*C.struct_sockaddr_storage)(ss))
|
||||
}
|
||||
|
||||
func makeSockaddrStorage(ip net.IP, port int, ss *C.struct_sockaddr_storage) bool {
|
||||
C.memset(unsafe.Pointer(ss), 0, C.sizeof_struct_sockaddr_storage)
|
||||
if len(ip) == 4 {
|
||||
sa4 := (*C.struct_sockaddr_in)(unsafe.Pointer(ss))
|
||||
sa4.sin_family = afInet
|
||||
sa4.sin_family = AFInet
|
||||
copy(((*[4]byte)(unsafe.Pointer(&sa4.sin_addr)))[:], ip)
|
||||
binary.BigEndian.PutUint16(((*[2]byte)(unsafe.Pointer(&sa4.sin_port)))[:], uint16(port))
|
||||
return true
|
||||
}
|
||||
if len(ip) == 16 {
|
||||
sa6 := (*C.struct_sockaddr_in6)(unsafe.Pointer(ss))
|
||||
sa6.sin6_family = afInet6
|
||||
sa6.sin6_family = AFInet6
|
||||
copy(((*[16]byte)(unsafe.Pointer(&sa6.sin6_addr)))[:], ip)
|
||||
binary.BigEndian.PutUint16(((*[2]byte)(unsafe.Pointer(&sa6.sin6_port)))[:], uint16(port))
|
||||
return true
|
||||
@ -137,26 +147,26 @@ func makeSockaddrStorage(ip net.IP, port int, ss *C.struct_sockaddr_storage) boo
|
||||
|
||||
// Node is an instance of the ZeroTier core node and related C++ I/O code
|
||||
type Node struct {
|
||||
basePath string
|
||||
localConfig LocalConfig
|
||||
networks map[NetworkID]*Network
|
||||
networksByMAC map[MAC]*Network // locked by networksLock
|
||||
externalAddresses map[string]*net.IPNet
|
||||
localConfigLock sync.RWMutex
|
||||
networksLock sync.RWMutex
|
||||
externalAddressesLock sync.Mutex
|
||||
gn *C.ZT_GoNode
|
||||
zn *C.ZT_Node
|
||||
id *Identity
|
||||
online uint32
|
||||
running uint32
|
||||
runLock sync.Mutex
|
||||
basePath string
|
||||
localConfigPath string
|
||||
localConfig LocalConfig
|
||||
networks map[NetworkID]*Network
|
||||
networksByMAC map[MAC]*Network // locked by networksLock
|
||||
interfaceAddresses map[string]net.IP // physical external IPs on the machine
|
||||
localConfigLock sync.RWMutex
|
||||
networksLock sync.RWMutex
|
||||
interfaceAddressesLock sync.Mutex
|
||||
gn *C.ZT_GoNode
|
||||
zn *C.ZT_Node
|
||||
id *Identity
|
||||
apiServer *http.Server
|
||||
online uint32
|
||||
running uint32
|
||||
runLock sync.Mutex
|
||||
}
|
||||
|
||||
// NewNode creates and initializes a new instance of the ZeroTier node service
|
||||
func NewNode(basePath string) (*Node, error) {
|
||||
var err error
|
||||
|
||||
os.MkdirAll(basePath, 0755)
|
||||
if _, err := os.Stat(basePath); err != nil {
|
||||
return nil, err
|
||||
@ -164,9 +174,14 @@ func NewNode(basePath string) (*Node, error) {
|
||||
|
||||
n := new(Node)
|
||||
n.basePath = basePath
|
||||
n.localConfigPath = path.Join(basePath, "local.conf")
|
||||
err := n.localConfig.Read(n.localConfigPath, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
n.networks = make(map[NetworkID]*Network)
|
||||
n.networksByMAC = make(map[MAC]*Network)
|
||||
n.externalAddresses = make(map[string]*net.IPNet)
|
||||
n.interfaceAddresses = make(map[string]net.IP)
|
||||
|
||||
cpath := C.CString(basePath)
|
||||
n.gn = C.ZT_GoNode_new(cpath)
|
||||
@ -184,6 +199,12 @@ func NewNode(basePath string) (*Node, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
n.apiServer, err = createAPIServer(basePath, n)
|
||||
if err != nil {
|
||||
C.ZT_GoNode_delete(n.gn)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gnRawAddr := uintptr(unsafe.Pointer(n.gn))
|
||||
nodesByUserPtrLock.Lock()
|
||||
nodesByUserPtr[gnRawAddr] = n
|
||||
@ -202,7 +223,7 @@ func NewNode(basePath string) (*Node, error) {
|
||||
if (now - lastScannedInterfaces) >= 30000 {
|
||||
lastScannedInterfaces = now
|
||||
|
||||
externalAddresses := make(map[string]*net.IPNet)
|
||||
interfaceAddresses := make(map[string]net.IP)
|
||||
ifs, _ := net.Interfaces()
|
||||
if len(ifs) > 0 {
|
||||
n.networksLock.RLock()
|
||||
@ -214,7 +235,7 @@ func NewNode(basePath string) (*Node, error) {
|
||||
for _, a := range addrs {
|
||||
ipn, _ := a.(*net.IPNet)
|
||||
if ipn != nil {
|
||||
externalAddresses[ipn.String()] = ipn
|
||||
interfaceAddresses[ipn.IP.String()] = ipn.IP
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -224,10 +245,10 @@ func NewNode(basePath string) (*Node, error) {
|
||||
}
|
||||
|
||||
n.localConfigLock.RLock()
|
||||
n.externalAddressesLock.Lock()
|
||||
for astr, ipn := range externalAddresses {
|
||||
if _, alreadyKnown := n.externalAddresses[astr]; !alreadyKnown {
|
||||
ipCstr := C.CString(ipn.IP.String())
|
||||
n.interfaceAddressesLock.Lock()
|
||||
for astr, ipn := range interfaceAddresses {
|
||||
if _, alreadyKnown := n.interfaceAddresses[astr]; !alreadyKnown {
|
||||
ipCstr := C.CString(ipn.String())
|
||||
if n.localConfig.Settings.PrimaryPort > 0 && n.localConfig.Settings.PrimaryPort < 65536 {
|
||||
C.ZT_GoNode_phyStartListen(n.gn, nil, ipCstr, C.int(n.localConfig.Settings.PrimaryPort))
|
||||
}
|
||||
@ -240,9 +261,9 @@ func NewNode(basePath string) (*Node, error) {
|
||||
C.free(unsafe.Pointer(ipCstr))
|
||||
}
|
||||
}
|
||||
for astr, ipn := range n.externalAddresses {
|
||||
if _, stillPresent := externalAddresses[astr]; !stillPresent {
|
||||
ipCstr := C.CString(ipn.IP.String())
|
||||
for astr, ipn := range n.interfaceAddresses {
|
||||
if _, stillPresent := interfaceAddresses[astr]; !stillPresent {
|
||||
ipCstr := C.CString(ipn.String())
|
||||
if n.localConfig.Settings.PrimaryPort > 0 && n.localConfig.Settings.PrimaryPort < 65536 {
|
||||
C.ZT_GoNode_phyStopListen(n.gn, nil, ipCstr, C.int(n.localConfig.Settings.PrimaryPort))
|
||||
}
|
||||
@ -255,8 +276,8 @@ func NewNode(basePath string) (*Node, error) {
|
||||
C.free(unsafe.Pointer(ipCstr))
|
||||
}
|
||||
}
|
||||
n.externalAddresses = externalAddresses
|
||||
n.externalAddressesLock.Unlock()
|
||||
n.interfaceAddresses = interfaceAddresses
|
||||
n.interfaceAddressesLock.Unlock()
|
||||
n.localConfigLock.RUnlock()
|
||||
}
|
||||
}
|
||||
@ -269,6 +290,7 @@ func NewNode(basePath string) (*Node, error) {
|
||||
// Close closes this Node and frees its underlying C++ Node structures
|
||||
func (n *Node) Close() {
|
||||
if atomic.SwapUint32(&n.running, 0) != 0 {
|
||||
n.apiServer.Close()
|
||||
C.ZT_GoNode_delete(n.gn)
|
||||
nodesByUserPtrLock.Lock()
|
||||
delete(nodesByUserPtr, uintptr(unsafe.Pointer(n.gn)))
|
||||
@ -284,6 +306,21 @@ func (n *Node) Address() Address { return n.id.address }
|
||||
// Identity returns this node's identity (including secret portion)
|
||||
func (n *Node) Identity() *Identity { return n.id }
|
||||
|
||||
// Online returns true if this node can reach something
|
||||
func (n *Node) Online() bool { return atomic.LoadUint32(&n.online) != 0 }
|
||||
|
||||
// InterfaceAddresses are external IPs belonging to physical interfaces on this machine
|
||||
func (n *Node) InterfaceAddresses() []net.IP {
|
||||
var ea []net.IP
|
||||
n.interfaceAddressesLock.Lock()
|
||||
for _, a := range n.interfaceAddresses {
|
||||
ea = append(ea, a)
|
||||
}
|
||||
n.interfaceAddressesLock.Unlock()
|
||||
sort.Slice(ea, func(a, b int) bool { return bytes.Compare(ea[a], ea[b]) < 0 })
|
||||
return ea
|
||||
}
|
||||
|
||||
// LocalConfig gets this node's local configuration
|
||||
func (n *Node) LocalConfig() LocalConfig {
|
||||
n.localConfigLock.RLock()
|
||||
@ -396,11 +433,11 @@ func (n *Node) Roots() []*Root {
|
||||
root := (*C.ZT_Root)(unsafe.Pointer(uintptr(unsafe.Pointer(rl)) + C.sizeof_ZT_RootList))
|
||||
id, err := NewIdentityFromString(C.GoString(root.identity))
|
||||
if err == nil {
|
||||
var addrs []net.Addr
|
||||
var addrs []InetAddress
|
||||
for j := uintptr(0); j < uintptr(root.addressCount); j++ {
|
||||
a := sockaddrStorageToUDPAddr((*C.struct_sockaddr_storage)(unsafe.Pointer(uintptr(unsafe.Pointer(root.addresses)) + (j * C.sizeof_struct_sockaddr_storage))))
|
||||
if a != nil {
|
||||
addrs = append(addrs, a)
|
||||
a := NewInetAddressFromSockaddr(unsafe.Pointer(uintptr(unsafe.Pointer(root.addresses)) + (j * C.sizeof_struct_sockaddr_storage)))
|
||||
if a != nil && a.Valid() {
|
||||
addrs = append(addrs, *a)
|
||||
}
|
||||
}
|
||||
roots = append(roots, &Root{
|
||||
@ -488,10 +525,8 @@ func (n *Node) pathLookup(ztAddress Address) (net.IP, int) {
|
||||
defer n.localConfigLock.RUnlock()
|
||||
virt := n.localConfig.Virtual[ztAddress]
|
||||
if virt != nil && len(virt.Try) > 0 {
|
||||
udpA, _ := virt.Try[rand.Int()%len(virt.Try)].(*net.UDPAddr)
|
||||
if udpA != nil {
|
||||
return udpA.IP, udpA.Port
|
||||
}
|
||||
idx := rand.Int() % len(virt.Try)
|
||||
return virt.Try[idx].IP, virt.Try[idx].Port
|
||||
}
|
||||
return nil, 0
|
||||
}
|
||||
@ -521,28 +556,24 @@ func (n *Node) makeStateObjectPath(objType int, id [2]uint64) (string, bool) {
|
||||
}
|
||||
|
||||
func (n *Node) stateObjectPut(objType int, id [2]uint64, data []byte) {
|
||||
go func() {
|
||||
fp, secret := n.makeStateObjectPath(objType, id)
|
||||
if len(fp) > 0 {
|
||||
fileMode := os.FileMode(0644)
|
||||
if secret {
|
||||
fileMode = os.FileMode(0600)
|
||||
}
|
||||
ioutil.WriteFile(fp, data, fileMode)
|
||||
if secret {
|
||||
acl.Chmod(fp, 0600) // this emulates Unix chmod on Windows and uses os.Chmod on Unix-type systems
|
||||
}
|
||||
fp, secret := n.makeStateObjectPath(objType, id)
|
||||
if len(fp) > 0 {
|
||||
fileMode := os.FileMode(0644)
|
||||
if secret {
|
||||
fileMode = os.FileMode(0600)
|
||||
}
|
||||
}()
|
||||
ioutil.WriteFile(fp, data, fileMode)
|
||||
if secret {
|
||||
acl.Chmod(fp, 0600) // this emulates Unix chmod on Windows and uses os.Chmod on Unix-type systems
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Node) stateObjectDelete(objType int, id [2]uint64) {
|
||||
go func() {
|
||||
fp, _ := n.makeStateObjectPath(objType, id)
|
||||
if len(fp) > 0 {
|
||||
os.Remove(fp)
|
||||
}
|
||||
}()
|
||||
fp, _ := n.makeStateObjectPath(objType, id)
|
||||
if len(fp) > 0 {
|
||||
os.Remove(fp)
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Node) stateObjectGet(objType int, id [2]uint64) ([]byte, bool) {
|
||||
@ -592,12 +623,12 @@ func goPathLookupFunc(gn unsafe.Pointer, ztAddress C.uint64_t, desiredAddressFam
|
||||
if len(ip) > 0 && port > 0 && port <= 65535 {
|
||||
ip4 := ip.To4()
|
||||
if len(ip4) == 4 {
|
||||
*((*C.int)(familyP)) = C.int(afInet)
|
||||
*((*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)
|
||||
*((*C.int)(familyP)) = C.int(AFInet6)
|
||||
copy((*[16]byte)(ipP)[:], ip)
|
||||
*((*C.int)(portP)) = C.int(port)
|
||||
return 1
|
||||
@ -609,17 +640,19 @@ func goPathLookupFunc(gn unsafe.Pointer, ztAddress C.uint64_t, desiredAddressFam
|
||||
|
||||
//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))
|
||||
}
|
||||
go func() {
|
||||
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
|
||||
@ -642,17 +675,17 @@ func goStateObjectGetFunc(gn unsafe.Pointer, objType C.int, id, data unsafe.Poin
|
||||
|
||||
//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() {
|
||||
nodesByUserPtrLock.RLock()
|
||||
node := nodesByUserPtr[uintptr(gn)]
|
||||
nodesByUserPtrLock.RUnlock()
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
|
||||
recordTypes := C.GoBytes(dnsRecordTypes, numDNSRecordTypes)
|
||||
recordName := C.GoString((*C.char)(name))
|
||||
|
||||
recordNameCStrCopy := C.CString(recordName)
|
||||
for _, rt := range recordTypes {
|
||||
switch rt {
|
||||
@ -794,12 +827,12 @@ func (t *nativeTap) AddIP(ip *net.IPNet) error {
|
||||
if bits > 128 || bits < 0 {
|
||||
return ErrInvalidParameter
|
||||
}
|
||||
C.ZT_GoTap_addIp(t.tap, C.int(afInet6), unsafe.Pointer(&ip.IP[0]), C.int(bits))
|
||||
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))
|
||||
C.ZT_GoTap_addIp(t.tap, C.int(AFInet), unsafe.Pointer(&ip.IP[0]), C.int(bits))
|
||||
}
|
||||
return ErrInvalidParameter
|
||||
}
|
||||
@ -811,14 +844,14 @@ func (t *nativeTap) RemoveIP(ip *net.IPNet) error {
|
||||
if bits > 128 || bits < 0 {
|
||||
return ErrInvalidParameter
|
||||
}
|
||||
C.ZT_GoTap_removeIp(t.tap, C.int(afInet6), unsafe.Pointer(&ip.IP[0]), C.int(bits))
|
||||
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))
|
||||
C.ZT_GoTap_removeIp(t.tap, C.int(AFInet), unsafe.Pointer(&ip.IP[0]), C.int(bits))
|
||||
return nil
|
||||
}
|
||||
return ErrInvalidParameter
|
||||
@ -839,7 +872,7 @@ func (t *nativeTap) IPs() (ips []net.IPNet, err error) {
|
||||
af := int(ipbuf[ipptr])
|
||||
ipptr++
|
||||
switch af {
|
||||
case afInet:
|
||||
case AFInet:
|
||||
var ip [4]byte
|
||||
for j := 0; j < 4; j++ {
|
||||
ip[j] = ipbuf[ipptr]
|
||||
@ -848,7 +881,7 @@ func (t *nativeTap) IPs() (ips []net.IPNet, err error) {
|
||||
bits := ipbuf[ipptr]
|
||||
ipptr++
|
||||
ips = append(ips, net.IPNet{IP: net.IP(ip[:]), Mask: net.CIDRMask(int(bits), 32)})
|
||||
case afInet6:
|
||||
case AFInet6:
|
||||
var ip [16]byte
|
||||
for j := 0; j < 16; j++ {
|
||||
ip[j] = ipbuf[ipptr]
|
||||
@ -888,16 +921,16 @@ func (t *nativeTap) AddRoute(r *Route) error {
|
||||
if len(r.Target.IP) == 4 {
|
||||
mask, _ := r.Target.Mask.Size()
|
||||
if len(r.Via) == 4 {
|
||||
rc = int(C.ZT_GoTap_addRoute(t.tap, afInet, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), afInet, unsafe.Pointer(&r.Via[0]), C.uint(r.Metric)))
|
||||
rc = int(C.ZT_GoTap_addRoute(t.tap, AFInet, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), AFInet, unsafe.Pointer(&r.Via[0]), C.uint(r.Metric)))
|
||||
} else {
|
||||
rc = int(C.ZT_GoTap_addRoute(t.tap, afInet, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), 0, nil, C.uint(r.Metric)))
|
||||
rc = int(C.ZT_GoTap_addRoute(t.tap, AFInet, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), 0, nil, C.uint(r.Metric)))
|
||||
}
|
||||
} else if len(r.Target.IP) == 16 {
|
||||
mask, _ := r.Target.Mask.Size()
|
||||
if len(r.Via) == 4 {
|
||||
rc = int(C.ZT_GoTap_addRoute(t.tap, afInet6, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), afInet6, unsafe.Pointer(&r.Via[0]), C.uint(r.Metric)))
|
||||
rc = int(C.ZT_GoTap_addRoute(t.tap, AFInet6, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), AFInet6, unsafe.Pointer(&r.Via[0]), C.uint(r.Metric)))
|
||||
} else {
|
||||
rc = int(C.ZT_GoTap_addRoute(t.tap, afInet6, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), 0, nil, C.uint(r.Metric)))
|
||||
rc = int(C.ZT_GoTap_addRoute(t.tap, AFInet6, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), 0, nil, C.uint(r.Metric)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -914,16 +947,16 @@ func (t *nativeTap) RemoveRoute(r *Route) error {
|
||||
if len(r.Target.IP) == 4 {
|
||||
mask, _ := r.Target.Mask.Size()
|
||||
if len(r.Via) == 4 {
|
||||
rc = int(C.ZT_GoTap_removeRoute(t.tap, afInet, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), afInet, unsafe.Pointer(&r.Via[0]), C.uint(r.Metric)))
|
||||
rc = int(C.ZT_GoTap_removeRoute(t.tap, AFInet, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), AFInet, unsafe.Pointer(&r.Via[0]), C.uint(r.Metric)))
|
||||
} else {
|
||||
rc = int(C.ZT_GoTap_removeRoute(t.tap, afInet, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), 0, nil, C.uint(r.Metric)))
|
||||
rc = int(C.ZT_GoTap_removeRoute(t.tap, AFInet, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), 0, nil, C.uint(r.Metric)))
|
||||
}
|
||||
} else if len(r.Target.IP) == 16 {
|
||||
mask, _ := r.Target.Mask.Size()
|
||||
if len(r.Via) == 4 {
|
||||
rc = int(C.ZT_GoTap_removeRoute(t.tap, afInet6, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), afInet6, unsafe.Pointer(&r.Via[0]), C.uint(r.Metric)))
|
||||
rc = int(C.ZT_GoTap_removeRoute(t.tap, AFInet6, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), AFInet6, unsafe.Pointer(&r.Via[0]), C.uint(r.Metric)))
|
||||
} else {
|
||||
rc = int(C.ZT_GoTap_removeRoute(t.tap, afInet6, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), 0, nil, C.uint(r.Metric)))
|
||||
rc = int(C.ZT_GoTap_removeRoute(t.tap, AFInet6, unsafe.Pointer(&r.Target.IP[0]), C.int(mask), 0, nil, C.uint(r.Metric)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -933,12 +966,6 @@ func (t *nativeTap) RemoveRoute(r *Route) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SyncRoutes synchronizes managed routes
|
||||
func (t *nativeTap) SyncRoutes() error {
|
||||
C.ZT_GoTap_syncRoutes(t.tap)
|
||||
return nil
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
func handleTapMulticastGroupChange(gn unsafe.Pointer, nwid, mac C.uint64_t, adi C.uint32_t, added bool) {
|
||||
|
28
go/pkg/zerotier/osdep-posix.go
Normal file
28
go/pkg/zerotier/osdep-posix.go
Normal file
@ -0,0 +1,28 @@
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
* 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"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
func createNamedSocketListener(basePath, name string) (net.Listener, error) {
|
||||
apiSockPath := path.Join(basePath, name)
|
||||
os.Remove(apiSockPath)
|
||||
return net.Listen("unix", apiSockPath)
|
||||
}
|
28
go/pkg/zerotier/osdep-windows.go
Normal file
28
go/pkg/zerotier/osdep-windows.go
Normal file
@ -0,0 +1,28 @@
|
||||
// +build windows
|
||||
|
||||
/*
|
||||
* 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"
|
||||
|
||||
winio "github.com/Microsoft/go-winio"
|
||||
)
|
||||
|
||||
const windowsAPISocketPathPrefix = "\\\\.\\pipe\\zerotier_"
|
||||
|
||||
func createNamedSocketListener(basePath, name string) (net.Listener, error) {
|
||||
winio.ListenPipe(windowsAPISocketPathPrefix+name, nil)
|
||||
}
|
@ -13,13 +13,14 @@
|
||||
|
||||
package zerotier
|
||||
|
||||
import "net"
|
||||
|
||||
// Root describes a root server used to find and establish communication with other nodes.
|
||||
type Root struct {
|
||||
DNSName string
|
||||
Identity *Identity
|
||||
Addresses []net.Addr
|
||||
Addresses []InetAddress
|
||||
Preferred bool
|
||||
Online bool
|
||||
}
|
||||
|
||||
// Static returns true if this is a static root
|
||||
func (r *Root) Static() bool { return len(r.DNSName) == 0 }
|
||||
|
@ -28,5 +28,4 @@ type Tap interface {
|
||||
AddMulticastGroupChangeHandler(func(bool, *MulticastGroup))
|
||||
AddRoute(r *Route) error
|
||||
RemoveRoute(r *Route) error
|
||||
SyncRoutes() error
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user