mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 20:13:44 +02:00
Move some toString/fromString to C++ since any ZT code base would need it, and stub out the controller commands.
This commit is contained in:
parent
a5390b1bc8
commit
1970dab13d
17 changed files with 414 additions and 67 deletions
17
go/cmd/zerotier/cli/controller.go
Normal file
17
go/cmd/zerotier/cli/controller.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c)2013-2020 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2024-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
package cli
|
||||
|
||||
func Controller(basePath, authToken string, args []string, jsonOutput bool) {
|
||||
}
|
|
@ -18,7 +18,6 @@ import (
|
|||
"zerotier/pkg/zerotier"
|
||||
)
|
||||
|
||||
// Help dumps help to stdout
|
||||
func Help() {
|
||||
fmt.Printf(`ZeroTier Network Hypervisor Service Version %d.%d.%d
|
||||
(c)2013-2020 ZeroTier, Inc.
|
||||
|
@ -38,11 +37,11 @@ Commands:
|
|||
service Start as service
|
||||
status Show node status, identity, and config
|
||||
peers List all VL1 peers
|
||||
join <network ID> [fingerprint] Join a virtual network
|
||||
leave <network ID> Leave a virtual network
|
||||
join <network> [fingerprint] Join a virtual network
|
||||
leave <network> Leave a virtual network
|
||||
networks List VL2 virtual networks
|
||||
network <network ID> Show verbose network info
|
||||
set <network ID> [option] [value] Get or set a network config option
|
||||
network <network> Show verbose network info
|
||||
set <network> [option] [value] Get or set a network config option
|
||||
manageips <boolean> Is IP management allowed?
|
||||
manageroutes <boolean> Is route management allowed?
|
||||
globalips <boolean> Allow assignment of global IPs?
|
||||
|
@ -62,11 +61,20 @@ Commands:
|
|||
verify <identity> <file> <sig> Verify a signature
|
||||
locator <command> [args] Locator management commands
|
||||
new <identity> <address> [...] Create and sign a new locator
|
||||
show <locator> [<identity>] Show locator information
|
||||
roots List root peers
|
||||
addroot <identity> <locator> Add a root or update its locator
|
||||
addroot <url> Add or update roots from a URL
|
||||
removeroot <address> Remove a peer from the root list
|
||||
show <locator> [identity] Show locator information
|
||||
root [command] Root management commands
|
||||
list List root peers (same as no command)
|
||||
add <identity> <locator> Add or manually update a root
|
||||
add <url> Add or update root(s) from a URL
|
||||
remove <address> Un-designate a peer as a root
|
||||
controller <command> [option] Local controller management commands
|
||||
networks List networks run by local controller
|
||||
new Create a new network
|
||||
set <network> [setting] [value] Show or modify network settings
|
||||
members <network> List members of a network
|
||||
member <network> [setting] [value] Show or modify member level settings
|
||||
auth <address|fingerprint> Authorize a peer
|
||||
deauth <address|fingerprint> Deauthorize a peer
|
||||
|
||||
The 'service' command does not exit until the service receives a signal.
|
||||
This is typically run from launchd (Mac), systemd or init (Linux), a Windows
|
||||
|
@ -78,6 +86,5 @@ node.
|
|||
|
||||
Identities can be specified verbatim on the command line or as a path to
|
||||
a file. This is detected automatically.
|
||||
|
||||
`,zerotier.CoreVersionMajor, zerotier.CoreVersionMinor, zerotier.CoreVersionRevision)
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import (
|
|||
"zerotier/pkg/zerotier"
|
||||
)
|
||||
|
||||
// Identity command
|
||||
func Identity(args []string) {
|
||||
if len(args) > 0 {
|
||||
switch args[0] {
|
||||
|
|
83
go/cmd/zerotier/cli/locator.go
Normal file
83
go/cmd/zerotier/cli/locator.go
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (c)2013-2020 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2024-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
"zerotier/pkg/zerotier"
|
||||
)
|
||||
|
||||
func Locator(args []string) {
|
||||
if len(args) > 0 {
|
||||
switch args[0] {
|
||||
|
||||
case "new":
|
||||
if len(args) >= 3 {
|
||||
id := readIdentity(args[1])
|
||||
if !id.HasPrivate() {
|
||||
fmt.Println("ERROR: identity is missing private key and can't be used to sign a locator.")
|
||||
os.Exit(1)
|
||||
}
|
||||
var eps []zerotier.Endpoint
|
||||
for i:=2;i<len(args);i++ {
|
||||
ep, _ := zerotier.NewEndpointFromString(args[i])
|
||||
if ep != nil {
|
||||
eps = append(eps, *ep)
|
||||
}
|
||||
}
|
||||
loc, err := zerotier.NewLocator(zerotier.TimeMs(),eps,id)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: unable to create or sign locator: %s\n",err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println(loc.String())
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
case "show":
|
||||
if len(args) > 1 && len(args) < 4 {
|
||||
loc := readLocator(args[1])
|
||||
var id *zerotier.Identity
|
||||
if len(args) == 3 {
|
||||
id = readIdentity(args[2])
|
||||
}
|
||||
ts, fp, eps, valid, _ := loc.GetInfo(id)
|
||||
fmt.Printf("%s\n Timestamp: %s (%d)\n Validity: ",fp.String(),time.Unix(ts / 1000,ts * 1000).String(),ts)
|
||||
if id == nil {
|
||||
fmt.Printf("(no identity provided)\n")
|
||||
} else {
|
||||
if valid {
|
||||
fmt.Printf("SIGNATURE VERIFIED\n")
|
||||
} else {
|
||||
fmt.Printf("! INVALID SIGNATURE\n")
|
||||
}
|
||||
}
|
||||
fmt.Print(" Endpoints: ")
|
||||
for i := range eps {
|
||||
if i > 0 {
|
||||
fmt.Print(" ")
|
||||
}
|
||||
fmt.Print(eps[i].String())
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Help()
|
||||
os.Exit(1)
|
||||
}
|
|
@ -99,23 +99,43 @@ func readIdentity(s string) *zerotier.Identity {
|
|||
}
|
||||
idData, err := ioutil.ReadFile(s)
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: identity '%s' cannot be resolved as file or literal identity: %s", s, err.Error())
|
||||
fmt.Printf("FATAL: identity '%s' cannot be parsed as file or literal: %s", s, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
id, err := zerotier.NewIdentityFromString(string(idData))
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: identity '%s' cannot be resolved as file or literal identity: %s", s, err.Error())
|
||||
fmt.Printf("FATAL: identity '%s' cannot be parsed as file or literal: %s", s, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
func readLocator(s string) *zerotier.Locator {
|
||||
if strings.ContainsRune(s, '@') {
|
||||
loc, _ := zerotier.NewLocatorFromString(s)
|
||||
if loc != nil {
|
||||
return loc
|
||||
}
|
||||
}
|
||||
locData, err := ioutil.ReadFile(s)
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: locator '%s' cannot be parsed as file or literal: %s", s, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
loc, err := zerotier.NewLocatorFromString(string(locData))
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: locator '%s' cannot be parsed as file or literal: %s", s, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
return loc
|
||||
}
|
||||
|
||||
func networkStatusStr(status int) string {
|
||||
switch status {
|
||||
case zerotier.NetworkStatusNotFound:
|
||||
return "NOTFOUND"
|
||||
case zerotier.NetworkStatusAccessDenied:
|
||||
return "DENIED"
|
||||
return "ACCESSDENIED"
|
||||
case zerotier.NetworkStatusRequestConfiguration:
|
||||
return "UPDATING"
|
||||
case zerotier.NetworkStatusOK:
|
||||
|
|
|
@ -21,7 +21,6 @@ import (
|
|||
"zerotier/pkg/zerotier"
|
||||
)
|
||||
|
||||
// Network CLI command
|
||||
func Network(basePath, authToken string, args []string, jsonOutput bool) {
|
||||
if len(args) != 1 {
|
||||
Help()
|
||||
|
|
17
go/cmd/zerotier/cli/root.go
Normal file
17
go/cmd/zerotier/cli/root.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c)2013-2020 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2024-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
package cli
|
||||
|
||||
func Root(basePath, authToken string, args []string, jsonOutput bool) {
|
||||
}
|
|
@ -127,13 +127,6 @@ func main() {
|
|||
case "peers", "listpeers", "lspeers":
|
||||
authTokenRequired(authToken)
|
||||
cli.Peers(basePath, authToken, cmdArgs, *jflag, false)
|
||||
case "roots", "listroots", "lsroots":
|
||||
authTokenRequired(authToken)
|
||||
cli.Peers(basePath, authToken, cmdArgs, *jflag, true)
|
||||
case "addroot":
|
||||
// TODO
|
||||
case "removeroot":
|
||||
// TODO
|
||||
case "join":
|
||||
authTokenRequired(authToken)
|
||||
cli.Join(basePath, authToken, cmdArgs)
|
||||
|
@ -151,8 +144,19 @@ func main() {
|
|||
cli.Set(basePath, authToken, cmdArgs)
|
||||
case "identity":
|
||||
cli.Identity(cmdArgs)
|
||||
case "locator":
|
||||
cli.Locator(cmdArgs)
|
||||
case "root":
|
||||
authTokenRequired(authToken)
|
||||
cli.Root(basePath, authToken, cmdArgs, *jflag)
|
||||
case "controller":
|
||||
authTokenRequired(authToken)
|
||||
cli.Controller(basePath, authToken, cmdArgs, *jflag)
|
||||
}
|
||||
|
||||
// Commands in the 'cli' sub-package do not return, so if we make
|
||||
// it here the command was not recognized.
|
||||
|
||||
cli.Help()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
|
@ -5,11 +5,12 @@ package zerotier
|
|||
// static inline uint64_t _getAddress(const ZT_Endpoint *ep) { return ep->value.fp.address; }
|
||||
// static inline uint64_t _getMAC(const ZT_Endpoint *ep) { return ep->value.mac; }
|
||||
// static inline const struct sockaddr_storage *_getSS(const ZT_Endpoint *ep) { return &(ep->value.ss); }
|
||||
// static inline void _setSS(ZT_Endpoint *ep,const void *ss) { memcpy(&(ep->value.ss),ss,sizeof(struct sockaddr_storage)); }
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
|
@ -29,6 +30,42 @@ type Endpoint struct {
|
|||
cep C.ZT_Endpoint
|
||||
}
|
||||
|
||||
// NewEndpointFromString constructs a new endpoint from an InetAddress or Endpoint string.
|
||||
// This will auto detect whether this is a plain InetAddress or an Endpoint in string
|
||||
// format. If the former it's created as a ZT_ENDPOINT_TYPE_IP_UDP endpoint.
|
||||
func NewEndpointFromString(s string) (*Endpoint, error) {
|
||||
if len(s) == 0 {
|
||||
var ep Endpoint
|
||||
ep.cep._type = C.ZT_ENDPOINT_TYPE_NIL
|
||||
return &ep, nil
|
||||
}
|
||||
if strings.IndexRune(s, '-') > 0 || (strings.IndexRune(s, ':') < 0 && strings.IndexRune(s, '.') < 0) {
|
||||
var ep Endpoint
|
||||
cs := C.CString(s)
|
||||
defer C.free(cs)
|
||||
if C.ZT_Endpoint_fromString(cs) == nil {
|
||||
return nil, ErrInvalidParameter
|
||||
}
|
||||
return &ep, nil
|
||||
}
|
||||
inaddr := NewInetAddressFromString(s)
|
||||
if inaddr == nil {
|
||||
return nil, ErrInvalidParameter
|
||||
}
|
||||
return NewEndpointFromInetAddress(inaddr)
|
||||
}
|
||||
|
||||
func NewEndpointFromInetAddress(addr *InetAddress) (*Endpoint, error) {
|
||||
var ep Endpoint
|
||||
var ss C.struct_sockaddr_storage
|
||||
if !makeSockaddrStorage(addr.IP, addr.Port, &ss) {
|
||||
return nil, ErrInvalidParameter
|
||||
}
|
||||
ep.cep._type = C.ZT_ENDPOINT_TYPE_IP_UDP
|
||||
C._setSS(&ep.cep, unsafe.Pointer(&ss))
|
||||
return &ep, nil
|
||||
}
|
||||
|
||||
// Type returns this endpoint's type.
|
||||
func (ep *Endpoint) Type() int {
|
||||
return int(ep.cep._type)
|
||||
|
@ -77,15 +114,12 @@ func (ep *Endpoint) MAC() MAC {
|
|||
}
|
||||
|
||||
func (ep *Endpoint) String() string {
|
||||
switch ep.cep._type {
|
||||
case EndpointTypeZeroTier:
|
||||
return fmt.Sprintf("%d/%s", ep.Type(), ep.Fingerprint().String())
|
||||
case EndpointTypeEthernet, EndpointTypeWifiDirect, EndpointTypeBluetooth:
|
||||
return fmt.Sprintf("%d/%s", ep.Type(), ep.MAC().String())
|
||||
case EndpointTypeIp, EndpointTypeIpUdp, EndpointTypeIpTcp, EndpointTypeIpHttp2:
|
||||
return fmt.Sprintf("%d/%s", ep.Type(), ep.InetAddress().String())
|
||||
var buf [4096]byte
|
||||
cs := C.ZT_Endpoint_toString(&ep.cep,unsafe.Pointer(&buf[0]),4096)
|
||||
if cs == nil {
|
||||
return "0"
|
||||
}
|
||||
return fmt.Sprintf("%d", ep.Type())
|
||||
return C.GoString(cs)
|
||||
}
|
||||
|
||||
func (ep *Endpoint) MarshalJSON() ([]byte, error) {
|
||||
|
@ -94,6 +128,15 @@ func (ep *Endpoint) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
func (ep *Endpoint) UnmarshalJSON(j []byte) error {
|
||||
// TODO
|
||||
var s string
|
||||
err := json.Unmarshal(j, &s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ep2, err := NewEndpointFromString(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*ep = *ep2
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ func NewFingerprintFromString(fps string) (*Fingerprint, error) {
|
|||
if len(fps) < AddressStringLength {
|
||||
return nil, ErrInvalidZeroTierAddress
|
||||
}
|
||||
ss := strings.Split(fps, "/")
|
||||
ss := strings.Split(fps, "-")
|
||||
if len(ss) < 1 || len(ss) > 2 {
|
||||
return nil, ErrInvalidParameter
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ func newFingerprintFromCFingerprint(cfp *C.ZT_Fingerprint) *Fingerprint {
|
|||
|
||||
func (fp *Fingerprint) String() string {
|
||||
if len(fp.Hash) == 48 {
|
||||
return fmt.Sprintf("%.10x/%s", uint64(fp.Address), Base32StdLowerCase.EncodeToString(fp.Hash))
|
||||
return fmt.Sprintf("%.10x-%s", uint64(fp.Address), Base32StdLowerCase.EncodeToString(fp.Hash))
|
||||
}
|
||||
return fp.Address.String()
|
||||
}
|
||||
|
|
|
@ -64,9 +64,26 @@ func NewLocatorFromBytes(lb []byte) (*Locator, error) {
|
|||
return goloc, nil
|
||||
}
|
||||
|
||||
func NewLocatorFromString(s string) (*Locator, error) {
|
||||
if len(s) == 0 {
|
||||
return nil, ErrInvalidParameter
|
||||
}
|
||||
sb := []byte(s)
|
||||
sb = append(sb,0)
|
||||
loc := C.ZT_Locator_fromString(unsafe.Pointer(&sb[0]))
|
||||
if uintptr(loc) == 0 {
|
||||
return nil, ErrInvalidParameter
|
||||
}
|
||||
goloc := new(Locator)
|
||||
goloc.cl = unsafe.Pointer(loc)
|
||||
runtime.SetFinalizer(goloc, locatorFinalizer)
|
||||
return goloc, nil
|
||||
}
|
||||
|
||||
// GetInfo gets information about this locator, also validating its signature if 'id' is non-nil.
|
||||
// If 'id' is nil the 'valid' return value is undefined.
|
||||
func (loc *Locator) GetInfo(id *Identity) (fp *Fingerprint, eps []Endpoint, valid bool, err error) {
|
||||
func (loc *Locator) GetInfo(id *Identity) (ts int64, fp *Fingerprint, eps []Endpoint, valid bool, err error) {
|
||||
ts = int64(C.ZT_Locator_timestamp(loc.cl))
|
||||
cfp := C.ZT_Locator_fingerprint(loc.cl)
|
||||
if uintptr(unsafe.Pointer(cfp)) == 0 {
|
||||
err = ErrInternal
|
||||
|
@ -84,3 +101,14 @@ func (loc *Locator) GetInfo(id *Identity) (fp *Fingerprint, eps []Endpoint, vali
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (loc *Locator) String() string {
|
||||
var buf [4096]byte
|
||||
C.ZT_Locator_toString(loc.cl,unsafe.Pointer(&buf[0]),4096)
|
||||
for i:=range buf {
|
||||
if buf[i] == 0 {
|
||||
return string(buf[0:i])
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
|
|
@ -2123,6 +2123,17 @@ ZT_SDK_API void ZT_Identity_delete(ZT_Identity *id);
|
|||
|
||||
/* ---------------------------------------------------------------------------------------------------------------- */
|
||||
|
||||
ZT_SDK_API char *ZT_Endpoint_toString(
|
||||
const ZT_Endpoint *ep,
|
||||
char *buf,
|
||||
int capacity);
|
||||
|
||||
ZT_SDK_API int ZT_Endpoint_fromString(
|
||||
ZT_Endpoint *ep,
|
||||
const char *str);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Create and sign a new locator
|
||||
*
|
||||
|
@ -2149,6 +2160,14 @@ ZT_SDK_API ZT_Locator *ZT_Locator_unmarshal(
|
|||
const void *data,
|
||||
unsigned int len);
|
||||
|
||||
/**
|
||||
* Decode a locator from string format
|
||||
*
|
||||
* @param str String format locator
|
||||
* @return Locator or NULL if string is not valid
|
||||
*/
|
||||
ZT_SDK_API ZT_Locator *ZT_Locator_fromString(const char *str);
|
||||
|
||||
/**
|
||||
* Serialize this locator into a buffer
|
||||
*
|
||||
|
@ -2159,6 +2178,19 @@ ZT_SDK_API ZT_Locator *ZT_Locator_unmarshal(
|
|||
*/
|
||||
ZT_SDK_API int ZT_Locator_marshal(const ZT_Locator *loc,void *buf,unsigned int bufSize);
|
||||
|
||||
/**
|
||||
* Get this locator in string format
|
||||
*
|
||||
* @param loc Locator
|
||||
* @param buf Buffer to store string
|
||||
* @param capacity Capacity of buffer in bytes (recommended size: 4096)
|
||||
* @return Pointer to buffer or NULL if an error occurs
|
||||
*/
|
||||
ZT_SDK_API char *ZT_Locator_toString(
|
||||
const ZT_Locator *loc,
|
||||
char *buf,
|
||||
int capacity);
|
||||
|
||||
/**
|
||||
* Get a pointer to the fingerprint of this locator's signer.
|
||||
*
|
||||
|
@ -2169,6 +2201,14 @@ ZT_SDK_API int ZT_Locator_marshal(const ZT_Locator *loc,void *buf,unsigned int b
|
|||
*/
|
||||
ZT_SDK_API const ZT_Fingerprint *ZT_Locator_fingerprint(const ZT_Locator *loc);
|
||||
|
||||
/**
|
||||
* Get a locator's timestamp
|
||||
*
|
||||
* @param loc Locator to query
|
||||
* @return Locator timestamp in milliseconds since epoch
|
||||
*/
|
||||
ZT_SDK_API int64_t ZT_Locator_timestamp(const ZT_Locator *loc);
|
||||
|
||||
/**
|
||||
* Get the number of endpoints in this locator
|
||||
*
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
namespace ZeroTier {
|
||||
|
||||
void Endpoint::toString(char s[ZT_ENDPOINT_STRING_SIZE_MAX]) const noexcept
|
||||
char *Endpoint::toString(char s[ZT_ENDPOINT_STRING_SIZE_MAX]) const noexcept
|
||||
{
|
||||
static const char *const s_endpointTypeChars = ZT_ENDPOINT_TYPE_CHAR_INDEX;
|
||||
|
||||
|
@ -30,14 +30,14 @@ void Endpoint::toString(char s[ZT_ENDPOINT_STRING_SIZE_MAX]) const noexcept
|
|||
break;
|
||||
case ZT_ENDPOINT_TYPE_ZEROTIER:
|
||||
s[0] = s_endpointTypeChars[ZT_ENDPOINT_TYPE_ZEROTIER];
|
||||
s[1] = '/';
|
||||
s[1] = '-';
|
||||
zt().toString(s + 2);
|
||||
break;
|
||||
case ZT_ENDPOINT_TYPE_ETHERNET:
|
||||
case ZT_ENDPOINT_TYPE_WIFI_DIRECT:
|
||||
case ZT_ENDPOINT_TYPE_BLUETOOTH:
|
||||
s[0] = s_endpointTypeChars[this->type];
|
||||
s[1] = '/';
|
||||
s[1] = '-';
|
||||
eth().toString(s + 2);
|
||||
break;
|
||||
case ZT_ENDPOINT_TYPE_IP:
|
||||
|
@ -45,10 +45,12 @@ void Endpoint::toString(char s[ZT_ENDPOINT_STRING_SIZE_MAX]) const noexcept
|
|||
case ZT_ENDPOINT_TYPE_IP_TCP:
|
||||
case ZT_ENDPOINT_TYPE_IP_HTTP2:
|
||||
s[0] = s_endpointTypeChars[this->type];
|
||||
s[1] = '/';
|
||||
s[1] = '-';
|
||||
ip().toString(s + 2);
|
||||
break;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
bool Endpoint::fromString(const char *s) noexcept
|
||||
|
@ -57,7 +59,7 @@ bool Endpoint::fromString(const char *s) noexcept
|
|||
if ((!s) || (!*s))
|
||||
return true;
|
||||
|
||||
const char *start = strchr(s, '/');
|
||||
const char *start = strchr(s, '-');
|
||||
if (start) {
|
||||
char tmp[16];
|
||||
for (unsigned int i = 0;i < 15;++i) {
|
||||
|
@ -248,3 +250,26 @@ bool Endpoint::operator<(const Endpoint &ep) const noexcept
|
|||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
extern "C" {
|
||||
|
||||
char *ZT_Endpoint_toString(
|
||||
const ZT_Endpoint *ep,
|
||||
char *buf,
|
||||
int capacity)
|
||||
{
|
||||
if ((!ep) || (!buf) || (capacity < ZT_ENDPOINT_STRING_SIZE_MAX))
|
||||
return nullptr;
|
||||
return reinterpret_cast<const ZeroTier::Endpoint *>(ep)->toString(buf);
|
||||
}
|
||||
|
||||
int ZT_Endpoint_fromString(
|
||||
ZT_Endpoint *ep,
|
||||
const char *str)
|
||||
{
|
||||
if ((!ep) || (!str))
|
||||
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
return reinterpret_cast<ZeroTier::Endpoint *>(ep)->fromString(str) ? ZT_RESULT_OK : ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
} // C API
|
||||
|
|
|
@ -147,14 +147,9 @@ public:
|
|||
ZT_INLINE Fingerprint zt() const noexcept
|
||||
{ return Fingerprint(this->value.fp); }
|
||||
|
||||
void toString(char s[ZT_ENDPOINT_STRING_SIZE_MAX]) const noexcept;
|
||||
char *toString(char s[ZT_ENDPOINT_STRING_SIZE_MAX]) const noexcept;
|
||||
|
||||
ZT_INLINE String toString() const
|
||||
{
|
||||
char tmp[ZT_ENDPOINT_STRING_SIZE_MAX];
|
||||
toString(tmp);
|
||||
return String(tmp);
|
||||
}
|
||||
ZT_INLINE String toString() const { char tmp[ZT_ENDPOINT_STRING_SIZE_MAX]; return String(toString(tmp)); }
|
||||
|
||||
bool fromString(const char *s) noexcept;
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ public:
|
|||
{
|
||||
Address(this->address).toString(s);
|
||||
if (haveHash()) {
|
||||
s[ZT_ADDRESS_LENGTH_HEX] = '/';
|
||||
s[ZT_ADDRESS_LENGTH_HEX] = '-';
|
||||
Utils::b32e(this->hash, ZT_FINGERPRINT_HASH_SIZE, s + (ZT_ADDRESS_LENGTH_HEX + 1), ZT_FINGERPRINT_STRING_SIZE_MAX - (ZT_ADDRESS_LENGTH_HEX + 1));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,10 +53,33 @@ bool Locator::verify(const Identity &id) const noexcept
|
|||
const unsigned int signlen = marshal(signdata, true);
|
||||
return id.verify(signdata, signlen, m_signature.data(), m_signature.size());
|
||||
}
|
||||
} catch ( ... ) {} // fail verify on any unexpected exception
|
||||
} catch (...) {} // fail verify on any unexpected exception
|
||||
return false;
|
||||
}
|
||||
|
||||
char *Locator::toString(char s[ZT_LOCATOR_STRING_SIZE_MAX]) const noexcept
|
||||
{
|
||||
static_assert(ZT_LOCATOR_STRING_SIZE_MAX > ((((ZT_LOCATOR_MARSHAL_SIZE_MAX / 5) + 1) * 8) + ZT_ADDRESS_LENGTH_HEX + 1), "overflow");
|
||||
uint8_t bin[ZT_LOCATOR_MARSHAL_SIZE_MAX];
|
||||
Address(m_signer.address).toString(s);
|
||||
s[ZT_ADDRESS_LENGTH_HEX] = '@';
|
||||
Utils::b32e(bin, marshal(bin, false), s + (ZT_ADDRESS_LENGTH_HEX + 1), ZT_LOCATOR_STRING_SIZE_MAX - (ZT_ADDRESS_LENGTH_HEX + 1));
|
||||
return s;
|
||||
}
|
||||
|
||||
bool Locator::fromString(const char *s) noexcept
|
||||
{
|
||||
if (!s)
|
||||
return false;
|
||||
if (strlen(s) < (ZT_ADDRESS_LENGTH_HEX + 1))
|
||||
return false;
|
||||
uint8_t bin[ZT_LOCATOR_MARSHAL_SIZE_MAX];
|
||||
const int bl = Utils::b32d(s + (ZT_ADDRESS_LENGTH_HEX + 1), bin, ZT_LOCATOR_MARSHAL_SIZE_MAX);
|
||||
if ((bl <= 0) || (bl > ZT_LOCATOR_MARSHAL_SIZE_MAX))
|
||||
return false;
|
||||
return unmarshal(bin, bl) > 0;
|
||||
}
|
||||
|
||||
int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX], const bool excludeSignature) const noexcept
|
||||
{
|
||||
Utils::storeBigEndian<uint64_t>(data, (uint64_t) m_ts);
|
||||
|
@ -96,7 +119,7 @@ int Locator::unmarshal(const uint8_t *data, const int len) noexcept
|
|||
m_ts = (int64_t) Utils::loadBigEndian<uint64_t>(data);
|
||||
int p = 8;
|
||||
|
||||
int l = m_signer.unmarshal(data + p,len - p);
|
||||
int l = m_signer.unmarshal(data + p, len - p);
|
||||
if (l <= 0)
|
||||
return -1;
|
||||
p += l;
|
||||
|
@ -123,7 +146,7 @@ int Locator::unmarshal(const uint8_t *data, const int len) noexcept
|
|||
return -1;
|
||||
const unsigned int siglen = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
if (unlikely((siglen > ZT_SIGNATURE_BUFFER_SIZE) || ((p + (int)siglen) > len)))
|
||||
if (unlikely((siglen > ZT_SIGNATURE_BUFFER_SIZE) || ((p + (int) siglen) > len)))
|
||||
return -1;
|
||||
m_signature.unsafeSetSize(siglen);
|
||||
Utils::copy(m_signature.data(), data + p, siglen);
|
||||
|
@ -148,9 +171,25 @@ ZT_Locator *ZT_Locator_create(
|
|||
if ((ts <= 0) || (!endpoints) || (endpointCount == 0) || (!signer))
|
||||
return nullptr;
|
||||
ZeroTier::Locator *loc = new ZeroTier::Locator();
|
||||
for(unsigned int i=0;i<endpointCount;++i)
|
||||
for (unsigned int i = 0;i < endpointCount;++i)
|
||||
loc->add(reinterpret_cast<const ZeroTier::Endpoint *>(endpoints)[i]);
|
||||
if (!loc->sign(ts,*reinterpret_cast<const ZeroTier::Identity *>(signer))) {
|
||||
if (!loc->sign(ts, *reinterpret_cast<const ZeroTier::Identity *>(signer))) {
|
||||
delete loc;
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<ZT_Locator *>(loc);
|
||||
} catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_Locator *ZT_Locator_fromString(const char *str)
|
||||
{
|
||||
try {
|
||||
if (!str)
|
||||
return nullptr;
|
||||
ZeroTier::Locator *loc = new ZeroTier::Locator();
|
||||
if (!loc->fromString(str)) {
|
||||
delete loc;
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -168,45 +207,62 @@ ZT_Locator *ZT_Locator_unmarshal(
|
|||
if ((!data) || (len == 0))
|
||||
return nullptr;
|
||||
ZeroTier::Locator *loc = new ZeroTier::Locator();
|
||||
if (loc->unmarshal(reinterpret_cast<const uint8_t *>(data),(int)len) <= 0) {
|
||||
if (loc->unmarshal(reinterpret_cast<const uint8_t *>(data), (int) len) <= 0) {
|
||||
delete loc;
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<ZT_Locator *>(loc);
|
||||
} catch ( ... ) {
|
||||
} catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int ZT_Locator_marshal(const ZT_Locator *loc,void *buf,unsigned int bufSize)
|
||||
int ZT_Locator_marshal(const ZT_Locator *loc, void *buf, unsigned int bufSize)
|
||||
{
|
||||
if ((!loc) || (bufSize < ZT_LOCATOR_MARSHAL_SIZE_MAX))
|
||||
return -1;
|
||||
return reinterpret_cast<const ZeroTier::Locator *>(loc)->marshal(reinterpret_cast<uint8_t *>(buf),(int)bufSize);
|
||||
return reinterpret_cast<const ZeroTier::Locator *>(loc)->marshal(reinterpret_cast<uint8_t *>(buf), (int) bufSize);
|
||||
}
|
||||
|
||||
char *ZT_Locator_toString(
|
||||
const ZT_Locator *loc,
|
||||
char *buf,
|
||||
int capacity)
|
||||
{
|
||||
if ((!loc) || (capacity < ZT_LOCATOR_STRING_SIZE_MAX))
|
||||
return nullptr;
|
||||
return reinterpret_cast<const ZeroTier::Locator *>(loc)->toString(buf);
|
||||
}
|
||||
|
||||
const ZT_Fingerprint *ZT_Locator_fingerprint(const ZT_Locator *loc)
|
||||
{
|
||||
if (!loc)
|
||||
return nullptr;
|
||||
return (ZT_Fingerprint *)(&(reinterpret_cast<const ZeroTier::Locator *>(loc)->signer()));
|
||||
return (ZT_Fingerprint *) (&(reinterpret_cast<const ZeroTier::Locator *>(loc)->signer()));
|
||||
}
|
||||
|
||||
int64_t ZT_Locator_timestamp(const ZT_Locator *loc)
|
||||
{
|
||||
if (!loc)
|
||||
return 0;
|
||||
return reinterpret_cast<const ZeroTier::Locator *>(loc)->timestamp();
|
||||
}
|
||||
|
||||
unsigned int ZT_Locator_endpointCount(const ZT_Locator *loc)
|
||||
{
|
||||
return (loc) ? (unsigned int)(reinterpret_cast<const ZeroTier::Locator *>(loc)->endpoints().size()) : 0;
|
||||
return (loc) ? (unsigned int) (reinterpret_cast<const ZeroTier::Locator *>(loc)->endpoints().size()) : 0;
|
||||
}
|
||||
|
||||
const ZT_Endpoint *ZT_Locator_endpoint(const ZT_Locator *loc,const unsigned int ep)
|
||||
const ZT_Endpoint *ZT_Locator_endpoint(const ZT_Locator *loc, const unsigned int ep)
|
||||
{
|
||||
if (!loc)
|
||||
return nullptr;
|
||||
if (ep >= (unsigned int)(reinterpret_cast<const ZeroTier::Locator *>(loc)->endpoints().size()))
|
||||
if (ep >= (unsigned int) (reinterpret_cast<const ZeroTier::Locator *>(loc)->endpoints().size()))
|
||||
return nullptr;
|
||||
return reinterpret_cast<const ZT_Endpoint *>(&(reinterpret_cast<const ZeroTier::Locator *>(loc)->endpoints()[ep]));
|
||||
}
|
||||
|
||||
int ZT_Locator_verify(const ZT_Locator *loc,const ZT_Identity *signer)
|
||||
int ZT_Locator_verify(const ZT_Locator *loc, const ZT_Identity *signer)
|
||||
{
|
||||
if ((!loc) || (!signer))
|
||||
return 0;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#define ZT_LOCATOR_MAX_ENDPOINTS 8
|
||||
#define ZT_LOCATOR_MARSHAL_SIZE_MAX (8 + ZT_FINGERPRINT_MARSHAL_SIZE + 2 + (ZT_LOCATOR_MAX_ENDPOINTS * ZT_ENDPOINT_MARSHAL_SIZE_MAX) + 2 + 2 + ZT_SIGNATURE_BUFFER_SIZE)
|
||||
#define ZT_LOCATOR_STRING_SIZE_MAX 4096
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -105,14 +106,27 @@ public:
|
|||
*/
|
||||
bool verify(const Identity &id) const noexcept;
|
||||
|
||||
/**
|
||||
* Convert this locator to a string
|
||||
*
|
||||
* @param s String buffer
|
||||
* @return Pointer to buffer
|
||||
*/
|
||||
char *toString(char s[ZT_LOCATOR_STRING_SIZE_MAX]) const noexcept;
|
||||
|
||||
/**
|
||||
* Decode a string format locator
|
||||
*
|
||||
* @param s Locator from toString()
|
||||
* @return True if format was valid
|
||||
*/
|
||||
bool fromString(const char *s) noexcept;
|
||||
|
||||
explicit ZT_INLINE operator bool() const noexcept
|
||||
{ return m_ts > 0; }
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_LOCATOR_MARSHAL_SIZE_MAX; }
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept { return ZT_LOCATOR_MARSHAL_SIZE_MAX; }
|
||||
int marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX], bool excludeSignature = false) const noexcept;
|
||||
|
||||
int unmarshal(const uint8_t *data, int len) noexcept;
|
||||
|
||||
private:
|
||||
|
|
Loading…
Add table
Reference in a new issue