From f21cbaef9c7f5bd0065e15026d8debf0f91d066a Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Mon, 9 Jul 2018 09:38:48 +0100 Subject: [PATCH 1/7] Fix debug builds after changes in #155 --- src/yggdrasil/debug.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/yggdrasil/debug.go b/src/yggdrasil/debug.go index 564d59c..4cb1072 100644 --- a/src/yggdrasil/debug.go +++ b/src/yggdrasil/debug.go @@ -22,6 +22,8 @@ import "net/http" import "runtime" import "os" +import "yggdrasil/defaults" + // Start the profiler in debug builds, if the required environment variable is set. func init() { envVarName := "PPROFLISTEN" @@ -239,15 +241,15 @@ func (c *Core) DEBUG_getDHTSize() int { // TUN defaults func (c *Core) DEBUG_GetTUNDefaultIfName() string { - return getDefaults().defaultIfName + return defaults.GetDefaults().DefaultIfName } func (c *Core) DEBUG_GetTUNDefaultIfMTU() int { - return getDefaults().defaultIfMTU + return defaults.GetDefaults().DefaultIfMTU } func (c *Core) DEBUG_GetTUNDefaultIfTAPMode() bool { - return getDefaults().defaultIfTAPMode + return defaults.GetDefaults().DefaultIfTAPMode } // udpInterface From cff7ef026f5f7a60b7cad13a889d3d9a94816e64 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Mon, 9 Jul 2018 19:30:41 +0100 Subject: [PATCH 2/7] Make yggdrasilctl less case-sensitive --- src/yggdrasil/admin.go | 2 +- yggdrasilctl.go | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/yggdrasil/admin.go b/src/yggdrasil/admin.go index cf56d41..0a7314c 100644 --- a/src/yggdrasil/admin.go +++ b/src/yggdrasil/admin.go @@ -309,7 +309,7 @@ func (a *admin) handleRequest(conn net.Conn) { handlers: for _, handler := range a.handlers { // We've found the handler that matches the request - if recv["request"] == handler.name { + if strings.ToLower(recv["request"].(string)) == strings.ToLower(handler.name) { // Check that we have all the required arguments for _, arg := range handler.args { // An argument in [square brackets] is optional and not required, diff --git a/yggdrasilctl.go b/yggdrasilctl.go index 6281b16..9d3fbb1 100644 --- a/yggdrasilctl.go +++ b/yggdrasilctl.go @@ -63,7 +63,7 @@ func main() { if i, err := strconv.Atoi(tokens[1]); err == nil { send[tokens[0]] = i } else { - switch tokens[1] { + switch strings.ToLower(tokens[1]) { case "true": send[tokens[0]] = true case "false": @@ -104,10 +104,10 @@ func main() { os.Exit(0) } - switch req["request"] { + switch strings.ToLower(req["request"].(string)) { case "dot": fmt.Println(res["dot"]) - case "help", "getPeers", "getSwitchPeers", "getDHT", "getSessions": + case "help", "getpeers", "getswitchpeers", "getdht", "getsessions": maxWidths := make(map[string]int) var keyOrder []string keysOrdered := false @@ -163,7 +163,7 @@ func main() { fmt.Println() } } - case "getTunTap", "setTunTap": + case "gettuntap", "settuntap": for k, v := range res { fmt.Println("Interface name:", k) if mtu, ok := v.(map[string]interface{})["mtu"].(float64); ok { @@ -173,7 +173,7 @@ func main() { fmt.Println("TAP mode:", tap_mode) } } - case "getSelf": + case "getself": for k, v := range res["self"].(map[string]interface{}) { fmt.Println("IPv6 address:", k) if subnet, ok := v.(map[string]interface{})["subnet"].(string); ok { @@ -183,7 +183,7 @@ func main() { fmt.Println("Coords:", coords) } } - case "addPeer", "removePeer", "addAllowedEncryptionPublicKey", "removeAllowedEncryptionPublicKey": + case "addpeer", "removepeer", "addallowedencryptionpublickey", "removeallowedencryptionpublickey": if _, ok := res["added"]; ok { for _, v := range res["added"].([]interface{}) { fmt.Println("Added:", fmt.Sprint(v)) @@ -204,7 +204,7 @@ func main() { fmt.Println("Not removed:", fmt.Sprint(v)) } } - case "getAllowedEncryptionPublicKeys": + case "getallowedencryptionpublickeys": if _, ok := res["allowed_box_pubs"]; !ok { fmt.Println("All connections are allowed") } else if res["allowed_box_pubs"] == nil { @@ -215,7 +215,7 @@ func main() { fmt.Println("-", v) } } - case "getMulticastInterfaces": + case "getmulticastinterfaces": if _, ok := res["multicast_interfaces"]; !ok { fmt.Println("No multicast interfaces found") } else if res["multicast_interfaces"] == nil { From f4bb2aaaebf207bf786a7769f899c128c12fdadb Mon Sep 17 00:00:00 2001 From: cathugger Date: Thu, 19 Jul 2018 01:03:24 +0000 Subject: [PATCH 3/7] More verbose disconnect messages --- src/yggdrasil/tcp.go | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/yggdrasil/tcp.go b/src/yggdrasil/tcp.go index 80ae284..831cd74 100644 --- a/src/yggdrasil/tcp.go +++ b/src/yggdrasil/tcp.go @@ -17,6 +17,7 @@ package yggdrasil import ( "errors" "fmt" + "io" "math/rand" "net" "sync" @@ -304,15 +305,19 @@ func (iface *tcpInterface) handler(sock net.Conn, incoming bool) { themAddrString := net.IP(themAddr[:]).String() themString := fmt.Sprintf("%s@%s", themAddrString, them) iface.core.log.Println("Connected:", themString) - iface.reader(sock, in) // In this goroutine, because of defers - iface.core.log.Println("Disconnected:", themString) + err = iface.reader(sock, in) // In this goroutine, because of defers + if err == nil { + iface.core.log.Println("Disconnected:", themString) + } else { + iface.core.log.Println("Disconnected:", themString, "with error:", err) + } return } // This reads from the socket into a []byte buffer for incomping messages. // It copies completed messages out of the cache into a new slice, and passes them to the peer struct via the provided `in func([]byte)` argument. // Then it shifts the incomplete fragments of data forward so future reads won't overwrite it. -func (iface *tcpInterface) reader(sock net.Conn, in func([]byte)) { +func (iface *tcpInterface) reader(sock net.Conn, in func([]byte)) error { bs := make([]byte, 2*tcp_msgSize) frag := bs[:0] for { @@ -320,13 +325,16 @@ 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 { - break + if err != io.EOF { + return err + } + return nil } frag = bs[:len(frag)+n] for { msg, ok, err := tcp_chop_msg(&frag) if err != nil { - return + return fmt.Errorf("Message error: %v", err) } if !ok { break From df9cadd9389b87632f53129123ab269d939118a1 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 19 Jul 2018 10:01:12 +0100 Subject: [PATCH 4/7] Cap MTU on Linux in TAP mode --- src/yggdrasil/tun_linux.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/yggdrasil/tun_linux.go b/src/yggdrasil/tun_linux.go index 24c5aa9..14c2f0a 100644 --- a/src/yggdrasil/tun_linux.go +++ b/src/yggdrasil/tun_linux.go @@ -29,6 +29,14 @@ func (tun *tunDevice) setup(ifname string, iftapmode bool, addr string, mtu int) } tun.iface = iface tun.mtu = getSupportedMTU(mtu) + // The following check is specific to Linux, as the TAP driver only supports + // an MTU of 65535-14 to make room for the ethernet headers. This makes sure + // that the MTU gets rounded down to 65521 instead of causing a panic. + if iftapmode { + if tun.mtu > 65535-tun_ETHER_HEADER_LENGTH { + tun.mtu = 65535-tun_ETHER_HEADER_LENGTH + } + } return tun.setupAddress(addr) } From 55b56e8686473b7070fd0b72782fbf908e755407 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 19 Jul 2018 10:15:26 +0100 Subject: [PATCH 5/7] Normalise startup output for TUN/TAP on Linux and Windows --- src/yggdrasil/tun_linux.go | 4 ++++ src/yggdrasil/tun_windows.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/yggdrasil/tun_linux.go b/src/yggdrasil/tun_linux.go index 14c2f0a..a1f8abd 100644 --- a/src/yggdrasil/tun_linux.go +++ b/src/yggdrasil/tun_linux.go @@ -37,6 +37,10 @@ func (tun *tunDevice) setup(ifname string, iftapmode bool, addr string, mtu int) tun.mtu = 65535-tun_ETHER_HEADER_LENGTH } } + // Friendly output + tun.core.log.Printf("Interface name: %s", tun.iface.Name()) + tun.core.log.Printf("Interface IPv6: %s", addr) + tun.core.log.Printf("Interface MTU: %d", tun.mtu) return tun.setupAddress(addr) } diff --git a/src/yggdrasil/tun_windows.go b/src/yggdrasil/tun_windows.go index c6e5770..d3420df 100644 --- a/src/yggdrasil/tun_windows.go +++ b/src/yggdrasil/tun_windows.go @@ -57,6 +57,10 @@ func (tun *tunDevice) setup(ifname string, iftapmode bool, addr string, mtu int) if err != nil { panic(err) } + // Friendly output + tun.core.log.Printf("Interface name: %s", tun.iface.Name()) + tun.core.log.Printf("Interface IPv6: %s", addr) + tun.core.log.Printf("Interface MTU: %d", tun.mtu) return tun.setupAddress(addr) } From 91a374d69889dd40fb7954de21917157a80fff78 Mon Sep 17 00:00:00 2001 From: cathugger Date: Thu, 19 Jul 2018 21:58:53 +0000 Subject: [PATCH 6/7] rearrange tcp reading loop according to documentation of io.Reader interface, "Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed EOF behaviors." --- src/yggdrasil/tcp.go | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/yggdrasil/tcp.go b/src/yggdrasil/tcp.go index 831cd74..3372fe6 100644 --- a/src/yggdrasil/tcp.go +++ b/src/yggdrasil/tcp.go @@ -324,26 +324,29 @@ func (iface *tcpInterface) reader(sock net.Conn, in func([]byte)) error { timeout := time.Now().Add(tcp_timeout) sock.SetReadDeadline(timeout) n, err := sock.Read(bs[len(frag):]) + if n > 0 { + frag = bs[:len(frag)+n] + for { + msg, ok, err2 := tcp_chop_msg(&frag) + if err2 != nil { + return fmt.Errorf("Message error: %v", err2) + } + if !ok { + // We didn't get the whole message yet + break + } + newMsg := append(util_getBytes(), msg...) + in(newMsg) + util_yield() + } + frag = append(bs[:0], frag...) + } if err != nil || n == 0 { if err != io.EOF { return err } return nil } - frag = bs[:len(frag)+n] - for { - msg, ok, err := tcp_chop_msg(&frag) - if err != nil { - return fmt.Errorf("Message error: %v", err) - } - if !ok { - break - } // We didn't get the whole message yet - newMsg := append(util_getBytes(), msg...) - in(newMsg) - util_yield() - } - frag = append(bs[:0], frag...) } } From 2b7b32ff3af1a534701d3254c5b666bae7a26ff1 Mon Sep 17 00:00:00 2001 From: Arceliar Date: Thu, 19 Jul 2018 18:38:48 -0500 Subject: [PATCH 7/7] Update CHANGELOG.md --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 872c297..c8d4ebb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - in case of vulnerabilities. --> +## [0.2.5] - 2018-07-19 +### Changed +- Make `yggdrasilctl` less case sensitive +- More verbose TCP disconnect messages + +### Fixed +- Fixed debug builds +- Cap maximum MTU on Linux in TAP mode +- Process successfully-read TCP traffic before checking for / handling errors (fixes EOF behavior) + ## [0.2.4] - 2018-07-08 ### Added - Support for UNIX domain sockets for the admin socket using `unix:///path/to/file.sock`