From 99e8b4ba605538b64c693c4056904f34810c3938 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Thu, 20 May 2021 18:26:01 +0200 Subject: [PATCH] tun: linux: account for interface removal from outside On Linux we can run `ip link del wg0`, in which case the fd becomes stale, and we should exit. Since this is an intentional action, don't treat it as an error. Signed-off-by: Jason A. Donenfeld --- device/send.go | 6 +++++- tun/tun_linux.go | 55 +++++++++++++++++++++++++----------------------- 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/device/send.go b/device/send.go index e07df1b..a4f07e4 100644 --- a/device/send.go +++ b/device/send.go @@ -8,7 +8,9 @@ package device import ( "bytes" "encoding/binary" + "errors" "net" + "os" "sync" "sync/atomic" "time" @@ -227,7 +229,9 @@ func (device *Device) RoutineReadFromTUN() { if err != nil { if !device.isClosed() { - device.log.Errorf("Failed to read packet from TUN device: %v", err) + if !errors.Is(err, os.ErrClosed) { + device.log.Errorf("Failed to read packet from TUN device: %v", err) + } go device.Close() } device.PutMessageBuffer(elem.buffer) diff --git a/tun/tun_linux.go b/tun/tun_linux.go index 46eb171..466a805 100644 --- a/tun/tun_linux.go +++ b/tun/tun_linux.go @@ -10,6 +10,7 @@ package tun import ( "bytes" + "errors" "fmt" "os" "sync" @@ -329,32 +330,30 @@ func (tun *NativeTun) nameSlow() (string, error) { return string(name), nil } -func (tun *NativeTun) Write(buff []byte, offset int) (int, error) { - +func (tun *NativeTun) Write(buf []byte, offset int) (int, error) { if tun.nopi { - buff = buff[offset:] + buf = buf[offset:] } else { // reserve space for header - - buff = buff[offset-4:] + buf = buf[offset-4:] // add packet information header - - buff[0] = 0x00 - buff[1] = 0x00 - - if buff[4]>>4 == ipv6.Version { - buff[2] = 0x86 - buff[3] = 0xdd + buf[0] = 0x00 + buf[1] = 0x00 + if buf[4]>>4 == ipv6.Version { + buf[2] = 0x86 + buf[3] = 0xdd } else { - buff[2] = 0x08 - buff[3] = 0x00 + buf[2] = 0x08 + buf[3] = 0x00 } } - // write - - return tun.tunFile.Write(buff) + n, err := tun.tunFile.Write(buf) + if errors.Is(err, syscall.EBADFD) { + err = os.ErrClosed + } + return n, err } func (tun *NativeTun) Flush() error { @@ -362,22 +361,26 @@ func (tun *NativeTun) Flush() error { return nil } -func (tun *NativeTun) Read(buff []byte, offset int) (int, error) { +func (tun *NativeTun) Read(buf []byte, offset int) (n int, err error) { select { - case err := <-tun.errors: - return 0, err + case err = <-tun.errors: default: if tun.nopi { - return tun.tunFile.Read(buff[offset:]) + n, err = tun.tunFile.Read(buf[offset:]) } else { - buff := buff[offset-4:] - n, err := tun.tunFile.Read(buff[:]) - if n < 4 { - return 0, err + buff := buf[offset-4:] + n, err = tun.tunFile.Read(buff[:]) + if errors.Is(err, syscall.EBADFD) { + err = os.ErrClosed + } + if n < 4 { + n = 0 + } else { + n -= 4 } - return n - 4, err } } + return } func (tun *NativeTun) Events() chan Event {