From d9f212dd39314cae88a5ccf698c446ae66935b7a Mon Sep 17 00:00:00 2001 From: Arceliar Date: Sun, 16 Dec 2018 17:01:59 -0600 Subject: [PATCH 1/2] don't panic if we write to a closed tun device because tun.close() was called --- src/yggdrasil/tun.go | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/src/yggdrasil/tun.go b/src/yggdrasil/tun.go index c3ceeb6..9d1e0fe 100644 --- a/src/yggdrasil/tun.go +++ b/src/yggdrasil/tun.go @@ -5,6 +5,7 @@ package yggdrasil import ( "bytes" "errors" + "sync" "time" "github.com/songgao/packets/ethernet" @@ -24,6 +25,8 @@ type tunAdapter struct { icmpv6 icmpv6 mtu int iface *water.Interface + mutex sync.RWMutex // Protects the below + isOpen bool } // Gets the maximum supported MTU for the platform based on the defaults in @@ -50,6 +53,9 @@ func (tun *tunAdapter) start(ifname string, iftapmode bool, addr string, mtu int if err := tun.setup(ifname, iftapmode, addr, mtu); err != nil { return err } + tun.mutex.Lock() + tun.isOpen = true + tun.mutex.Unlock() go func() { panic(tun.read()) }() go func() { panic(tun.write()) }() if iftapmode { @@ -148,12 +154,26 @@ func (tun *tunAdapter) write() error { len(data)) // Payload length copy(frame[tun_ETHER_HEADER_LENGTH:], data[:]) if _, err := tun.iface.Write(frame); err != nil { - panic(err) + tun.mutex.RLock() + open := tun.isOpen + tun.mutex.RUnlock() + if !open { + return nil + } else { + panic(err) + } } } } else { if _, err := tun.iface.Write(data); err != nil { - panic(err) + tun.mutex.RLock() + open := tun.isOpen + tun.mutex.RUnlock() + if !open { + return nil + } else { + panic(err) + } } } util.PutBytes(data) @@ -173,8 +193,15 @@ func (tun *tunAdapter) read() error { for { n, err := tun.iface.Read(buf) if err != nil { - // panic(err) - return err + tun.mutex.RLock() + open := tun.isOpen + tun.mutex.RUnlock() + if !open { + return nil + } else { + // panic(err) + return err + } } o := 0 if tun.iface.IsTAP() { @@ -202,6 +229,9 @@ func (tun *tunAdapter) read() error { // process stops. Typically this operation will happen quickly, but on macOS // it can block until a read operation is completed. func (tun *tunAdapter) close() error { + tun.mutex.Lock() + tun.isOpen = false + tun.mutex.Unlock() if tun.iface == nil { return nil } From db034ce6bd365d3dd3413bda55cc5f38a1c61317 Mon Sep 17 00:00:00 2001 From: Arceliar Date: Sun, 16 Dec 2018 17:23:07 -0600 Subject: [PATCH 2/2] replace panics with warning messages if the tun reader/writer return an error --- src/yggdrasil/tun.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/yggdrasil/tun.go b/src/yggdrasil/tun.go index 9d1e0fe..b6bc913 100644 --- a/src/yggdrasil/tun.go +++ b/src/yggdrasil/tun.go @@ -56,8 +56,8 @@ func (tun *tunAdapter) start(ifname string, iftapmode bool, addr string, mtu int tun.mutex.Lock() tun.isOpen = true tun.mutex.Unlock() - go func() { panic(tun.read()) }() - go func() { panic(tun.write()) }() + go func() { tun.core.log.Println("WARNING: tun.read() exited with error:", tun.read()) }() + go func() { tun.core.log.Println("WARNING: tun.write() exited with error:", tun.write()) }() if iftapmode { go func() { for {