From cd6030ec8f9977fb5e151d719ddd8986f8b60584 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sat, 7 Jul 2018 11:22:49 +0100 Subject: [PATCH 1/5] Add support for UNIX domain admin sockets and specifying URIs in AdminListen --- src/yggdrasil/admin.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/yggdrasil/admin.go b/src/yggdrasil/admin.go index bd5eb0c8..e02bf9e8 100644 --- a/src/yggdrasil/admin.go +++ b/src/yggdrasil/admin.go @@ -229,13 +229,26 @@ func (a *admin) start() error { // listen is run by start and manages API connections. func (a *admin) listen() { - l, err := net.Listen("tcp", a.listenaddr) + var l net.Listener + u, err := url.Parse(a.listenaddr) + if err == nil { + switch strings.ToLower(u.Scheme) { + case "unix": + l, err = net.Listen("unix", a.listenaddr[7:]) + case "tcp": + l, err = net.Listen("tcp", u.Host) + default: + err = errors.New("protocol not supported") + } + } else { + l, err = net.Listen("tcp", a.listenaddr) + } if err != nil { a.core.log.Printf("Admin socket failed to listen: %v", err) os.Exit(1) } + a.core.log.Printf("%s admin socket listening on %s", strings.ToUpper(l.Addr().Network()), l.Addr().String()) defer l.Close() - a.core.log.Printf("Admin socket listening on %s", l.Addr().String()) for { conn, err := l.Accept() if err == nil { From 047b7d95a15db5726035617b2bdf2789635d09da Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sat, 7 Jul 2018 11:25:01 +0100 Subject: [PATCH 2/5] Add support for UNIX domain admin sockets to yggdrasilctl --- yggdrasilctl.go | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/yggdrasilctl.go b/yggdrasilctl.go index 5cea7745..25998e35 100644 --- a/yggdrasilctl.go +++ b/yggdrasilctl.go @@ -1,9 +1,11 @@ package main +import "errors" import "flag" import "fmt" import "strings" import "net" +import "net/url" import "sort" import "encoding/json" import "strconv" @@ -12,20 +14,34 @@ import "os" type admin_info map[string]interface{} func main() { - server := flag.String("endpoint", "localhost:9001", "Admin socket endpoint") + server := flag.String("endpoint", "tcp://localhost:9001", "Admin socket endpoint") injson := flag.Bool("json", false, "Output in JSON format") flag.Parse() args := flag.Args() if len(args) == 0 { - fmt.Println("usage:", os.Args[0], "[-endpoint=localhost:9001] [-json] command [key=value] [...]") + fmt.Println("usage:", os.Args[0], "[-endpoint=proto://server] [-json] command [key=value] [...]") fmt.Println("example:", os.Args[0], "getPeers") fmt.Println("example:", os.Args[0], "setTunTap name=auto mtu=1500 tap_mode=false") - fmt.Println("example:", os.Args[0], "-endpoint=localhost:9001 getDHT") + fmt.Println("example:", os.Args[0], "-endpoint=tcp://localhost:9001 getDHT") + fmt.Println("example:", os.Args[0], "-endpoint=unix:///var/run/ygg.sock getDHT") return } - conn, err := net.Dial("tcp", *server) + var conn net.Conn + u, err := url.Parse(*server) + if err == nil { + switch strings.ToLower(u.Scheme) { + case "unix": + conn, err = net.Dial("unix", (*server)[7:]) + case "tcp": + conn, err = net.Dial("tcp", u.Host) + default: + err = errors.New("protocol not supported") + } + } else { + conn, err = net.Dial("tcp", *server) + } if err != nil { panic(err) } From 171e1e7823a502db250e5e878f2251783fa8b15f Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sat, 7 Jul 2018 11:28:50 +0100 Subject: [PATCH 3/5] Update default AdminListen to URI format --- yggdrasil.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yggdrasil.go b/yggdrasil.go index 20b4aa08..e4c63d70 100644 --- a/yggdrasil.go +++ b/yggdrasil.go @@ -53,7 +53,7 @@ func generateConfig(isAutoconf bool) *nodeConfig { r1 := rand.New(rand.NewSource(time.Now().UnixNano())) cfg.Listen = fmt.Sprintf("[::]:%d", r1.Intn(65534-32768)+32768) } - cfg.AdminListen = "localhost:9001" + cfg.AdminListen = "tcp://localhost:9001" cfg.EncryptionPublicKey = hex.EncodeToString(bpub[:]) cfg.EncryptionPrivateKey = hex.EncodeToString(bpriv[:]) cfg.SigningPublicKey = hex.EncodeToString(spub[:]) From 2a931df07af4bf889adf49cc896a61bf8e4484d4 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sat, 7 Jul 2018 12:34:10 +0100 Subject: [PATCH 4/5] Try to clean up UNIX domain admin sockets if shutdown properly --- src/yggdrasil/admin.go | 10 ++++++++++ src/yggdrasil/core.go | 1 + 2 files changed, 11 insertions(+) diff --git a/src/yggdrasil/admin.go b/src/yggdrasil/admin.go index e02bf9e8..cd3ea5c8 100644 --- a/src/yggdrasil/admin.go +++ b/src/yggdrasil/admin.go @@ -227,6 +227,16 @@ func (a *admin) start() error { return nil } +// cleans up when stopping +func (a *admin) stop() error { + if a.listenaddr[0:7] == "unix://" { + if err := os.Remove(a.listenaddr[7:]); err != nil { + return err + } + } + return nil +} + // listen is run by start and manages API connections. func (a *admin) listen() { var l net.Listener diff --git a/src/yggdrasil/core.go b/src/yggdrasil/core.go index 6d130d81..52636764 100644 --- a/src/yggdrasil/core.go +++ b/src/yggdrasil/core.go @@ -135,6 +135,7 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error { func (c *Core) Stop() { c.log.Println("Stopping...") c.tun.close() + c.admin.stop() } // Generates a new encryption keypair. The encryption keys are used to From a5af69df8a804cc9782570e98f3105e2a5b72643 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sat, 7 Jul 2018 20:04:11 +0100 Subject: [PATCH 5/5] Use Close() for admin socket --- src/yggdrasil/admin.go | 25 +++++++++++-------------- src/yggdrasil/core.go | 2 +- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/yggdrasil/admin.go b/src/yggdrasil/admin.go index cd3ea5c8..caa4afca 100644 --- a/src/yggdrasil/admin.go +++ b/src/yggdrasil/admin.go @@ -20,6 +20,7 @@ import ( type admin struct { core *Core listenaddr string + listener net.Listener handlers []admin_handlerInfo } @@ -228,39 +229,35 @@ func (a *admin) start() error { } // cleans up when stopping -func (a *admin) stop() error { - if a.listenaddr[0:7] == "unix://" { - if err := os.Remove(a.listenaddr[7:]); err != nil { - return err - } - } - return nil +func (a *admin) close() error { + return a.listener.Close() } // listen is run by start and manages API connections. func (a *admin) listen() { - var l net.Listener u, err := url.Parse(a.listenaddr) if err == nil { switch strings.ToLower(u.Scheme) { case "unix": - l, err = net.Listen("unix", a.listenaddr[7:]) + a.listener, err = net.Listen("unix", a.listenaddr[7:]) case "tcp": - l, err = net.Listen("tcp", u.Host) + a.listener, err = net.Listen("tcp", u.Host) default: err = errors.New("protocol not supported") } } else { - l, err = net.Listen("tcp", a.listenaddr) + a.listener, err = net.Listen("tcp", a.listenaddr) } if err != nil { a.core.log.Printf("Admin socket failed to listen: %v", err) os.Exit(1) } - a.core.log.Printf("%s admin socket listening on %s", strings.ToUpper(l.Addr().Network()), l.Addr().String()) - defer l.Close() + a.core.log.Printf("%s admin socket listening on %s", + strings.ToUpper(a.listener.Addr().Network()), + a.listener.Addr().String()) + defer a.listener.Close() for { - conn, err := l.Accept() + conn, err := a.listener.Accept() if err == nil { a.handleRequest(conn) } diff --git a/src/yggdrasil/core.go b/src/yggdrasil/core.go index 52636764..13bb8309 100644 --- a/src/yggdrasil/core.go +++ b/src/yggdrasil/core.go @@ -135,7 +135,7 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error { func (c *Core) Stop() { c.log.Println("Stopping...") c.tun.close() - c.admin.stop() + c.admin.close() } // Generates a new encryption keypair. The encryption keys are used to