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 }