ZeroTierOne/go/pkg/zerotier/localconfig.go

145 lines
4.7 KiB
Go

/*
* 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 zerotier
import (
"encoding/json"
"io/ioutil"
"os"
"runtime"
)
// LocalConfigPhysicalPathConfiguration contains settings for physical paths
type LocalConfigPhysicalPathConfiguration struct {
// 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 is a list of IPs/ports to try for this peer in addition to anything learned from roots or direct path push
Try []InetAddress `json:"try,omitempty"`
}
// ExternalAddress is an externally visible address
type ExternalAddress struct {
InetAddress
// Permanent indicates that this address should be incorporated into this node's Locator
Permanent bool `json:"permanent"`
}
// LocalConfigSettings contains node settings
type LocalConfigSettings struct {
// PrimaryPort is the main UDP port and must be set (defaults to 9993)
PrimaryPort int `json:"primaryPort"`
// SecondaryPort is the secondary UDP port, set to 0 to disbale (picked at random by default)
SecondaryPort int `json:"secondaryPort"`
// PortSearch causes ZeroTier to try other ports automatically if it can't bind to configured ports
PortSearch bool `json:"portSearch"`
// PortMapping enables uPnP and NAT-PMP support
PortMapping bool `json:"portMapping"`
// LogSizeMax is the maximum size of the infoLog in kilobytes or 0 for no limit and -1 to disable logging
LogSizeMax int `json:"logSizeMax"`
// IP/port to bind for TCP access to control API (disabled if null)
APITCPBindAddress *InetAddress `json:"apiTCPBindAddress,omitempty"`
// InterfacePrefixBlacklist are prefixes of physical network interface names that won't be used by ZeroTier (e.g. "lo" or "utun")
InterfacePrefixBlacklist []string `json:"interfacePrefixBlacklist,omitempty"`
// ExplicitAddresses are explicit IP/port addresses to advertise to other nodes, such as externally mapped ports on a router
ExplicitAddresses []ExternalAddress `json:"explicitAddresses,omitempty"`
}
// 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 `json:"physical,omitempty"`
// Virtual node specific configurations by 10-digit hex ZeroTier address
Virtual map[Address]LocalConfigVirtualAddressConfiguration `json:"virtual,omitempty"`
// Network local configurations by 16-digit hex ZeroTier network ID
Network map[NetworkID]NetworkLocalSettings `json:"network,omitempty"`
// LocalConfigSettings contains other local settings for this node
Settings LocalConfigSettings `json:"settings"`
initialized bool
}
// Read this local config from a file, initializing to defaults if the file does not exist.
func (lc *LocalConfig) Read(p string, saveDefaultsIfNotExist bool, isTotallyNewNode bool) error {
// Initialize defaults, which may be replaced if we read a file from disk.
if !lc.initialized {
lc.initialized = true
lc.Physical = make(map[string]LocalConfigPhysicalPathConfiguration)
lc.Virtual = make(map[Address]LocalConfigVirtualAddressConfiguration)
lc.Network = make(map[NetworkID]NetworkLocalSettings)
if isTotallyNewNode {
lc.Settings.PrimaryPort = 893
} else {
lc.Settings.PrimaryPort = 9993
}
lc.Settings.SecondaryPort = unassignedPrivilegedPorts[randomUInt()%uint(len(unassignedPrivilegedPorts))]
lc.Settings.PortSearch = true
lc.Settings.PortMapping = true
lc.Settings.LogSizeMax = 128
if !isTotallyNewNode {
lc.Settings.APITCPBindAddress = NewInetAddressFromString("127.0.0.1/9993")
}
switch runtime.GOOS {
case "windows":
lc.Settings.InterfacePrefixBlacklist = []string{"loopback"}
case "darwin":
lc.Settings.InterfacePrefixBlacklist = []string{"lo", "utun", "feth"}
default:
lc.Settings.InterfacePrefixBlacklist = []string{"lo"}
}
}
data, err := ioutil.ReadFile(p)
if err != nil {
if !os.IsNotExist(err) {
return err
}
if saveDefaultsIfNotExist {
err = lc.Write(p)
if err != nil {
return err
}
}
return nil
}
return json.Unmarshal(data, lc)
}
// Write this local config to a file
func (lc *LocalConfig) Write(p string) error {
data, err := json.MarshalIndent(lc, "", "\t")
if err != nil {
return err
}
return ioutil.WriteFile(p, data, 0644)
}