mirror of
https://github.com/tailscale/tailscale.git
synced 2026-04-04 14:43:42 -04:00
file for file stuff tun for tun stuff udp for udp stuff io_uring for general uring stuff also make build tags suffice
105 lines
2.1 KiB
Go
105 lines
2.1 KiB
Go
package uring
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"reflect"
|
|
"syscall"
|
|
"unsafe"
|
|
|
|
"golang.org/x/net/ipv6"
|
|
"golang.zx2c4.com/wireguard/tun"
|
|
)
|
|
|
|
// Wrap files into TUN devices.
|
|
|
|
func NewTUN(d tun.Device) (tun.Device, error) {
|
|
nt, ok := d.(*tun.NativeTun)
|
|
if !ok {
|
|
return nil, fmt.Errorf("NewTUN only wraps *tun.NativeTun, got %T", d)
|
|
}
|
|
f, err := newFile(nt.File())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
v := reflect.ValueOf(nt)
|
|
field, ok := v.Elem().Type().FieldByName("errors")
|
|
if !ok {
|
|
return nil, errors.New("could not find internal tun.NativeTun errors field")
|
|
}
|
|
ptr := unsafe.Pointer(nt)
|
|
ptr = unsafe.Pointer(uintptr(ptr) + field.Offset) // TODO: switch to unsafe.Add with Go 1.17...as if that's the worst thing in this line
|
|
c := *(*chan error)(ptr)
|
|
return &TUN{d: nt, f: f, errors: c}, nil
|
|
}
|
|
|
|
// No nopi
|
|
type TUN struct {
|
|
d *tun.NativeTun
|
|
f *file
|
|
errors chan error
|
|
}
|
|
|
|
func (t *TUN) File() *os.File {
|
|
return t.f.file
|
|
}
|
|
|
|
func (t *TUN) Read(buf []byte, offset int) (int, error) {
|
|
select {
|
|
case err := <-t.errors:
|
|
return 0, err
|
|
default:
|
|
}
|
|
// TODO: upstream has graceful shutdown error handling here.
|
|
buff := buf[offset-4:]
|
|
n, err := t.f.Read(buff[:])
|
|
if errors.Is(err, syscall.EBADFD) {
|
|
err = os.ErrClosed
|
|
}
|
|
if n < 4 {
|
|
n = 0
|
|
} else {
|
|
n -= 4
|
|
}
|
|
return n, err
|
|
}
|
|
|
|
func (t *TUN) Write(buf []byte, offset int) (int, error) {
|
|
// below copied from wireguard-go NativeTun.Write
|
|
|
|
// reserve space for header
|
|
buf = buf[offset-4:]
|
|
|
|
// add packet information header
|
|
buf[0] = 0x00
|
|
buf[1] = 0x00
|
|
if buf[4]>>4 == ipv6.Version {
|
|
buf[2] = 0x86
|
|
buf[3] = 0xdd
|
|
} else {
|
|
buf[2] = 0x08
|
|
buf[3] = 0x00
|
|
}
|
|
|
|
n, err := t.f.Write(buf)
|
|
if errors.Is(err, syscall.EBADFD) {
|
|
err = os.ErrClosed
|
|
}
|
|
return n, err
|
|
}
|
|
|
|
func (t *TUN) Flush() error { return t.d.Flush() }
|
|
func (t *TUN) MTU() (int, error) { return t.d.MTU() }
|
|
func (t *TUN) Name() (string, error) { return t.d.Name() }
|
|
func (t *TUN) Events() chan tun.Event { return t.d.Events() }
|
|
|
|
func (t *TUN) Close() error {
|
|
err1 := t.f.Close()
|
|
err2 := t.d.Close()
|
|
if err1 != nil {
|
|
return err1
|
|
}
|
|
return err2
|
|
}
|