don't panic if we write to a closed tun device because tun.close() was called

This commit is contained in:
Arceliar 2018-12-16 17:01:59 -06:00
parent 1a1e0553aa
commit d9f212dd39

View File

@ -5,6 +5,7 @@ package yggdrasil
import ( import (
"bytes" "bytes"
"errors" "errors"
"sync"
"time" "time"
"github.com/songgao/packets/ethernet" "github.com/songgao/packets/ethernet"
@ -24,6 +25,8 @@ type tunAdapter struct {
icmpv6 icmpv6 icmpv6 icmpv6
mtu int mtu int
iface *water.Interface iface *water.Interface
mutex sync.RWMutex // Protects the below
isOpen bool
} }
// Gets the maximum supported MTU for the platform based on the defaults in // 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 { if err := tun.setup(ifname, iftapmode, addr, mtu); err != nil {
return err return err
} }
tun.mutex.Lock()
tun.isOpen = true
tun.mutex.Unlock()
go func() { panic(tun.read()) }() go func() { panic(tun.read()) }()
go func() { panic(tun.write()) }() go func() { panic(tun.write()) }()
if iftapmode { if iftapmode {
@ -148,14 +154,28 @@ func (tun *tunAdapter) write() error {
len(data)) // Payload length len(data)) // Payload length
copy(frame[tun_ETHER_HEADER_LENGTH:], data[:]) copy(frame[tun_ETHER_HEADER_LENGTH:], data[:])
if _, err := tun.iface.Write(frame); err != nil { if _, err := tun.iface.Write(frame); err != nil {
tun.mutex.RLock()
open := tun.isOpen
tun.mutex.RUnlock()
if !open {
return nil
} else {
panic(err) panic(err)
} }
} }
}
} else { } else {
if _, err := tun.iface.Write(data); err != nil { if _, err := tun.iface.Write(data); err != nil {
tun.mutex.RLock()
open := tun.isOpen
tun.mutex.RUnlock()
if !open {
return nil
} else {
panic(err) panic(err)
} }
} }
}
util.PutBytes(data) util.PutBytes(data)
} }
} }
@ -173,9 +193,16 @@ func (tun *tunAdapter) read() error {
for { for {
n, err := tun.iface.Read(buf) n, err := tun.iface.Read(buf)
if err != nil { if err != nil {
tun.mutex.RLock()
open := tun.isOpen
tun.mutex.RUnlock()
if !open {
return nil
} else {
// panic(err) // panic(err)
return err return err
} }
}
o := 0 o := 0
if tun.iface.IsTAP() { if tun.iface.IsTAP() {
o = tun_ETHER_HEADER_LENGTH o = tun_ETHER_HEADER_LENGTH
@ -202,6 +229,9 @@ func (tun *tunAdapter) read() error {
// process stops. Typically this operation will happen quickly, but on macOS // process stops. Typically this operation will happen quickly, but on macOS
// it can block until a read operation is completed. // it can block until a read operation is completed.
func (tun *tunAdapter) close() error { func (tun *tunAdapter) close() error {
tun.mutex.Lock()
tun.isOpen = false
tun.mutex.Unlock()
if tun.iface == nil { if tun.iface == nil {
return nil return nil
} }