From 3847e6afb8634a30cb52a0c71bf8420d20c61ed5 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 24 May 2018 00:36:07 +0100 Subject: [PATCH 01/14] Start de-debugging --- src/yggdrasil/admin.go | 3 +++ src/yggdrasil/core.go | 25 +++++++++++++++++++++++++ src/yggdrasil/router.go | 4 ++++ src/yggdrasil/switch.go | 3 +++ 4 files changed, 35 insertions(+) diff --git a/src/yggdrasil/admin.go b/src/yggdrasil/admin.go index 5bf9d3fa..378f951c 100644 --- a/src/yggdrasil/admin.go +++ b/src/yggdrasil/admin.go @@ -213,6 +213,9 @@ func (a *admin) init(c *Core, listenaddr string) { }, errors.New("Failed to remove allowed box pub key") } }) +} + +func (a *admin) start() { go a.listen() } diff --git a/src/yggdrasil/core.go b/src/yggdrasil/core.go index 7b077946..96397cf3 100644 --- a/src/yggdrasil/core.go +++ b/src/yggdrasil/core.go @@ -3,6 +3,8 @@ package yggdrasil import "io/ioutil" import "log" import "regexp" +import "net" +import "yggdrasil/config" type Core struct { // This is the main data structure that holds everything else for a node @@ -33,6 +35,29 @@ func (c *Core) Init() { c.init(bpub, bpriv, spub, spriv) } +func (c *Core) Run(nc *config.NodeConfig) { + var boxPub boxPubKey + var boxPriv boxPrivKey + var sigPub sigPubKey + var sigPriv sigPrivKey + copy(boxPub[:], nc.EncryptionPublicKey) + copy(boxPriv[:], nc.EncryptionPrivateKey) + copy(sigPub[:], nc.SigningPublicKey) + copy(sigPriv[:], nc.SigningPrivateKey) + + c.init(&boxPub, &boxPriv, &sigPub, &sigPriv) + + c.udp.init(c, nc.Listen) + c.tcp.init(c, nc.Listen) + c.admin.init(c, nc.AdminListen) + + c.multicast.start() + c.router.start() + c.switchTable.start() + c.tun.setup(nc.IfName, nc.IfTAPMode, net.IP(c.router.addr[:]).String(), nc.IfMTU) + c.admin.start() +} + func (c *Core) init(bpub *boxPubKey, bpriv *boxPrivKey, spub *sigPubKey, diff --git a/src/yggdrasil/router.go b/src/yggdrasil/router.go index ad11d6e7..3b90258b 100644 --- a/src/yggdrasil/router.go +++ b/src/yggdrasil/router.go @@ -64,6 +64,10 @@ func (r *router) init(core *Core) { r.core.tun.send = send r.reset = make(chan struct{}, 1) r.admin = make(chan func()) + // go r.mainLoop() +} + +func (r *router) start() { go r.mainLoop() } diff --git a/src/yggdrasil/switch.go b/src/yggdrasil/switch.go index a005b106..5f6c2b9b 100644 --- a/src/yggdrasil/switch.go +++ b/src/yggdrasil/switch.go @@ -167,6 +167,9 @@ func (t *switchTable) init(core *Core, key sigPubKey) { t.updater.Store(&sync.Once{}) t.table.Store(lookupTable{}) t.drop = make(map[sigPubKey]int64) +} + +func (t *switchTable) start() { doTicker := func() { ticker := time.NewTicker(time.Second) defer ticker.Stop() From eac1c85a6287a89b40633e3f634e882eda10514b Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 24 May 2018 11:31:31 +0100 Subject: [PATCH 02/14] No calls to debug.go from yggdrasil.go --- src/yggdrasil/admin.go | 3 +- src/yggdrasil/core.go | 140 ++++++++++++++++++++++++++++++------- src/yggdrasil/multicast.go | 9 +-- src/yggdrasil/router.go | 4 +- src/yggdrasil/switch.go | 3 +- src/yggdrasil/tcp.go | 7 +- src/yggdrasil/udp.go | 13 +++- yggdrasil.go | 115 ++++++++++-------------------- 8 files changed, 181 insertions(+), 113 deletions(-) diff --git a/src/yggdrasil/admin.go b/src/yggdrasil/admin.go index 378f951c..05c5eafb 100644 --- a/src/yggdrasil/admin.go +++ b/src/yggdrasil/admin.go @@ -215,8 +215,9 @@ func (a *admin) init(c *Core, listenaddr string) { }) } -func (a *admin) start() { +func (a *admin) start() error { go a.listen() + return nil } func (a *admin) listen() { diff --git a/src/yggdrasil/core.go b/src/yggdrasil/core.go index 96397cf3..d4a0c17c 100644 --- a/src/yggdrasil/core.go +++ b/src/yggdrasil/core.go @@ -1,6 +1,6 @@ package yggdrasil -import "io/ioutil" +// import "io/ioutil" import "log" import "regexp" import "net" @@ -35,29 +35,6 @@ func (c *Core) Init() { c.init(bpub, bpriv, spub, spriv) } -func (c *Core) Run(nc *config.NodeConfig) { - var boxPub boxPubKey - var boxPriv boxPrivKey - var sigPub sigPubKey - var sigPriv sigPrivKey - copy(boxPub[:], nc.EncryptionPublicKey) - copy(boxPriv[:], nc.EncryptionPrivateKey) - copy(sigPub[:], nc.SigningPublicKey) - copy(sigPriv[:], nc.SigningPrivateKey) - - c.init(&boxPub, &boxPriv, &sigPub, &sigPriv) - - c.udp.init(c, nc.Listen) - c.tcp.init(c, nc.Listen) - c.admin.init(c, nc.AdminListen) - - c.multicast.start() - c.router.start() - c.switchTable.start() - c.tun.setup(nc.IfName, nc.IfTAPMode, net.IP(c.router.addr[:]).String(), nc.IfMTU) - c.admin.start() -} - func (c *Core) init(bpub *boxPubKey, bpriv *boxPrivKey, spub *sigPubKey, @@ -67,7 +44,7 @@ func (c *Core) init(bpub *boxPubKey, // Start launches goroutines that depend on structs being set up // This is pretty much required to completely avoid race conditions util_initByteStore() - c.log = log.New(ioutil.Discard, "", 0) + // c.log = log.New(ioutil.Discard, "", 0) c.boxPub, c.boxPriv = *bpub, *bpriv c.sigPub, c.sigPriv = *spub, *spriv c.admin.core = c @@ -82,6 +59,79 @@ func (c *Core) init(bpub *boxPubKey, c.tun.init(c) } +func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error { + c.log = log + c.log.Println("Starting up...") + + udp := udpInterface{} + if err := udp.init(c, nc.Listen); err != nil { + c.log.Println("Failed to start UDP interface") + return err + } + c.udp = &udp + + tcp := tcpInterface{} + if err := tcp.init(c, nc.Listen); err != nil { + c.log.Println("Failed to start TCP interface") + return err + } + c.tcp = &tcp + + var boxPub boxPubKey + var boxPriv boxPrivKey + var sigPub sigPubKey + var sigPriv sigPrivKey + copy(boxPub[:], nc.EncryptionPublicKey) + copy(boxPriv[:], nc.EncryptionPrivateKey) + copy(sigPub[:], nc.SigningPublicKey) + copy(sigPriv[:], nc.SigningPrivateKey) + + c.init(&boxPub, &boxPriv, &sigPub, &sigPriv) + c.admin.init(c, nc.AdminListen) + + if err := c.router.start(); err != nil { + c.log.Println("Failed to start router") + return err + } + + if err := c.switchTable.start(); err != nil { + c.log.Println("Failed to start switch table ticker") + return err + } + + if err := c.tun.setup(nc.IfName, nc.IfTAPMode, net.IP(c.router.addr[:]).String(), nc.IfMTU); err != nil { + c.log.Println("Failed to start TUN/TAP") + return err + } + + if err := c.admin.start(); err != nil { + c.log.Println("Failed to start admin socket") + return err + } + + if err := c.multicast.start(); err != nil { + c.log.Println("Failed to start multicast interface") + return err + } + + c.log.Println("Startup complete") + return nil +} + +func (c *Core) Stop() { + c.log.Println("Stopping...") + c.tun.close() + c.log.Println("Goodbye!") +} + +func (c *Core) NewEncryptionKeys() (*boxPubKey, *boxPrivKey) { + return newBoxKeys() +} + +func (c *Core) NewSigningKeys() (*sigPubKey, *sigPrivKey) { + return newSigKeys() +} + func (c *Core) GetNodeID() *NodeID { return getNodeID(&c.boxPub) } @@ -97,3 +147,43 @@ func (c *Core) GetAddress() *address { func (c *Core) GetSubnet() *subnet { return address_subnetForNodeID(c.GetNodeID()) } + +func (c *Core) SetLogger(log *log.Logger) { + c.log = log +} + +func (c *Core) AddPeer(addr string) error { + return c.admin.addPeer(addr) +} + +func (c *Core) AddMulticastInterfaceExpr(expr *regexp.Regexp) { + c.ifceExpr = append(c.ifceExpr, expr) +} + +func (c *Core) AddAllowedEncryptionPublicKey(boxStr string) error { + return c.admin.addAllowedEncryptionPublicKey(boxStr) +} + +func (c *Core) GetTUNDefaultIfName() string { + return getDefaults().defaultIfName +} + +func (c *Core) GetTUNDefaultIfMTU() int { + return getDefaults().defaultIfMTU +} + +func (c *Core) GetTUNMaximumIfMTU() int { + return getDefaults().maximumIfMTU +} + +func (c *Core) GetTUNDefaultIfTAPMode() bool { + return getDefaults().defaultIfTAPMode +} + +func (c *Core) GetTUNIfName() string { + return c.tun.iface.Name() +} + +func (c *Core) GetTUNIfMTU() int { + return c.tun.mtu +} diff --git a/src/yggdrasil/multicast.go b/src/yggdrasil/multicast.go index afcf8b7f..6cb12bc4 100644 --- a/src/yggdrasil/multicast.go +++ b/src/yggdrasil/multicast.go @@ -44,19 +44,19 @@ func (m *multicast) init(core *Core) { m.core.log.Println("Found", len(m.interfaces), "multicast interface(s)") } -func (m *multicast) start() { +func (m *multicast) start() error { if len(m.core.ifceExpr) == 0 { m.core.log.Println("Multicast discovery is disabled") } else { m.core.log.Println("Multicast discovery is enabled") addr, err := net.ResolveUDPAddr("udp", m.groupAddr) if err != nil { - panic(err) + return err } listenString := fmt.Sprintf("[::]:%v", addr.Port) conn, err := net.ListenPacket("udp6", listenString) if err != nil { - panic(err) + return err } //defer conn.Close() // Let it close on its own when the application exits m.sock = ipv6.NewPacketConn(conn) @@ -68,6 +68,7 @@ func (m *multicast) start() { go m.listen() go m.announce() } + return nil } func (m *multicast) announce() { @@ -76,7 +77,7 @@ func (m *multicast) announce() { panic(err) } var anAddr net.TCPAddr - myAddr := m.core.DEBUG_getGlobalTCPAddr() + myAddr := m.core.tcp.getAddr() anAddr.Port = myAddr.Port destAddr, err := net.ResolveUDPAddr("udp6", m.groupAddr) if err != nil { diff --git a/src/yggdrasil/router.go b/src/yggdrasil/router.go index 3b90258b..545a15be 100644 --- a/src/yggdrasil/router.go +++ b/src/yggdrasil/router.go @@ -67,8 +67,10 @@ func (r *router) init(core *Core) { // go r.mainLoop() } -func (r *router) start() { +func (r *router) start() error { + r.core.log.Println("Starting router") go r.mainLoop() + return nil } func (r *router) mainLoop() { diff --git a/src/yggdrasil/switch.go b/src/yggdrasil/switch.go index 5f6c2b9b..1db63f61 100644 --- a/src/yggdrasil/switch.go +++ b/src/yggdrasil/switch.go @@ -169,7 +169,7 @@ func (t *switchTable) init(core *Core, key sigPubKey) { t.drop = make(map[sigPubKey]int64) } -func (t *switchTable) start() { +func (t *switchTable) start() error { doTicker := func() { ticker := time.NewTicker(time.Second) defer ticker.Stop() @@ -179,6 +179,7 @@ func (t *switchTable) start() { } } go doTicker() + return nil } func (t *switchTable) getLocator() switchLocator { diff --git a/src/yggdrasil/tcp.go b/src/yggdrasil/tcp.go index 869b6afd..14726df2 100644 --- a/src/yggdrasil/tcp.go +++ b/src/yggdrasil/tcp.go @@ -42,6 +42,10 @@ type tcpInfo struct { remoteAddr string } +func (iface *tcpInterface) getAddr() *net.TCPAddr { + return iface.serv.Addr().(*net.TCPAddr) +} + func (iface *tcpInterface) init(core *Core, addr string) (err error) { iface.core = core @@ -51,7 +55,8 @@ func (iface *tcpInterface) init(core *Core, addr string) (err error) { iface.conns = make(map[tcpInfo](chan struct{})) go iface.listener() } - return + + return err } func (iface *tcpInterface) listener() { diff --git a/src/yggdrasil/udp.go b/src/yggdrasil/udp.go index 81f5d38b..f2921f31 100644 --- a/src/yggdrasil/udp.go +++ b/src/yggdrasil/udp.go @@ -65,18 +65,25 @@ type udpKeys struct { sig sigPubKey } -func (iface *udpInterface) init(core *Core, addr string) { +func (iface *udpInterface) getAddr() *net.UDPAddr { + return iface.sock.LocalAddr().(*net.UDPAddr) +} + +func (iface *udpInterface) init(core *Core, addr string) error { iface.core = core udpAddr, err := net.ResolveUDPAddr("udp", addr) if err != nil { - panic(err) + return err + //panic(err) } iface.sock, err = net.ListenUDP("udp", udpAddr) if err != nil { - panic(err) + return err + // panic(err) } iface.conns = make(map[connAddr]*connInfo) go iface.reader() + return nil } func (iface *udpInterface) sendKeys(addr connAddr) { diff --git a/yggdrasil.go b/yggdrasil.go index 9f1aa2aa..87f7627d 100644 --- a/yggdrasil.go +++ b/yggdrasil.go @@ -31,63 +31,10 @@ type node struct { core Core } -func (n *node) init(cfg *nodeConfig, logger *log.Logger) { - boxPub, err := hex.DecodeString(cfg.EncryptionPublicKey) - if err != nil { - panic(err) - } - boxPriv, err := hex.DecodeString(cfg.EncryptionPrivateKey) - if err != nil { - panic(err) - } - sigPub, err := hex.DecodeString(cfg.SigningPublicKey) - if err != nil { - panic(err) - } - sigPriv, err := hex.DecodeString(cfg.SigningPrivateKey) - if err != nil { - panic(err) - } - n.core.DEBUG_init(boxPub, boxPriv, sigPub, sigPriv) - n.core.DEBUG_setLogger(logger) - - logger.Println("Starting interface...") - n.core.DEBUG_setupAndStartGlobalTCPInterface(cfg.Listen) // Listen for peers on TCP - n.core.DEBUG_setupAndStartGlobalUDPInterface(cfg.Listen) // Also listen on UDP, TODO allow separate configuration for ip/port to listen on each of these - logger.Println("Started interface") - logger.Println("Starting admin socket...") - n.core.DEBUG_setupAndStartAdminInterface(cfg.AdminListen) - logger.Println("Started admin socket") - for _, pBoxStr := range cfg.AllowedEncryptionPublicKeys { - n.core.DEBUG_addAllowedEncryptionPublicKey(pBoxStr) - } - for _, ll := range cfg.MulticastInterfaces { - ifceExpr, err := regexp.Compile(ll) - if err != nil { - panic(err) - } - n.core.DEBUG_setIfceExpr(ifceExpr) - } - n.core.DEBUG_setupAndStartMulticastInterface() - - go func() { - if len(cfg.Peers) == 0 { - return - } - for { - for _, p := range cfg.Peers { - n.core.DEBUG_addPeer(p) - time.Sleep(time.Second) - } - time.Sleep(time.Minute) - } - }() -} - func generateConfig(isAutoconf bool) *nodeConfig { core := Core{} - bpub, bpriv := core.DEBUG_newBoxKeys() - spub, spriv := core.DEBUG_newSigKeys() + bpub, bpriv := core.NewEncryptionKeys() + spub, spriv := core.NewSigningKeys() cfg := nodeConfig{} if isAutoconf { cfg.Listen = "[::]:0" @@ -103,9 +50,9 @@ func generateConfig(isAutoconf bool) *nodeConfig { cfg.Peers = []string{} cfg.AllowedEncryptionPublicKeys = []string{} cfg.MulticastInterfaces = []string{".*"} - cfg.IfName = core.DEBUG_GetTUNDefaultIfName() - cfg.IfMTU = core.DEBUG_GetTUNDefaultIfMTU() - cfg.IfTAPMode = core.DEBUG_GetTUNDefaultIfTAPMode() + cfg.IfName = core.GetTUNDefaultIfName() + cfg.IfMTU = core.GetTUNDefaultIfMTU() + cfg.IfTAPMode = core.GetTUNDefaultIfTAPMode() return &cfg } @@ -151,12 +98,12 @@ func main() { // For now we will do a little bit to help the user adjust their // configuration to match the new configuration format changes := map[string]string{ - "Multicast": "", - "LinkLocal": "MulticastInterfaces", - "BoxPub": "EncryptionPublicKey", - "BoxPriv": "EncryptionPrivateKey", - "SigPub": "SigningPublicKey", - "SigPriv": "SigningPrivateKey", + "Multicast": "", + "LinkLocal": "MulticastInterfaces", + "BoxPub": "EncryptionPublicKey", + "BoxPriv": "EncryptionPrivateKey", + "SigPub": "SigningPublicKey", + "SigPriv": "SigningPrivateKey", "AllowedBoxPubs": "AllowedEncryptionPublicKeys", } for from, to := range changes { @@ -200,21 +147,36 @@ func main() { go func() { log.Println(http.ListenAndServe("localhost:6060", nil)) }() } // Setup - logger.Println("Initializing...") n := node{} - n.init(cfg, logger) - if cfg.IfName != "none" { - logger.Println("Starting TUN/TAP...") - } else { - logger.Println("Not starting TUN/TAP") + for _, pBoxStr := range cfg.AllowedEncryptionPublicKeys { + n.core.AddAllowedEncryptionPublicKey(pBoxStr) } - //n.core.DEBUG_startTun(cfg.IfName) // 1280, the smallest supported MTU - n.core.DEBUG_startTunWithMTU(cfg.IfName, cfg.IfTAPMode, cfg.IfMTU) // Largest supported MTU - defer func() { - logger.Println("Closing...") - n.core.DEBUG_stopTun() + for _, ll := range cfg.MulticastInterfaces { + ifceExpr, err := regexp.Compile(ll) + if err != nil { + panic(err) + } + n.core.AddMulticastInterfaceExpr(ifceExpr) + } + if err := n.core.Start(cfg, logger); err != nil { + logger.Println("An error occured during startup") + panic(err) + } + go func() { + if len(cfg.Peers) == 0 { + return + } + for { + for _, p := range cfg.Peers { + n.core.AddPeer(p) + time.Sleep(time.Second) + } + time.Sleep(time.Minute) + } + }() + defer func() { + n.core.Stop() }() - logger.Println("Started...") address := (*n.core.GetAddress())[:] subnet := (*n.core.GetSubnet())[:] subnet = append(subnet, 0, 0, 0, 0, 0, 0, 0, 0) @@ -230,5 +192,4 @@ func main() { minwinsvc.SetOnExit(winTerminate) // Wait for the terminate/interrupt signal <-c - logger.Println("Stopping...") } From 196a14d8d2d3b29c2e4957d89fb480ed02e37ebf Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 24 May 2018 11:49:40 +0100 Subject: [PATCH 03/14] No DEBUG_ calls from src/yggdrasil --- src/yggdrasil/admin.go | 10 +++++----- src/yggdrasil/debug.go | 2 ++ src/yggdrasil/multicast.go | 4 ++-- src/yggdrasil/tcp.go | 23 +++++++++++++++++++++++ src/yggdrasil/udp.go | 15 +++++++++++++++ 5 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/yggdrasil/admin.go b/src/yggdrasil/admin.go index 05c5eafb..26d2db99 100644 --- a/src/yggdrasil/admin.go +++ b/src/yggdrasil/admin.go @@ -360,11 +360,11 @@ func (a *admin) addPeer(addr string) error { if err == nil { switch strings.ToLower(u.Scheme) { case "tcp": - a.core.DEBUG_addTCPConn(u.Host) + a.core.tcp.connect(u.Host) case "udp": - a.core.DEBUG_maybeSendUDPKeys(u.Host) + a.core.udp.connect(u.Host) case "socks": - a.core.DEBUG_addSOCKSConn(u.Host, u.Path[1:]) + a.core.tcp.connectSOCKS(u.Host, u.Path[1:]) default: return errors.New("invalid peer: " + addr) } @@ -372,13 +372,13 @@ func (a *admin) addPeer(addr string) error { // no url scheme provided addr = strings.ToLower(addr) if strings.HasPrefix(addr, "udp:") { - a.core.DEBUG_maybeSendUDPKeys(addr[4:]) + a.core.udp.connect(addr[4:]) return nil } else { if strings.HasPrefix(addr, "tcp:") { addr = addr[4:] } - a.core.DEBUG_addTCPConn(addr) + a.core.tcp.connect(addr) return nil } return errors.New("invalid peer: " + addr) diff --git a/src/yggdrasil/debug.go b/src/yggdrasil/debug.go index a86f2225..2334b89d 100644 --- a/src/yggdrasil/debug.go +++ b/src/yggdrasil/debug.go @@ -1,3 +1,5 @@ +// +build !linux,!darwin,!windows,!openbsd,!freebsd,!netbsd + package yggdrasil // These are functions that should not exist diff --git a/src/yggdrasil/multicast.go b/src/yggdrasil/multicast.go index 6cb12bc4..d20a0b82 100644 --- a/src/yggdrasil/multicast.go +++ b/src/yggdrasil/multicast.go @@ -68,7 +68,7 @@ func (m *multicast) start() error { go m.listen() go m.announce() } - return nil + return nil } func (m *multicast) announce() { @@ -152,7 +152,7 @@ func (m *multicast) listen() { saddr := addr.String() //if _, isIn := n.peers[saddr]; isIn { continue } //n.peers[saddr] = struct{}{} - m.core.DEBUG_addTCPConn(saddr) + m.core.tcp.connect(saddr) //fmt.Println("DEBUG:", "added multicast peer:", saddr) } } diff --git a/src/yggdrasil/tcp.go b/src/yggdrasil/tcp.go index 14726df2..4eb47bab 100644 --- a/src/yggdrasil/tcp.go +++ b/src/yggdrasil/tcp.go @@ -16,6 +16,7 @@ import "errors" import "sync" import "fmt" import "bufio" +import "golang.org/x/net/proxy" const tcp_msgSize = 2048 + 65535 // TODO figure out what makes sense @@ -46,6 +47,28 @@ func (iface *tcpInterface) getAddr() *net.TCPAddr { return iface.serv.Addr().(*net.TCPAddr) } +func (iface *tcpInterface) connect(addr string) { + iface.call(addr) +} + +func (iface *tcpInterface) connectSOCKS(socksaddr, peeraddr string) { + go func() { + dialer, err := proxy.SOCKS5("tcp", socksaddr, nil, proxy.Direct) + if err == nil { + conn, err := dialer.Dial("tcp", peeraddr) + if err == nil { + iface.callWithConn(&wrappedConn{ + c: conn, + raddr: &wrappedAddr{ + network: "tcp", + addr: peeraddr, + }, + }) + } + } + }() +} + func (iface *tcpInterface) init(core *Core, addr string) (err error) { iface.core = core diff --git a/src/yggdrasil/udp.go b/src/yggdrasil/udp.go index f2921f31..63b76736 100644 --- a/src/yggdrasil/udp.go +++ b/src/yggdrasil/udp.go @@ -69,6 +69,21 @@ func (iface *udpInterface) getAddr() *net.UDPAddr { return iface.sock.LocalAddr().(*net.UDPAddr) } +func (iface *udpInterface) connect(saddr string) { + udpAddr, err := net.ResolveUDPAddr("udp", saddr) + if err != nil { + panic(err) + } + var addr connAddr + addr.fromUDPAddr(udpAddr) + iface.mutex.RLock() + _, isIn := iface.conns[addr] + iface.mutex.RUnlock() + if !isIn { + iface.sendKeys(addr) + } +} + func (iface *udpInterface) init(core *Core, addr string) error { iface.core = core udpAddr, err := net.ResolveUDPAddr("udp", addr) From f40525693e17a05a6743e170b7058b08bcec7e64 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 24 May 2018 12:17:55 +0100 Subject: [PATCH 04/14] Add godoc to core.go --- src/yggdrasil/core.go | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/yggdrasil/core.go b/src/yggdrasil/core.go index d4a0c17c..4d594f27 100644 --- a/src/yggdrasil/core.go +++ b/src/yggdrasil/core.go @@ -6,6 +6,8 @@ import "regexp" import "net" import "yggdrasil/config" +// The Core object represents the Yggdrasil node. You should create a Core +// object for each Yggdrasil node you plan to run. type Core struct { // This is the main data structure that holds everything else for a node boxPub boxPubKey @@ -28,8 +30,9 @@ type Core struct { ifceExpr []*regexp.Regexp // the zone of link-local IPv6 peers must match this } +// This function is only called by the simulator to set up a node with random +// keys. It should not be used and may be removed in the future. func (c *Core) Init() { - // Only called by the simulator, to set up nodes with random keys bpub, bpriv := newBoxKeys() spub, spriv := newSigKeys() c.init(bpub, bpriv, spub, spriv) @@ -59,6 +62,10 @@ func (c *Core) init(bpub *boxPubKey, c.tun.init(c) } +// Starts up Yggdrasil using the provided NodeConfig, and outputs debug logging +// through the provided log.Logger. The started stack will include TCP and UDP +// sockets, a multicast discovery socket, an admin socket, router, switch and +// DHT node. func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error { c.log = log c.log.Println("Starting up...") @@ -118,72 +125,97 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error { return nil } +// Stops the Yggdrasil node. func (c *Core) Stop() { c.log.Println("Stopping...") c.tun.close() - c.log.Println("Goodbye!") } +// Generates a new encryption keypair. The encryption keys are used to +// encrypt traffic and to derive the IPv6 address/subnet of the node. func (c *Core) NewEncryptionKeys() (*boxPubKey, *boxPrivKey) { return newBoxKeys() } +// Generates a new signing keypair. The signing keys are used to derive the +// structure of the spanning tree. func (c *Core) NewSigningKeys() (*sigPubKey, *sigPrivKey) { return newSigKeys() } +// Gets the node ID. func (c *Core) GetNodeID() *NodeID { return getNodeID(&c.boxPub) } +// Gets the tree ID. func (c *Core) GetTreeID() *TreeID { return getTreeID(&c.sigPub) } +// Gets the IPv6 address of the Yggdrasil node. This is always a /128. func (c *Core) GetAddress() *address { return address_addrForNodeID(c.GetNodeID()) } +// Gets the routed IPv6 subnet of the Yggdrasil node. This is always a /64. func (c *Core) GetSubnet() *subnet { return address_subnetForNodeID(c.GetNodeID()) } +// Sets the output logger of the Yggdrasil node after startup. This may be +// useful if you want to redirect the output later. func (c *Core) SetLogger(log *log.Logger) { c.log = log } +// Adds a peer. This should be specified in the peer URI format, i.e. +// tcp://a.b.c.d:e, udp://a.b.c.d:e, socks://a.b.c.d:e/f.g.h.i:j func (c *Core) AddPeer(addr string) error { return c.admin.addPeer(addr) } +// Adds an expression to select multicast interfaces for peer discovery. This +// should be done before calling Start. This function can be called multiple +// times to add multiple search expressions. func (c *Core) AddMulticastInterfaceExpr(expr *regexp.Regexp) { c.ifceExpr = append(c.ifceExpr, expr) } +// Adds an allowed public key. This allow peerings to be restricted only to +// keys that you have selected. func (c *Core) AddAllowedEncryptionPublicKey(boxStr string) error { return c.admin.addAllowedEncryptionPublicKey(boxStr) } +// Gets the default TUN/TAP interface name for your platform. func (c *Core) GetTUNDefaultIfName() string { return getDefaults().defaultIfName } +// Gets the default TUN/TAP interface MTU for your platform. This can be as high +// as 65535, depending on platform, but is never lower than 1280. func (c *Core) GetTUNDefaultIfMTU() int { return getDefaults().defaultIfMTU } +// Gets the maximum supported TUN/TAP interface MTU for your platform. This +// can be as high as 65535, depending on platform, but is never lower than 1280. func (c *Core) GetTUNMaximumIfMTU() int { return getDefaults().maximumIfMTU } +// Gets the default TUN/TAP interface mode for your platform. func (c *Core) GetTUNDefaultIfTAPMode() bool { return getDefaults().defaultIfTAPMode } +// Gets the current TUN/TAP interface name. func (c *Core) GetTUNIfName() string { return c.tun.iface.Name() } +// Gets the current TUN/TAP interface MTU. func (c *Core) GetTUNIfMTU() int { return c.tun.mtu } From b019297458032b0ff7e6694b4a3ac2f91314e7b1 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 24 May 2018 12:40:02 +0100 Subject: [PATCH 05/14] Document yggdrasil.go --- yggdrasil.go | 84 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 72 insertions(+), 12 deletions(-) diff --git a/yggdrasil.go b/yggdrasil.go index 87f7627d..385878a5 100644 --- a/yggdrasil.go +++ b/yggdrasil.go @@ -31,10 +31,20 @@ type node struct { core Core } +// Generates default configuration. This is used when outputting the -genconf +// parameter and also when using -autoconf. The isAutoconf flag is used to +// determine whether the operating system should select a free port by itself +// (which guarantees that there will not be a conflict with any other services) +// or whether to generate a random port number. The only side effect of setting +// isAutoconf is that the TCP and UDP ports will likely end up with different +// port numbers. func generateConfig(isAutoconf bool) *nodeConfig { + // Create a new core. core := Core{} + // Generate encryption keys. bpub, bpriv := core.NewEncryptionKeys() spub, spriv := core.NewSigningKeys() + // Create a node configuration and populate it. cfg := nodeConfig{} if isAutoconf { cfg.Listen = "[::]:0" @@ -57,6 +67,8 @@ func generateConfig(isAutoconf bool) *nodeConfig { return &cfg } +// Generates a new configuration and returns it in HJSON format. This is used +// with -genconf. func doGenconf() string { cfg := generateConfig(false) bs, err := hjson.Marshal(cfg) @@ -66,37 +78,51 @@ func doGenconf() string { return string(bs) } -var pprof = flag.Bool("pprof", false, "Run pprof, see http://localhost:6060/debug/pprof/") -var genconf = flag.Bool("genconf", false, "print a new config to stdout") -var useconf = flag.Bool("useconf", false, "read config from stdin") -var useconffile = flag.String("useconffile", "", "read config from specified file path") -var normaliseconf = flag.Bool("normaliseconf", false, "use in combination with either -useconf or -useconffile, outputs your configuration normalised") -var autoconf = flag.Bool("autoconf", false, "automatic mode (dynamic IP, peer with IPv6 neighbors)") - +// The main function is responsible for configuring and starting Yggdrasil. func main() { + // Configure the command line parameters. + pprof := flag.Bool("pprof", false, "Run pprof, see http://localhost:6060/debug/pprof/") + genconf := flag.Bool("genconf", false, "print a new config to stdout") + useconf := flag.Bool("useconf", false, "read config from stdin") + useconffile := flag.String("useconffile", "", "read config from specified file path") + normaliseconf := flag.Bool("normaliseconf", false, "use in combination with either -useconf or -useconffile, outputs your configuration normalised") + autoconf := flag.Bool("autoconf", false, "automatic mode (dynamic IP, peer with IPv6 neighbors)") flag.Parse() + var cfg *nodeConfig switch { case *autoconf: + // Use an autoconf-generated config, this will give us random keys and + // port numbers, and will use an automatically selected TUN/TAP interface. cfg = generateConfig(true) case *useconffile != "" || *useconf: + // Use a configuration file. If -useconf, the configuration will be read + // from stdin. If -useconffile, the configuration will be read from the + // filesystem. var config []byte var err error if *useconffile != "" { + // Read the file from the filesystem config, err = ioutil.ReadFile(*useconffile) } else { + // Read the file from stdin. config, err = ioutil.ReadAll(os.Stdin) } if err != nil { panic(err) } + // Generate a new configuration - this gives us a set of sane defaults - + // then parse the configuration we loaded above on top of it. The effect + // of this is that any configuration item that is missing from the provided + // configuration will use a sane default. cfg = generateConfig(false) var dat map[string]interface{} if err := hjson.Unmarshal(config, &dat); err != nil { panic(err) } // For now we will do a little bit to help the user adjust their - // configuration to match the new configuration format + // configuration to match the new configuration format, as some of the key + // names have changed recently. changes := map[string]string{ "Multicast": "", "LinkLocal": "MulticastInterfaces", @@ -106,6 +132,7 @@ func main() { "SigPriv": "SigningPrivateKey", "AllowedBoxPubs": "AllowedEncryptionPublicKeys", } + // Loop over the mappings aove and see if we have anything to fix. for from, to := range changes { if _, ok := dat[from]; ok { if to == "" { @@ -116,15 +143,24 @@ func main() { if !*normaliseconf { log.Println("Warning: Deprecated config option", from, "- please rename to", to) } + // If the configuration file doesn't already contain a line with the + // new name then set it to the old value. This makes sure that we + // don't overwrite something that was put there intentionally. if _, ok := dat[to]; !ok { dat[to] = dat[from] } } } } + // Overlay our newly mapped configuration onto the autoconf node config that + // we generated above. if err = mapstructure.Decode(dat, &cfg); err != nil { panic(err) } + // If the -normaliseconf option was specified then remarshal the above + // configuration and print it back to stdout. This lets the user update + // their configuration file with newly mapped names (like above) or to + // convert from plain JSON to commented HJSON. if *normaliseconf { bs, err := hjson.Marshal(cfg) if err != nil { @@ -134,23 +170,35 @@ func main() { return } case *genconf: + // Generate a new configuration and print it to stdout. fmt.Println(doGenconf()) default: + // No flags were provided, therefore print the list of flags to stdout. flag.PrintDefaults() } + // Have we got a working configuration? If we don't then it probably means + // that neither -autoconf, -useconf or -useconffile were set above. Stop + // if we don't. if cfg == nil { return } + // Create a new logger that logs output to stdout. logger := log.New(os.Stdout, "", log.Flags()) + // If the -pprof flag was provided then start the pprof service on port 6060. if *pprof { runtime.SetBlockProfileRate(1) go func() { log.Println(http.ListenAndServe("localhost:6060", nil)) }() } - // Setup + // Setup the Yggdrasil node itself. The node{} type includes a Core, so we + // don't need to create this manually. n := node{} + // Check to see if any allowed encryption keys were provided in the config. + // If they were then set them now. for _, pBoxStr := range cfg.AllowedEncryptionPublicKeys { n.core.AddAllowedEncryptionPublicKey(pBoxStr) } + // Check to see if any multicast interface expressions were provided in the + // config. If they were then set them now. for _, ll := range cfg.MulticastInterfaces { ifceExpr, err := regexp.Compile(ll) if err != nil { @@ -158,10 +206,17 @@ func main() { } n.core.AddMulticastInterfaceExpr(ifceExpr) } + // Now that we have a working configuration, and we have provided any allowed + // encryption keys or multicast interface expressions, we can now actually + // start Yggdrasil. This will start the router, switch, DHT node, TCP and UDP + // sockets, TUN/TAP adapter and multicast discovery port. if err := n.core.Start(cfg, logger); err != nil { logger.Println("An error occured during startup") panic(err) } + // If any static peers were provided in the configuration above then we should + // configure them. The loop ensures that disconnected peers will eventually + // be reconnected with. go func() { if len(cfg.Peers) == 0 { return @@ -174,22 +229,27 @@ func main() { time.Sleep(time.Minute) } }() + // The Stop function ensures that the TUN/TAP adapter is correctly shut down + // before the program exits. defer func() { n.core.Stop() }() + // Make some nice output that tells us what our IPv6 address and subnet are. + // This is just logged to stdout for the user. address := (*n.core.GetAddress())[:] subnet := (*n.core.GetSubnet())[:] subnet = append(subnet, 0, 0, 0, 0, 0, 0, 0, 0) logger.Printf("Your IPv6 address is %s", net.IP(address).String()) logger.Printf("Your IPv6 subnet is %s/64", net.IP(subnet).String()) - // Catch interrupt to exit gracefully + // Catch interrupts from the operating system to exit gracefully. c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt, syscall.SIGTERM) - // Create a function to capture the service being stopped on Windows + // Create a function to capture the service being stopped on Windows. winTerminate := func() { c <- os.Interrupt } minwinsvc.SetOnExit(winTerminate) - // Wait for the terminate/interrupt signal + // Wait for the terminate/interrupt signal. Once a signal is received, the + // deferred Stop function above will run which will shut down TUN/TAP. <-c } From 9920b556a03c95ac0a956ab676aeac7bcb460b8a Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 24 May 2018 14:19:42 +0100 Subject: [PATCH 06/14] Still build debug.go --- src/yggdrasil/debug.go | 2 -- src/yggdrasil/tcp.go | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/yggdrasil/debug.go b/src/yggdrasil/debug.go index 2334b89d..a86f2225 100644 --- a/src/yggdrasil/debug.go +++ b/src/yggdrasil/debug.go @@ -1,5 +1,3 @@ -// +build !linux,!darwin,!windows,!openbsd,!freebsd,!netbsd - package yggdrasil // These are functions that should not exist diff --git a/src/yggdrasil/tcp.go b/src/yggdrasil/tcp.go index 4eb47bab..17d52468 100644 --- a/src/yggdrasil/tcp.go +++ b/src/yggdrasil/tcp.go @@ -302,12 +302,14 @@ func (iface *tcpInterface) reader(sock net.Conn, in func([]byte)) { sock.SetReadDeadline(timeout) n, err := sock.Read(bs[len(frag):]) if err != nil || n == 0 { + // iface.core.log.Println(err) break } frag = bs[:len(frag)+n] for { msg, ok, err := tcp_chop_msg(&frag) if err != nil { + // iface.core.log.Println(err) return } if !ok { From b252854d21c13412d3f850ecd00d04de22aa96e9 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 24 May 2018 14:30:42 +0100 Subject: [PATCH 07/14] Fix ioutil output for sim --- src/yggdrasil/core.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/yggdrasil/core.go b/src/yggdrasil/core.go index 4d594f27..0527b54f 100644 --- a/src/yggdrasil/core.go +++ b/src/yggdrasil/core.go @@ -1,6 +1,6 @@ package yggdrasil -// import "io/ioutil" +import "io/ioutil" import "log" import "regexp" import "net" @@ -47,7 +47,9 @@ func (c *Core) init(bpub *boxPubKey, // Start launches goroutines that depend on structs being set up // This is pretty much required to completely avoid race conditions util_initByteStore() - // c.log = log.New(ioutil.Discard, "", 0) + if c.log == nil { + c.log = log.New(ioutil.Discard, "", 0) + } c.boxPub, c.boxPriv = *bpub, *bpriv c.sigPub, c.sigPriv = *spub, *spriv c.admin.core = c From b5057d60adcbd438b5db80cde812e2c419e22140 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 24 May 2018 15:05:12 +0100 Subject: [PATCH 08/14] Fix enabling/disabling multicast --- src/yggdrasil/multicast.go | 4 ++++ yggdrasil.go | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/yggdrasil/multicast.go b/src/yggdrasil/multicast.go index d20a0b82..f3355916 100644 --- a/src/yggdrasil/multicast.go +++ b/src/yggdrasil/multicast.go @@ -16,6 +16,10 @@ type multicast struct { func (m *multicast) init(core *Core) { m.core = core m.groupAddr = "[ff02::114]:9001" + // Check if we've been given any expressions + if len(m.core.ifceExpr) == 0 { + return + } // Ask the system for network interfaces allifaces, err := net.Interfaces() if err != nil { diff --git a/yggdrasil.go b/yggdrasil.go index 385878a5..4f98b6a8 100644 --- a/yggdrasil.go +++ b/yggdrasil.go @@ -48,9 +48,11 @@ func generateConfig(isAutoconf bool) *nodeConfig { cfg := nodeConfig{} if isAutoconf { cfg.Listen = "[::]:0" + cfg.MulticastInterfaces = []string{".*"} } else { r1 := rand.New(rand.NewSource(time.Now().UnixNano())) cfg.Listen = fmt.Sprintf("[::]:%d", r1.Intn(65534-32768)+32768) + cfg.MulticastInterfaces = []string{} } cfg.AdminListen = "[::1]:9001" cfg.EncryptionPublicKey = hex.EncodeToString(bpub[:]) @@ -59,7 +61,6 @@ func generateConfig(isAutoconf bool) *nodeConfig { cfg.SigningPrivateKey = hex.EncodeToString(spriv[:]) cfg.Peers = []string{} cfg.AllowedEncryptionPublicKeys = []string{} - cfg.MulticastInterfaces = []string{".*"} cfg.IfName = core.GetTUNDefaultIfName() cfg.IfMTU = core.GetTUNDefaultIfMTU() cfg.IfTAPMode = core.GetTUNDefaultIfTAPMode() @@ -71,6 +72,7 @@ func generateConfig(isAutoconf bool) *nodeConfig { // with -genconf. func doGenconf() string { cfg := generateConfig(false) + cfg.MulticastInterfaces = append(cfg.MulticastInterfaces, ".*") bs, err := hjson.Marshal(cfg) if err != nil { panic(err) From c5782ca00a26f1ba86ebd90c18cc17963b3b8a0a Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 24 May 2018 15:30:35 +0100 Subject: [PATCH 09/14] Improve API for GetAddress and GetSubnet --- src/yggdrasil/admin.go | 7 ++----- src/yggdrasil/core.go | 13 ++++++++----- src/yggdrasil/multicast.go | 10 +++++----- src/yggdrasil/tcp.go | 4 ++-- yggdrasil.go | 10 ++++------ 5 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/yggdrasil/admin.go b/src/yggdrasil/admin.go index 26d2db99..05e5c9a1 100644 --- a/src/yggdrasil/admin.go +++ b/src/yggdrasil/admin.go @@ -425,13 +425,10 @@ func (a *admin) startTunWithMTU(ifname string, iftapmode bool, ifmtu int) error func (a *admin) getData_getSelf() *admin_nodeInfo { table := a.core.switchTable.table.Load().(lookupTable) - addr := (*a.core.GetAddress())[:] - subnet := (*a.core.GetSubnet())[:] - subnet = append(subnet, 0, 0, 0, 0, 0, 0, 0, 0) coords := table.self.getCoords() self := admin_nodeInfo{ - {"ip", net.IP(addr[:]).String()}, - {"subnet", fmt.Sprintf("%s/64", net.IP(subnet[:]).String())}, + {"ip", a.core.GetAddress().String()}, + {"subnet", a.core.GetSubnet().String()}, {"coords", fmt.Sprint(coords)}, } return &self diff --git a/src/yggdrasil/core.go b/src/yggdrasil/core.go index 0527b54f..a4b50fdb 100644 --- a/src/yggdrasil/core.go +++ b/src/yggdrasil/core.go @@ -48,7 +48,7 @@ func (c *Core) init(bpub *boxPubKey, // This is pretty much required to completely avoid race conditions util_initByteStore() if c.log == nil { - c.log = log.New(ioutil.Discard, "", 0) + c.log = log.New(ioutil.Discard, "", 0) } c.boxPub, c.boxPriv = *bpub, *bpriv c.sigPub, c.sigPriv = *spub, *spriv @@ -156,13 +156,16 @@ func (c *Core) GetTreeID() *TreeID { } // Gets the IPv6 address of the Yggdrasil node. This is always a /128. -func (c *Core) GetAddress() *address { - return address_addrForNodeID(c.GetNodeID()) +func (c *Core) GetAddress() *net.IP { + address := net.IP(address_addrForNodeID(c.GetNodeID())[:]) + return &address } // Gets the routed IPv6 subnet of the Yggdrasil node. This is always a /64. -func (c *Core) GetSubnet() *subnet { - return address_subnetForNodeID(c.GetNodeID()) +func (c *Core) GetSubnet() *net.IPNet { + subnet := address_subnetForNodeID(c.GetNodeID())[:] + subnet = append(subnet, 0, 0, 0, 0, 0, 0, 0, 0) + return &net.IPNet{ IP: subnet, Mask: net.CIDRMask(64, 128) } } // Sets the output logger of the Yggdrasil node after startup. This may be diff --git a/src/yggdrasil/multicast.go b/src/yggdrasil/multicast.go index f3355916..c86159c7 100644 --- a/src/yggdrasil/multicast.go +++ b/src/yggdrasil/multicast.go @@ -16,10 +16,10 @@ type multicast struct { func (m *multicast) init(core *Core) { m.core = core m.groupAddr = "[ff02::114]:9001" - // Check if we've been given any expressions - if len(m.core.ifceExpr) == 0 { - return - } + // Check if we've been given any expressions + if len(m.core.ifceExpr) == 0 { + return + } // Ask the system for network interfaces allifaces, err := net.Interfaces() if err != nil { @@ -72,7 +72,7 @@ func (m *multicast) start() error { go m.listen() go m.announce() } - return nil + return nil } func (m *multicast) announce() { diff --git a/src/yggdrasil/tcp.go b/src/yggdrasil/tcp.go index 17d52468..c152d0d1 100644 --- a/src/yggdrasil/tcp.go +++ b/src/yggdrasil/tcp.go @@ -302,14 +302,14 @@ func (iface *tcpInterface) reader(sock net.Conn, in func([]byte)) { sock.SetReadDeadline(timeout) n, err := sock.Read(bs[len(frag):]) if err != nil || n == 0 { - // iface.core.log.Println(err) + // iface.core.log.Println(err) break } frag = bs[:len(frag)+n] for { msg, ok, err := tcp_chop_msg(&frag) if err != nil { - // iface.core.log.Println(err) + // iface.core.log.Println(err) return } if !ok { diff --git a/yggdrasil.go b/yggdrasil.go index 4f98b6a8..8a8ab2ef 100644 --- a/yggdrasil.go +++ b/yggdrasil.go @@ -4,7 +4,6 @@ import "encoding/hex" import "flag" import "fmt" import "io/ioutil" -import "net" import "os" import "os/signal" import "syscall" @@ -238,11 +237,10 @@ func main() { }() // Make some nice output that tells us what our IPv6 address and subnet are. // This is just logged to stdout for the user. - address := (*n.core.GetAddress())[:] - subnet := (*n.core.GetSubnet())[:] - subnet = append(subnet, 0, 0, 0, 0, 0, 0, 0, 0) - logger.Printf("Your IPv6 address is %s", net.IP(address).String()) - logger.Printf("Your IPv6 subnet is %s/64", net.IP(subnet).String()) + address := n.core.GetAddress() + subnet := n.core.GetSubnet() + logger.Printf("Your IPv6 address is %s", address.String()) + logger.Printf("Your IPv6 subnet is %s", subnet.String()) // Catch interrupts from the operating system to exit gracefully. c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt, syscall.SIGTERM) From 98051d920744478e8bc17df67dd15b1a58d3634d Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sat, 26 May 2018 10:31:25 +0100 Subject: [PATCH 10/14] Fix public/private key encoding --- src/yggdrasil/core.go | 47 +++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/src/yggdrasil/core.go b/src/yggdrasil/core.go index a4b50fdb..907db6a8 100644 --- a/src/yggdrasil/core.go +++ b/src/yggdrasil/core.go @@ -4,6 +4,7 @@ import "io/ioutil" import "log" import "regexp" import "net" +import "encoding/hex" import "yggdrasil/config" // The Core object represents the Yggdrasil node. You should create a Core @@ -72,12 +73,33 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error { c.log = log c.log.Println("Starting up...") - udp := udpInterface{} - if err := udp.init(c, nc.Listen); err != nil { - c.log.Println("Failed to start UDP interface") + var boxPub boxPubKey + var boxPriv boxPrivKey + var sigPub sigPubKey + var sigPriv sigPrivKey + boxPubHex, err := hex.DecodeString(nc.EncryptionPublicKey) + if err != nil { return err } - c.udp = &udp + boxPrivHex, err := hex.DecodeString(nc.EncryptionPrivateKey) + if err != nil { + return err + } + sigPubHex, err := hex.DecodeString(nc.SigningPublicKey) + if err != nil { + return err + } + sigPrivHex, err := hex.DecodeString(nc.SigningPrivateKey) + if err != nil { + return err + } + copy(boxPub[:], boxPubHex) + copy(boxPriv[:], boxPrivHex) + copy(sigPub[:], sigPubHex) + copy(sigPriv[:], sigPrivHex) + + c.init(&boxPub, &boxPriv, &sigPub, &sigPriv) + c.admin.init(c, nc.AdminListen) tcp := tcpInterface{} if err := tcp.init(c, nc.Listen); err != nil { @@ -86,17 +108,12 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error { } c.tcp = &tcp - var boxPub boxPubKey - var boxPriv boxPrivKey - var sigPub sigPubKey - var sigPriv sigPrivKey - copy(boxPub[:], nc.EncryptionPublicKey) - copy(boxPriv[:], nc.EncryptionPrivateKey) - copy(sigPub[:], nc.SigningPublicKey) - copy(sigPriv[:], nc.SigningPrivateKey) - - c.init(&boxPub, &boxPriv, &sigPub, &sigPriv) - c.admin.init(c, nc.AdminListen) + udp := udpInterface{} + if err := udp.init(c, nc.Listen); err != nil { + c.log.Println("Failed to start UDP interface") + return err + } + c.udp = &udp if err := c.router.start(); err != nil { c.log.Println("Failed to start router") From ef2ed4b04a52b5b6cb9bd452bf1324425cd0bcb1 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sat, 26 May 2018 10:48:16 +0100 Subject: [PATCH 11/14] Start router/switch table ticker for sim --- src/yggdrasil/debug.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/yggdrasil/debug.go b/src/yggdrasil/debug.go index a86f2225..56173c5d 100644 --- a/src/yggdrasil/debug.go +++ b/src/yggdrasil/debug.go @@ -279,6 +279,14 @@ func (c *Core) DEBUG_init(bpub []byte, copy(sigPub[:], spub) copy(sigPriv[:], spriv) c.init(&boxPub, &boxPriv, &sigPub, &sigPriv) + + if err := c.router.start(); err != nil { + panic(err) + } + + if err := c.switchTable.start(); err != nil { + panic(err) + } } //////////////////////////////////////////////////////////////////////////////// From 12cba9dac91e4da9720c3662e5b267bca7e1ac7c Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sat, 26 May 2018 20:59:15 +0100 Subject: [PATCH 12/14] Fix passing CIDR to tun.setup --- src/yggdrasil/core.go | 3 ++- yggdrasil.go | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/yggdrasil/core.go b/src/yggdrasil/core.go index 907db6a8..55306197 100644 --- a/src/yggdrasil/core.go +++ b/src/yggdrasil/core.go @@ -125,7 +125,8 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error { return err } - if err := c.tun.setup(nc.IfName, nc.IfTAPMode, net.IP(c.router.addr[:]).String(), nc.IfMTU); err != nil { + ip := net.IP(c.router.addr[:]).String() + if err := c.tun.setup(nc.IfName, nc.IfTAPMode, fmt.Sprintf("%s/8", ip), nc.IfMTU); err != nil { c.log.Println("Failed to start TUN/TAP") return err } diff --git a/yggdrasil.go b/yggdrasil.go index 8a8ab2ef..72cacb05 100644 --- a/yggdrasil.go +++ b/yggdrasil.go @@ -212,7 +212,7 @@ func main() { // start Yggdrasil. This will start the router, switch, DHT node, TCP and UDP // sockets, TUN/TAP adapter and multicast discovery port. if err := n.core.Start(cfg, logger); err != nil { - logger.Println("An error occured during startup") + logger.Println("An error occurred during startup") panic(err) } // If any static peers were provided in the configuration above then we should From 21c39e2c814758615efaf015f7c1b4815c1e609f Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sat, 26 May 2018 21:38:29 +0100 Subject: [PATCH 13/14] Fix accidental truncation of address on macOS and BSD --- src/yggdrasil/tun_bsd.go | 2 +- src/yggdrasil/tun_darwin.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/yggdrasil/tun_bsd.go b/src/yggdrasil/tun_bsd.go index 5dbdd7d7..721b6778 100644 --- a/src/yggdrasil/tun_bsd.go +++ b/src/yggdrasil/tun_bsd.go @@ -137,7 +137,7 @@ func (tun *tunDevice) setupAddress(addr string) error { copy(ar.ifr_name[:], tun.iface.Name()) ar.ifru_addr.sin6_len = uint8(unsafe.Sizeof(ar.ifru_addr)) ar.ifru_addr.sin6_family = unix.AF_INET6 - parts := strings.Split(strings.TrimRight(addr, "/8"), ":") + parts := strings.Split(strings.Split(addr, "/")[0], ":") for i := 0; i < 8; i++ { addr, _ := strconv.ParseUint(parts[i], 16, 16) b := make([]byte, 16) diff --git a/src/yggdrasil/tun_darwin.go b/src/yggdrasil/tun_darwin.go index 94a63de2..72b9cf08 100644 --- a/src/yggdrasil/tun_darwin.go +++ b/src/yggdrasil/tun_darwin.go @@ -84,7 +84,7 @@ func (tun *tunDevice) setupAddress(addr string) error { ar.ifra_addr.sin6_len = uint8(unsafe.Sizeof(ar.ifra_addr)) ar.ifra_addr.sin6_family = unix.AF_INET6 - parts := strings.Split(strings.TrimRight(addr, "/8"), ":") + parts := strings.Split(strings.Split(addr, "/")[0], ":") for i := 0; i < 8; i++ { addr, _ := strconv.ParseUint(parts[i], 16, 16) b := make([]byte, 16) From 03773eca3d52b8bd6dbd4d8a9641923465e0cbd7 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sat, 26 May 2018 21:39:07 +0100 Subject: [PATCH 14/14] Missing import to fmt --- src/yggdrasil/core.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/yggdrasil/core.go b/src/yggdrasil/core.go index 55306197..21cd2af4 100644 --- a/src/yggdrasil/core.go +++ b/src/yggdrasil/core.go @@ -4,6 +4,7 @@ import "io/ioutil" import "log" import "regexp" import "net" +import "fmt" import "encoding/hex" import "yggdrasil/config"