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...") }