Merge pull request #3 from vikulin/future

Future merge
This commit is contained in:
Vadym Vikulin 2021-06-02 17:36:33 +03:00 committed by GitHub
commit a7da93ffd8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 105 additions and 154 deletions

View file

@ -35,7 +35,7 @@ import (
type node struct { type node struct {
core core.Core core core.Core
state *config.NodeState config *config.NodeConfig
tuntap module.Module // tuntap.TunAdapter tuntap module.Module // tuntap.TunAdapter
multicast module.Module // multicast.Multicast multicast module.Module // multicast.Multicast
admin module.Module // admin.AdminSocket admin module.Module // admin.AdminSocket
@ -107,7 +107,9 @@ func readConfig(useconf *bool, useconffile *string, normaliseconf *bool) *config
if err != nil { if err != nil {
panic(err) panic(err)
} }
json.Unmarshal(confJson, &cfg) if err := json.Unmarshal(confJson, &cfg); err != nil {
panic(err)
}
// Overlay our newly mapped configuration onto the autoconf node config that // Overlay our newly mapped configuration onto the autoconf node config that
// we generated above. // we generated above.
if err = mapstructure.Decode(dat, &cfg); err != nil { if err = mapstructure.Decode(dat, &cfg); err != nil {
@ -272,8 +274,7 @@ func main() {
n := node{} n := node{}
// Now start Yggdrasil - this starts the DHT, router, switch and other core // Now start Yggdrasil - this starts the DHT, router, switch and other core
// components needed for Yggdrasil to operate // components needed for Yggdrasil to operate
n.state, err = n.core.Start(cfg, logger) if err = n.core.Start(cfg, logger); err != nil {
if err != nil {
logger.Errorln("An error occurred during startup") logger.Errorln("An error occurred during startup")
panic(err) panic(err)
} }
@ -284,20 +285,23 @@ func main() {
n.tuntap = &tuntap.TunAdapter{} n.tuntap = &tuntap.TunAdapter{}
n.tuntap.(*tuntap.TunAdapter).SetSessionGatekeeper(n.sessionFirewall) n.tuntap.(*tuntap.TunAdapter).SetSessionGatekeeper(n.sessionFirewall)
// Start the admin socket // Start the admin socket
n.admin.Init(&n.core, n.state, logger, nil) if err := n.admin.Init(&n.core, cfg, logger, nil); err != nil {
if err := n.admin.Start(); err != nil { logger.Errorln("An error occured initialising admin socket:", err)
} else if err := n.admin.Start(); err != nil {
logger.Errorln("An error occurred starting admin socket:", err) logger.Errorln("An error occurred starting admin socket:", err)
} }
n.admin.SetupAdminHandlers(n.admin.(*admin.AdminSocket)) n.admin.SetupAdminHandlers(n.admin.(*admin.AdminSocket))
// Start the multicast interface // Start the multicast interface
n.multicast.Init(&n.core, n.state, logger, nil) if err := n.multicast.Init(&n.core, cfg, logger, nil); err != nil {
if err := n.multicast.Start(); err != nil { logger.Errorln("An error occured initialising multicast:", err)
} else if err := n.multicast.Start(); err != nil {
logger.Errorln("An error occurred starting multicast:", err) logger.Errorln("An error occurred starting multicast:", err)
} }
n.multicast.SetupAdminHandlers(n.admin.(*admin.AdminSocket)) n.multicast.SetupAdminHandlers(n.admin.(*admin.AdminSocket))
// Start the TUN/TAP interface // Start the TUN/TAP interface
n.tuntap.Init(&n.core, n.state, logger, nil) if err := n.tuntap.Init(&n.core, cfg, logger, nil); err != nil {
if err := n.tuntap.Start(); err != nil { logger.Errorln("An error occurred initialising TUN/TAP:", err)
} else if err := n.tuntap.Start(); err != nil {
logger.Errorln("An error occurred starting TUN/TAP:", err) logger.Errorln("An error occurred starting TUN/TAP:", err)
} }
n.tuntap.SetupAdminHandlers(n.admin.(*admin.AdminSocket)) n.tuntap.SetupAdminHandlers(n.admin.(*admin.AdminSocket))
@ -317,23 +321,23 @@ func main() {
} }
func (n *node) shutdown() { func (n *node) shutdown() {
n.admin.Stop() _ = n.admin.Stop()
n.multicast.Stop() _ = n.multicast.Stop()
n.tuntap.Stop() _ = n.tuntap.Stop()
n.core.Stop() n.core.Stop()
} }
func (n *node) sessionFirewall(pubkey ed25519.PublicKey, initiator bool) bool { func (n *node) sessionFirewall(pubkey ed25519.PublicKey, initiator bool) bool {
n.state.Mutex.RLock() n.config.RLock()
defer n.state.Mutex.RUnlock() defer n.config.RUnlock()
// Allow by default if the session firewall is disabled // Allow by default if the session firewall is disabled
if !n.state.Current.SessionFirewall.Enable { if !n.config.SessionFirewall.Enable {
return true return true
} }
// Reject blacklisted nodes // Reject blacklisted nodes
for _, b := range n.state.Current.SessionFirewall.BlacklistPublicKeys { for _, b := range n.config.SessionFirewall.BlacklistPublicKeys {
key, err := hex.DecodeString(b) key, err := hex.DecodeString(b)
if err == nil { if err == nil {
if bytes.Equal(key, pubkey) { if bytes.Equal(key, pubkey) {
@ -343,7 +347,7 @@ func (n *node) sessionFirewall(pubkey ed25519.PublicKey, initiator bool) bool {
} }
// Allow whitelisted nodes // Allow whitelisted nodes
for _, b := range n.state.Current.SessionFirewall.WhitelistPublicKeys { for _, b := range n.config.SessionFirewall.WhitelistPublicKeys {
key, err := hex.DecodeString(b) key, err := hex.DecodeString(b)
if err == nil { if err == nil {
if bytes.Equal(key, pubkey) { if bytes.Equal(key, pubkey) {
@ -353,7 +357,7 @@ func (n *node) sessionFirewall(pubkey ed25519.PublicKey, initiator bool) bool {
} }
// Allow outbound sessions if appropriate // Allow outbound sessions if appropriate
if n.state.Current.SessionFirewall.AlwaysAllowOutbound { if n.config.SessionFirewall.AlwaysAllowOutbound {
if initiator { if initiator {
return true return true
} }
@ -369,12 +373,12 @@ func (n *node) sessionFirewall(pubkey ed25519.PublicKey, initiator bool) bool {
} }
// Allow direct peers if appropriate // Allow direct peers if appropriate
if n.state.Current.SessionFirewall.AllowFromDirect && isDirectPeer { if n.config.SessionFirewall.AllowFromDirect && isDirectPeer {
return true return true
} }
// Allow remote nodes if appropriate // Allow remote nodes if appropriate
if n.state.Current.SessionFirewall.AllowFromRemote && !isDirectPeer { if n.config.SessionFirewall.AllowFromRemote && !isDirectPeer {
return true return true
} }

View file

@ -47,8 +47,8 @@ func run() int {
fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [options] command [key=value] [key=value] ...\n\n", os.Args[0]) fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [options] command [key=value] [key=value] ...\n\n", os.Args[0])
fmt.Println("Options:") fmt.Println("Options:")
flag.PrintDefaults() flag.PrintDefaults()
fmt.Println("\nPlease note that options must always specified BEFORE the command\non the command line or they will be ignored.\n") fmt.Println("\nPlease note that options must always specified BEFORE the command\non the command line or they will be ignored.\n") // nolint:govet
fmt.Println("Commands:\n - Use \"list\" for a list of available commands\n") fmt.Println("Commands:\n - Use \"list\" for a list of available commands\n") // nolint:govet
fmt.Println("Examples:") fmt.Println("Examples:")
fmt.Println(" - ", os.Args[0], "list") fmt.Println(" - ", os.Args[0], "list")
fmt.Println(" - ", os.Args[0], "getPeers") fmt.Println(" - ", os.Args[0], "getPeers")

View file

@ -63,12 +63,13 @@ func (a *AdminSocket) AddHandler(name string, args []string, handlerfunc func(js
} }
// Init runs the initial admin setup. // Init runs the initial admin setup.
func (a *AdminSocket) Init(c *core.Core, state *config.NodeState, log *log.Logger, options interface{}) error { func (a *AdminSocket) Init(c *core.Core, nc *config.NodeConfig, log *log.Logger, options interface{}) error {
a.core = c a.core = c
a.log = log a.log = log
a.handlers = make(map[string]handler) a.handlers = make(map[string]handler)
current := state.GetCurrent() nc.RLock()
a.listenaddr = current.AdminListen a.listenaddr = nc.AdminListen
nc.RUnlock()
a.done = make(chan struct{}) a.done = make(chan struct{})
close(a.done) // Start in a done / not-started state close(a.done) // Start in a done / not-started state
_ = a.AddHandler("list", []string{}, func(_ json.RawMessage) (interface{}, error) { _ = a.AddHandler("list", []string{}, func(_ json.RawMessage) (interface{}, error) {

View file

@ -24,41 +24,11 @@ import (
"github.com/yggdrasil-network/yggdrasil-go/src/defaults" "github.com/yggdrasil-network/yggdrasil-go/src/defaults"
) )
// NodeState represents the active and previous configuration of an Yggdrasil
// node. A NodeState object is returned when starting an Yggdrasil node. Note
// that this structure and related functions are likely to disappear soon.
type NodeState struct {
Current NodeConfig
Previous NodeConfig
Mutex sync.RWMutex
}
// Current returns the active node configuration.
func (s *NodeState) GetCurrent() NodeConfig {
s.Mutex.RLock()
defer s.Mutex.RUnlock()
return s.Current
}
// Previous returns the previous node configuration.
func (s *NodeState) GetPrevious() NodeConfig {
s.Mutex.RLock()
defer s.Mutex.RUnlock()
return s.Previous
}
// Replace the node configuration with new configuration.
func (s *NodeState) Replace(n NodeConfig) {
s.Mutex.Lock()
defer s.Mutex.Unlock()
s.Previous = s.Current
s.Current = n
}
// NodeConfig is the main configuration structure, containing configuration // NodeConfig is the main configuration structure, containing configuration
// options that are necessary for an Yggdrasil node to run. You will need to // options that are necessary for an Yggdrasil node to run. You will need to
// supply one of these structs to the Yggdrasil core when starting a node. // supply one of these structs to the Yggdrasil core when starting a node.
type NodeConfig struct { type NodeConfig struct {
sync.RWMutex
Peers []string `comment:"List of connection strings for outbound peer connections in URI format,\ne.g. tcp://a.b.c.d:e or socks://a.b.c.d:e/f.g.h.i:j. These connections\nwill obey the operating system routing table, therefore you should\nuse this section when you may connect via different interfaces."` Peers []string `comment:"List of connection strings for outbound peer connections in URI format,\ne.g. tcp://a.b.c.d:e or socks://a.b.c.d:e/f.g.h.i:j. These connections\nwill obey the operating system routing table, therefore you should\nuse this section when you may connect via different interfaces."`
InterfacePeers map[string][]string `comment:"List of connection strings for outbound peer connections in URI format,\narranged by source interface, e.g. { \"eth0\": [ tcp://a.b.c.d:e ] }.\nNote that SOCKS peerings will NOT be affected by this option and should\ngo in the \"Peers\" section instead."` InterfacePeers map[string][]string `comment:"List of connection strings for outbound peer connections in URI format,\narranged by source interface, e.g. { \"eth0\": [ tcp://a.b.c.d:e ] }.\nNote that SOCKS peerings will NOT be affected by this option and should\ngo in the \"Peers\" section instead."`
Listen []string `comment:"Listen addresses for incoming connections. You will need to add\nlisteners in order to accept incoming peerings from non-local nodes.\nMulticast peer discovery will work regardless of any listeners set\nhere. Each listener should be specified in URI format as above, e.g.\ntcp://0.0.0.0:0 or tcp://[::]:0 to listen on all interfaces."` Listen []string `comment:"Listen addresses for incoming connections. You will need to add\nlisteners in order to accept incoming peerings from non-local nodes.\nMulticast peer discovery will work regardless of any listeners set\nhere. Each listener should be specified in URI format as above, e.g.\ntcp://0.0.0.0:0 or tcp://[::]:0 to listen on all interfaces."`

View file

@ -25,7 +25,7 @@ type Core struct {
// guarantee that it will be covered by the mutex // guarantee that it will be covered by the mutex
phony.Inbox phony.Inbox
*iw.PacketConn *iw.PacketConn
config config.NodeState // Config config *config.NodeConfig // Config
secret ed25519.PrivateKey secret ed25519.PrivateKey
public ed25519.PublicKey public ed25519.PublicKey
links links links links
@ -42,9 +42,9 @@ func (c *Core) _init() error {
c.log = log.New(ioutil.Discard, "", 0) c.log = log.New(ioutil.Discard, "", 0)
} }
current := c.config.GetCurrent() c.config.RLock()
sigPriv, err := hex.DecodeString(c.config.PrivateKey)
sigPriv, err := hex.DecodeString(current.PrivateKey) c.config.RUnlock()
if err != nil { if err != nil {
return err return err
} }
@ -64,11 +64,11 @@ func (c *Core) _init() error {
// configure them. The loop ensures that disconnected peers will eventually // configure them. The loop ensures that disconnected peers will eventually
// be reconnected with. // be reconnected with.
func (c *Core) _addPeerLoop() { func (c *Core) _addPeerLoop() {
// Get the peers from the config - these could change! c.config.RLock()
current := c.config.GetCurrent() defer c.config.RUnlock()
// Add peers from the Peers section // Add peers from the Peers section
for _, peer := range current.Peers { for _, peer := range c.config.Peers {
go func(peer string, intf string) { go func(peer string, intf string) {
u, err := url.Parse(peer) u, err := url.Parse(peer)
if err != nil { if err != nil {
@ -81,7 +81,7 @@ func (c *Core) _addPeerLoop() {
} }
// Add peers from the InterfacePeers section // Add peers from the InterfacePeers section
for intf, intfpeers := range current.InterfacePeers { for intf, intfpeers := range c.config.InterfacePeers {
for _, peer := range intfpeers { for _, peer := range intfpeers {
go func(peer string, intf string) { go func(peer string, intf string) {
u, err := url.Parse(peer) u, err := url.Parse(peer)
@ -107,21 +107,17 @@ func (c *Core) _addPeerLoop() {
// TCP and UDP sockets, a multicast discovery socket, an admin socket, router, // TCP and UDP sockets, a multicast discovery socket, an admin socket, router,
// switch and DHT node. A config.NodeState is returned which contains both the // switch and DHT node. A config.NodeState is returned which contains both the
// current and previous configurations (from reconfigures). // current and previous configurations (from reconfigures).
func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) (conf *config.NodeState, err error) { func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) (err error) {
phony.Block(c, func() { phony.Block(c, func() {
conf, err = c._start(nc, log) err = c._start(nc, log)
}) })
return return
} }
// This function is unsafe and should only be ran by the core actor. // This function is unsafe and should only be ran by the core actor.
func (c *Core) _start(nc *config.NodeConfig, log *log.Logger) (*config.NodeState, error) { func (c *Core) _start(nc *config.NodeConfig, log *log.Logger) error {
c.log = log c.log = log
c.config = nc
c.config = config.NodeState{
Current: *nc,
Previous: *nc,
}
if name := version.BuildName(); name != "unknown" { if name := version.BuildName(); name != "unknown" {
c.log.Infoln("Build name:", name) c.log.Infoln("Build name:", name)
@ -133,30 +129,20 @@ func (c *Core) _start(nc *config.NodeConfig, log *log.Logger) (*config.NodeState
c.log.Infoln("Starting up...") c.log.Infoln("Starting up...")
if err := c._init(); err != nil { if err := c._init(); err != nil {
c.log.Errorln("Failed to initialize core") c.log.Errorln("Failed to initialize core")
return nil, err return err
} }
if err := c.links.init(c); err != nil { if err := c.links.init(c); err != nil {
c.log.Errorln("Failed to start link interfaces") c.log.Errorln("Failed to start link interfaces")
return nil, err return err
} }
//if err := c.switchTable.start(); err != nil {
// c.log.Errorln("Failed to start switch")
// return nil, err
//}
//if err := c.router.start(); err != nil {
// c.log.Errorln("Failed to start router")
// return nil, err
//}
c.addPeerTimer = time.AfterFunc(0, func() { c.addPeerTimer = time.AfterFunc(0, func() {
c.Act(nil, c._addPeerLoop) c.Act(nil, c._addPeerLoop)
}) })
c.log.Infoln("Startup complete") c.log.Infoln("Startup complete")
return &c.config, nil return nil
} }
// Stop shuts down the Yggdrasil node. // Stop shuts down the Yggdrasil node.
@ -172,7 +158,7 @@ func (c *Core) _stop() {
c.addPeerTimer.Stop() c.addPeerTimer.Stop()
c.addPeerTimer = nil c.addPeerTimer = nil
} }
c.links.stop() _ = c.links.stop()
/* FIXME this deadlocks, need a waitgroup or something to coordinate shutdown /* FIXME this deadlocks, need a waitgroup or something to coordinate shutdown
for _, peer := range c.GetPeers() { for _, peer := range c.GetPeers() {
c.DisconnectPeer(peer.Port) c.DisconnectPeer(peer.Port)

View file

@ -40,14 +40,12 @@ func GetLoggerWithPrefix(prefix string, verbose bool) *log.Logger {
// Verbosity flag is passed to logger. // Verbosity flag is passed to logger.
func CreateAndConnectTwo(t testing.TB, verbose bool) (nodeA *Core, nodeB *Core) { func CreateAndConnectTwo(t testing.TB, verbose bool) (nodeA *Core, nodeB *Core) {
nodeA = new(Core) nodeA = new(Core)
_, err := nodeA.Start(GenerateConfig(), GetLoggerWithPrefix("A: ", verbose)) if err := nodeA.Start(GenerateConfig(), GetLoggerWithPrefix("A: ", verbose)); err != nil {
if err != nil {
t.Fatal(err) t.Fatal(err)
} }
nodeB = new(Core) nodeB = new(Core)
_, err = nodeB.Start(GenerateConfig(), GetLoggerWithPrefix("B: ", verbose)) if err := nodeB.Start(GenerateConfig(), GetLoggerWithPrefix("B: ", verbose)); err != nil {
if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -188,7 +188,9 @@ func (intf *link) handler() (chan struct{}, error) {
} }
} }
// Check if we're authorized to connect to this key / IP // Check if we're authorized to connect to this key / IP
allowed := intf.links.core.config.GetCurrent().AllowedPublicKeys intf.links.core.config.RLock()
allowed := intf.links.core.config.AllowedPublicKeys
intf.links.core.config.RUnlock()
isallowed := len(allowed) == 0 isallowed := len(allowed) == 0
for _, k := range allowed { for _, k := range allowed {
if k == hex.EncodeToString(meta.key) { // TODO: this is yuck if k == hex.EncodeToString(meta.key) { // TODO: this is yuck
@ -248,15 +250,3 @@ func (intf *link) close() {
func (intf *link) name() string { func (intf *link) name() string {
return intf.lname return intf.lname
} }
func (intf *link) local() string {
return intf.info.local
}
func (intf *link) remote() string {
return intf.info.remote
}
func (intf *link) interfaceType() string {
return intf.info.linkType
}

View file

@ -67,7 +67,7 @@ type tcpOptions struct {
} }
func (l *TcpListener) Stop() { func (l *TcpListener) Stop() {
defer func() { recover() }() defer func() { _ = recover() }()
close(l.stop) close(l.stop)
} }
@ -75,7 +75,7 @@ func (l *TcpListener) Stop() {
func (t *tcp) setExtraOptions(c net.Conn) { func (t *tcp) setExtraOptions(c net.Conn) {
switch sock := c.(type) { switch sock := c.(type) {
case *net.TCPConn: case *net.TCPConn:
sock.SetNoDelay(true) _ = sock.SetNoDelay(true)
// TODO something for socks5 // TODO something for socks5
default: default:
} }
@ -104,9 +104,9 @@ func (t *tcp) init(l *links) error {
t.listeners = make(map[string]*TcpListener) t.listeners = make(map[string]*TcpListener)
t.mutex.Unlock() t.mutex.Unlock()
t.links.core.config.Mutex.RLock() t.links.core.config.RLock()
defer t.links.core.config.Mutex.RUnlock() defer t.links.core.config.RUnlock()
for _, listenaddr := range t.links.core.config.Current.Listen { for _, listenaddr := range t.links.core.config.Listen {
u, err := url.Parse(listenaddr) u, err := url.Parse(listenaddr)
if err != nil { if err != nil {
t.links.core.log.Errorln("Failed to parse listener: listener", listenaddr, "is not correctly formatted, ignoring") t.links.core.log.Errorln("Failed to parse listener: listener", listenaddr, "is not correctly formatted, ignoring")

View file

@ -36,7 +36,7 @@ func (t *tcp) getControl(sintf string) func(string, string, syscall.RawConn) err
btd := func(fd uintptr) { btd := func(fd uintptr) {
err = unix.BindToDevice(int(fd), sintf) err = unix.BindToDevice(int(fd), sintf)
} }
c.Control(btd) _ = c.Control(btd)
if err != nil { if err != nil {
t.links.core.log.Debugln("Failed to set SO_BINDTODEVICE:", sintf) t.links.core.log.Debugln("Failed to set SO_BINDTODEVICE:", sintf)
} }

View file

@ -11,7 +11,7 @@ import (
// Module is an interface that defines which functions must be supported by a // Module is an interface that defines which functions must be supported by a
// given Yggdrasil module. // given Yggdrasil module.
type Module interface { type Module interface {
Init(core *core.Core, state *config.NodeState, log *log.Logger, options interface{}) error Init(core *core.Core, state *config.NodeConfig, log *log.Logger, options interface{}) error
Start() error Start() error
Stop() error Stop() error
SetupAdminHandlers(a *admin.AdminSocket) SetupAdminHandlers(a *admin.AdminSocket)

View file

@ -23,7 +23,7 @@ import (
type Multicast struct { type Multicast struct {
phony.Inbox phony.Inbox
core *core.Core core *core.Core
config *config.NodeState config *config.NodeConfig
log *log.Logger log *log.Logger
sock *ipv6.PacketConn sock *ipv6.PacketConn
groupAddr string groupAddr string
@ -45,14 +45,13 @@ type listenerInfo struct {
} }
// Init prepares the multicast interface for use. // Init prepares the multicast interface for use.
func (m *Multicast) Init(core *core.Core, state *config.NodeState, log *log.Logger, options interface{}) error { func (m *Multicast) Init(core *core.Core, nc *config.NodeConfig, log *log.Logger, options interface{}) error {
m.core = core m.core = core
m.config = state m.config = nc
m.log = log m.log = log
m.listeners = make(map[string]*listenerInfo) m.listeners = make(map[string]*listenerInfo)
m._interfaces = make(map[string]interfaceInfo) m._interfaces = make(map[string]interfaceInfo)
current := m.config.GetCurrent() m.listenPort = m.config.LinkLocalTCPPort
m.listenPort = current.LinkLocalTCPPort
m.groupAddr = "[ff02::114]:9001" m.groupAddr = "[ff02::114]:9001"
return nil return nil
} }
@ -73,7 +72,9 @@ func (m *Multicast) _start() error {
if m.isOpen { if m.isOpen {
return fmt.Errorf("multicast module is already started") return fmt.Errorf("multicast module is already started")
} }
if len(m.config.GetCurrent().MulticastInterfaces) == 0 { m.config.RLock()
defer m.config.RUnlock()
if len(m.config.MulticastInterfaces) == 0 {
return nil return nil
} }
m.log.Infoln("Starting multicast module") m.log.Infoln("Starting multicast module")
@ -90,7 +91,7 @@ func (m *Multicast) _start() error {
return err return err
} }
m.sock = ipv6.NewPacketConn(conn) m.sock = ipv6.NewPacketConn(conn)
if err = m.sock.SetControlMessage(ipv6.FlagDst, true); err != nil { if err = m.sock.SetControlMessage(ipv6.FlagDst, true); err != nil { // nolint:staticcheck
// Windows can't set this flag, so we need to handle it in other ways // Windows can't set this flag, so we need to handle it in other ways
} }
@ -161,8 +162,7 @@ func (m *Multicast) Interfaces() map[string]net.Interface {
func (m *Multicast) getAllowedInterfaces() map[string]net.Interface { func (m *Multicast) getAllowedInterfaces() map[string]net.Interface {
interfaces := make(map[string]net.Interface) interfaces := make(map[string]net.Interface)
// Get interface expressions from config // Get interface expressions from config
current := m.config.GetCurrent() exprs := m.config.MulticastInterfaces
exprs := current.MulticastInterfaces
// Ask the system for network interfaces // Ask the system for network interfaces
allifaces, err := net.Interfaces() allifaces, err := net.Interfaces()
if err != nil { if err != nil {
@ -269,7 +269,7 @@ func (m *Multicast) _announce() {
continue continue
} }
// Join the multicast group // Join the multicast group
m.sock.JoinGroup(&iface, groupAddr) _ = m.sock.JoinGroup(&iface, groupAddr)
// Try and see if we already have a TCP listener for this interface // Try and see if we already have a TCP listener for this interface
var info *listenerInfo var info *listenerInfo
if nfo, ok := m.listeners[iface.Name]; !ok || nfo.listener.Listener == nil { if nfo, ok := m.listeners[iface.Name]; !ok || nfo.listener.Listener == nil {
@ -304,7 +304,7 @@ func (m *Multicast) _announce() {
a.Zone = "" a.Zone = ""
destAddr.Zone = iface.Name destAddr.Zone = iface.Name
msg := []byte(a.String()) msg := []byte(a.String())
m.sock.WriteTo(msg, nil, destAddr) _, _ = m.sock.WriteTo(msg, nil, destAddr)
} }
if info.interval.Seconds() < 15 { if info.interval.Seconds() < 15 {
info.interval += time.Second info.interval += time.Second

View file

@ -29,8 +29,6 @@ import (
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
var awdlGoroutineStarted bool
func (m *Multicast) _multicastStarted() { func (m *Multicast) _multicastStarted() {
if !m.isOpen { if !m.isOpen {
return return

View file

@ -123,16 +123,12 @@ func (tun *TunAdapter) write() {
continue // bad remote address/subnet continue // bad remote address/subnet
} }
bs = buf[:TUN_OFFSET_BYTES+len(bs)] bs = buf[:TUN_OFFSET_BYTES+len(bs)]
n, err = tun.iface.Write(bs, TUN_OFFSET_BYTES) if _, err = tun.iface.Write(bs, TUN_OFFSET_BYTES); err != nil {
if err != nil {
tun.Act(nil, func() { tun.Act(nil, func() {
if !tun.isOpen { if !tun.isOpen {
tun.log.Errorln("TUN iface write error:", err) tun.log.Errorln("TUN iface write error:", err)
} }
}) })
} }
if n != len(bs) {
// TODO some kind of error reporting for a partial write
}
} }
} }

View file

@ -50,7 +50,7 @@ func (k *keyStore) sendToAddress(addr address.Address, bs []byte) {
if info := k.addrToInfo[addr]; info != nil { if info := k.addrToInfo[addr]; info != nil {
k.resetTimeout(info) k.resetTimeout(info)
k.mutex.Unlock() k.mutex.Unlock()
k.tun.core.WriteTo(bs, iwt.Addr(info.key[:])) _, _ = k.tun.core.WriteTo(bs, iwt.Addr(info.key[:]))
} else { } else {
var buf *buffer var buf *buffer
if buf = k.addrBuffer[addr]; buf == nil { if buf = k.addrBuffer[addr]; buf == nil {
@ -79,7 +79,7 @@ func (k *keyStore) sendToSubnet(subnet address.Subnet, bs []byte) {
if info := k.subnetToInfo[subnet]; info != nil { if info := k.subnetToInfo[subnet]; info != nil {
k.resetTimeout(info) k.resetTimeout(info)
k.mutex.Unlock() k.mutex.Unlock()
k.tun.core.WriteTo(bs, iwt.Addr(info.key[:])) _, _ = k.tun.core.WriteTo(bs, iwt.Addr(info.key[:]))
} else { } else {
var buf *buffer var buf *buffer
if buf = k.subnetBuffer[subnet]; buf == nil { if buf = k.subnetBuffer[subnet]; buf == nil {
@ -132,13 +132,13 @@ func (k *keyStore) update(key ed25519.PublicKey) *keyInfo {
k.mutex.Unlock() k.mutex.Unlock()
if buf := k.addrBuffer[info.address]; buf != nil { if buf := k.addrBuffer[info.address]; buf != nil {
for _, bs := range buf.packets { for _, bs := range buf.packets {
k.tun.core.WriteTo(bs, iwt.Addr(info.key[:])) _, _ = k.tun.core.WriteTo(bs, iwt.Addr(info.key[:]))
} }
delete(k.addrBuffer, info.address) delete(k.addrBuffer, info.address)
} }
if buf := k.subnetBuffer[info.subnet]; buf != nil { if buf := k.subnetBuffer[info.subnet]; buf != nil {
for _, bs := range buf.packets { for _, bs := range buf.packets {
k.tun.core.WriteTo(bs, iwt.Addr(info.key[:])) _, _ = k.tun.core.WriteTo(bs, iwt.Addr(info.key[:]))
} }
delete(k.subnetBuffer, info.subnet) delete(k.subnetBuffer, info.subnet)
} }

View file

@ -129,7 +129,7 @@ func (m *nodeinfo) _sendReq(key keyArray, callback func(nodeinfo NodeInfoPayload
if callback != nil { if callback != nil {
m._addCallback(key, callback) m._addCallback(key, callback)
} }
m.proto.tun.core.WriteTo([]byte{typeSessionProto, typeProtoNodeInfoRequest}, iwt.Addr(key[:])) _, _ = m.proto.tun.core.WriteTo([]byte{typeSessionProto, typeProtoNodeInfoRequest}, iwt.Addr(key[:]))
} }
func (m *nodeinfo) handleReq(from phony.Actor, key keyArray) { func (m *nodeinfo) handleReq(from phony.Actor, key keyArray) {
@ -146,7 +146,7 @@ func (m *nodeinfo) handleRes(from phony.Actor, key keyArray, info NodeInfoPayloa
func (m *nodeinfo) _sendRes(key keyArray) { func (m *nodeinfo) _sendRes(key keyArray) {
bs := append([]byte{typeSessionProto, typeProtoNodeInfoResponse}, m._getNodeInfo()...) bs := append([]byte{typeSessionProto, typeProtoNodeInfoResponse}, m._getNodeInfo()...)
m.proto.tun.core.WriteTo(bs, iwt.Addr(key[:])) _, _ = m.proto.tun.core.WriteTo(bs, iwt.Addr(key[:]))
} }
// Admin socket stuff // Admin socket stuff

View file

@ -209,7 +209,7 @@ func (p *protoHandler) _handleGetDHTResponse(key keyArray, bs []byte) {
func (p *protoHandler) _sendDebug(key keyArray, dType uint8, data []byte) { func (p *protoHandler) _sendDebug(key keyArray, dType uint8, data []byte) {
bs := append([]byte{typeSessionProto, typeProtoDebug, dType}, data...) bs := append([]byte{typeSessionProto, typeProtoDebug, dType}, data...)
p.tun.core.WriteTo(bs, iwt.Addr(key[:])) _, _ = p.tun.core.WriteTo(bs, iwt.Addr(key[:]))
} }
// Admin socket stuff // Admin socket stuff

View file

@ -35,7 +35,7 @@ type MTU uint16
type TunAdapter struct { type TunAdapter struct {
core *core.Core core *core.Core
store keyStore store keyStore
config *config.NodeState config *config.NodeConfig
log *log.Logger log *log.Logger
addr address.Address addr address.Address
subnet address.Subnet subnet address.Subnet
@ -103,13 +103,17 @@ func MaximumMTU() uint64 {
// Init initialises the TUN module. You must have acquired a Listener from // Init initialises the TUN module. You must have acquired a Listener from
// the Yggdrasil core before this point and it must not be in use elsewhere. // the Yggdrasil core before this point and it must not be in use elsewhere.
func (tun *TunAdapter) Init(core *core.Core, config *config.NodeState, log *log.Logger, options interface{}) error { func (tun *TunAdapter) Init(core *core.Core, config *config.NodeConfig, log *log.Logger, options interface{}) error {
tun.core = core tun.core = core
tun.store.init(tun) tun.store.init(tun)
tun.config = config tun.config = config
tun.log = log tun.log = log
tun.proto.init(tun) tun.proto.init(tun)
tun.proto.nodeinfo.setNodeInfo(config.Current.NodeInfo, config.Current.NodeInfoPrivacy) tun.config.RLock()
if err := tun.proto.nodeinfo.setNodeInfo(tun.config.NodeInfo, tun.config.NodeInfoPrivacy); err != nil {
return fmt.Errorf("tun.proto.nodeinfo.setNodeInfo: %w", err)
}
tun.config.RUnlock()
if err := tun.core.SetOutOfBandHandler(tun.oobHandler); err != nil { if err := tun.core.SetOutOfBandHandler(tun.oobHandler); err != nil {
return fmt.Errorf("tun.core.SetOutOfBandHander: %w", err) return fmt.Errorf("tun.core.SetOutOfBandHander: %w", err)
} }
@ -130,7 +134,8 @@ func (tun *TunAdapter) _start() error {
if tun.isOpen { if tun.isOpen {
return errors.New("TUN module is already started") return errors.New("TUN module is already started")
} }
current := tun.config.GetCurrent() tun.config.RLock()
defer tun.config.RUnlock()
if tun.config == nil { if tun.config == nil {
return errors.New("no configuration available to TUN") return errors.New("no configuration available to TUN")
} }
@ -139,21 +144,21 @@ func (tun *TunAdapter) _start() error {
tun.addr = *address.AddrForKey(pk) tun.addr = *address.AddrForKey(pk)
tun.subnet = *address.SubnetForKey(pk) tun.subnet = *address.SubnetForKey(pk)
addr := fmt.Sprintf("%s/%d", net.IP(tun.addr[:]).String(), 8*len(address.GetPrefix())-1) addr := fmt.Sprintf("%s/%d", net.IP(tun.addr[:]).String(), 8*len(address.GetPrefix())-1)
if current.IfName == "none" || current.IfName == "dummy" { if tun.config.IfName == "none" || tun.config.IfName == "dummy" {
tun.log.Debugln("Not starting TUN as ifname is none or dummy") tun.log.Debugln("Not starting TUN as ifname is none or dummy")
tun.isEnabled = false tun.isEnabled = false
go tun.write() go tun.write()
return nil return nil
} }
mtu := current.IfMTU mtu := tun.config.IfMTU
if tun.maxSessionMTU() < mtu { if tun.maxSessionMTU() < mtu {
mtu = tun.maxSessionMTU() mtu = tun.maxSessionMTU()
} }
if err := tun.setup(current.IfName, addr, mtu); err != nil { if err := tun.setup(tun.config.IfName, addr, mtu); err != nil {
return err return err
} }
if tun.MTU() != mtu { if tun.MTU() != mtu {
tun.log.Warnf("Warning: Interface MTU %d automatically adjusted to %d (supported range is 1280-%d)", current.IfMTU, tun.MTU(), MaximumMTU()) tun.log.Warnf("Warning: Interface MTU %d automatically adjusted to %d (supported range is 1280-%d)", tun.config.IfMTU, tun.MTU(), MaximumMTU())
} }
tun.isOpen = true tun.isOpen = true
tun.isEnabled = true tun.isEnabled = true
@ -216,13 +221,13 @@ func (tun *TunAdapter) oobHandler(fromKey, toKey ed25519.PublicKey, data []byte)
func (tun *TunAdapter) sendKeyLookup(partial ed25519.PublicKey) { func (tun *TunAdapter) sendKeyLookup(partial ed25519.PublicKey) {
sig := ed25519.Sign(tun.core.PrivateKey(), partial[:]) sig := ed25519.Sign(tun.core.PrivateKey(), partial[:])
bs := append([]byte{typeKeyLookup}, sig...) bs := append([]byte{typeKeyLookup}, sig...)
tun.core.SendOutOfBand(partial, bs) _ = tun.core.SendOutOfBand(partial, bs)
} }
func (tun *TunAdapter) sendKeyResponse(dest ed25519.PublicKey) { func (tun *TunAdapter) sendKeyResponse(dest ed25519.PublicKey) {
sig := ed25519.Sign(tun.core.PrivateKey(), dest[:]) sig := ed25519.Sign(tun.core.PrivateKey(), dest[:])
bs := append([]byte{typeKeyResponse}, sig...) bs := append([]byte{typeKeyResponse}, sig...)
tun.core.SendOutOfBand(dest, bs) _ = tun.core.SendOutOfBand(dest, bs)
} }
func (tun *TunAdapter) maxSessionMTU() uint64 { func (tun *TunAdapter) maxSessionMTU() uint64 {

View file

@ -40,26 +40,29 @@ const (
darwin_ND6_INFINITE_LIFETIME = 0xFFFFFFFF // netinet6/nd6.h darwin_ND6_INFINITE_LIFETIME = 0xFFFFFFFF // netinet6/nd6.h
) )
// nolint:structcheck
type in6_addrlifetime struct { type in6_addrlifetime struct {
ia6t_expire float64 ia6t_expire float64 // nolint:unused
ia6t_preferred float64 ia6t_preferred float64 // nolint:unused
ia6t_vltime uint32 ia6t_vltime uint32
ia6t_pltime uint32 ia6t_pltime uint32
} }
// nolint:structcheck
type sockaddr_in6 struct { type sockaddr_in6 struct {
sin6_len uint8 sin6_len uint8
sin6_family uint8 sin6_family uint8
sin6_port uint8 sin6_port uint8 // nolint:unused
sin6_flowinfo uint32 sin6_flowinfo uint32 // nolint:unused
sin6_addr [8]uint16 sin6_addr [8]uint16
sin6_scope_id uint32 sin6_scope_id uint32 // nolint:unused
} }
// nolint:structcheck
type in6_aliasreq struct { type in6_aliasreq struct {
ifra_name [16]byte ifra_name [16]byte
ifra_addr sockaddr_in6 ifra_addr sockaddr_in6
ifra_dstaddr sockaddr_in6 ifra_dstaddr sockaddr_in6 // nolint:unused
ifra_prefixmask sockaddr_in6 ifra_prefixmask sockaddr_in6
ifra_flags uint32 ifra_flags uint32
ifra_lifetime in6_addrlifetime ifra_lifetime in6_addrlifetime

View file

@ -2,14 +2,14 @@ package tuntap
// Out-of-band packet types // Out-of-band packet types
const ( const (
typeKeyDummy = iota typeKeyDummy = iota // nolint:deadcode,varcheck
typeKeyLookup typeKeyLookup
typeKeyResponse typeKeyResponse
) )
// In-band packet types // In-band packet types
const ( const (
typeSessionDummy = iota typeSessionDummy = iota // nolint:deadcode,varcheck
typeSessionTraffic typeSessionTraffic
typeSessionProto typeSessionProto
) )