summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMikael Magnusson <mikma@users.sourceforge.net>2023-10-24 21:36:52 +0200
committerMikael Magnusson <mikma@users.sourceforge.net>2024-05-10 01:01:33 +0200
commitbaf7762eadfcb6be798bebcbd914194a8d40823b (patch)
tree2afbf410d3a650c3efabeabee3797f1b7648c2fe
parent12269c2761734b15625017d8565745096325392f (diff)
WIP: add SetFddhcp2
-rw-r--r--tun/tun_linux.go37
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(),