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 <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2021-05-20 18:26:01 +02:00
parent bd83f0ac99
commit 99e8b4ba60
2 changed files with 34 additions and 27 deletions

View File

@ -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)

View File

@ -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 {