diff options
author | Mikael Magnusson <mikma@users.sourceforge.net> | 2023-10-24 21:36:52 +0200 |
---|---|---|
committer | Mikael Magnusson <mikma@users.sourceforge.net> | 2024-05-10 01:01:33 +0200 |
commit | baf7762eadfcb6be798bebcbd914194a8d40823b (patch) | |
tree | 2afbf410d3a650c3efabeabee3797f1b7648c2fe | |
parent | 12269c2761734b15625017d8565745096325392f (diff) |
WIP: add SetFddhcp2
-rw-r--r-- | tun/tun_linux.go | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/tun/tun_linux.go b/tun/tun_linux.go index bd69cb5..9633359 100644 --- a/tun/tun_linux.go +++ b/tun/tun_linux.go @@ -29,6 +29,8 @@ const ( type NativeTun struct { tunFile *os.File + tunRdFile *os.File + nextTunFile *os.File index int32 // if index errors chan error // async error handling events chan Event // device related events @@ -360,6 +362,16 @@ func (tun *NativeTun) Write(bufs [][]byte, offset int) (int, error) { if errors.Is(err, syscall.EBADFD) { return total, os.ErrClosed } + + if tun.tunFile != tun.nextTunFile && errors.Is(err, os.ErrDeadlineExceeded) { + // Switch to new tunFile + tun.tunFile = tun.nextTunFile + n, err = tun.tunFile.Write(bufs[bufsI][offset:]) + if errors.Is(err, syscall.EBADFD) { + return total, os.ErrClosed + } + } + if err != nil { errs = errors.Join(errs, err) } else { @@ -459,7 +471,14 @@ func (tun *NativeTun) Read(bufs [][]byte, sizes []int, offset int) (int, error) if tun.vnetHdr { readInto = tun.readBuff[:] } - n, err := tun.tunFile.Read(readInto) + n, err := tun.tunRdFile.Read(readInto) + if tun.tunRdFile != tun.nextTunFile && errors.Is(err, os.ErrDeadlineExceeded) { + // Old tun is empty. Retry with new tun. + tun.tunRdFile.Close() + tun.tunRdFile = tun.nextTunFile + n, err = tun.tunRdFile.Read(readInto) + } + if errors.Is(err, syscall.EBADFD) { err = os.ErrClosed } @@ -475,6 +494,18 @@ func (tun *NativeTun) Read(bufs [][]byte, sizes []int, offset int) (int, error) } } +func (tun *NativeTun) SetFd(fd int) error { + err := unix.SetNonblock(fd, true) + if err != nil { + return err + } + oldTun := tun.tunFile + tun.nextTunFile = os.NewFile(uintptr(fd), "/dev/tunB") + tun.tunFile = tun.nextTunFile + oldTun.SetDeadline(time.Now()) // Release blocked in Read and Write + return nil +} + func (tun *NativeTun) Events() <-chan Event { return tun.events } @@ -585,6 +616,7 @@ func CreateTUN(name string, mtu int) (Device, error) { func CreateTUNFromFile(file *os.File, mtu int) (Device, error) { tun := &NativeTun{ tunFile: file, + tunRdFile: file, events: make(chan Event, 5), errors: make(chan error, 5), statusListenersShutdown: make(chan struct{}), @@ -634,7 +666,7 @@ func CreateTUNFromFile(file *os.File, mtu int) (Device, error) { // CreateUnmonitoredTUNFromFD creates a Device from the provided file // descriptor. -func CreateUnmonitoredTUNFromFD(fd int) (Device, string, error) { +func CreateUnmonitoredTUNFromFD(fd int) (*NativeTun, string, error) { err := unix.SetNonblock(fd, true) if err != nil { return nil, "", err @@ -642,6 +674,7 @@ func CreateUnmonitoredTUNFromFD(fd int) (Device, string, error) { file := os.NewFile(uintptr(fd), "/dev/tun") tun := &NativeTun{ tunFile: file, + tunRdFile: file, events: make(chan Event, 5), errors: make(chan error, 5), tcpGROTable: newTCPGROTable(), |