diff --git a/tun.go b/tun.go index f4b60c1..ff77cf7 100644 --- a/tun.go +++ b/tun.go @@ -109,7 +109,8 @@ type Options struct { _TXChecksumOffload bool // For library usages. - EXP_DisableDNSHijack bool + EXP_DisableDNSHijack bool + EXP_ExternalConfiguration bool // For gvisor stack, it should be enabled when MTU is less than 32768; otherwise it should be less than or equal to 8192. // The above condition is just an estimate and not exact, calculated on M4 pro. diff --git a/tun_darwin.go b/tun_darwin.go index 45efa29..36a0b11 100644 --- a/tun_darwin.go +++ b/tun_darwin.go @@ -146,11 +146,17 @@ func New(options Options) (Tun, error) { } func (t *NativeTun) Start() error { + if t.options.EXP_ExternalConfiguration { + return nil + } t.options.InterfaceMonitor.RegisterMyInterface(t.options.Name) return t.setRoutes() } func (t *NativeTun) Close() error { + if t.options.EXP_ExternalConfiguration { + return t.tunFile.Close() + } defer flushDNSCache() return E.Errors(t.unsetRoutes(), t.tunFile.Close()) } @@ -232,6 +238,9 @@ func create(tunFd int, ifIndex int, name string, options Options) error { if err != nil { return os.NewSyscallError("IoctlSetIfreqMTU", err) } + if options.EXP_ExternalConfiguration { + return nil + } if len(options.Inet4Address) > 0 { for _, address := range options.Inet4Address { ifReq := ifAliasReq{ @@ -396,11 +405,14 @@ func (t *NativeTun) TXChecksumOffload() bool { } func (t *NativeTun) UpdateRouteOptions(tunOptions Options) error { + t.options = tunOptions + if t.options.EXP_ExternalConfiguration { + return nil + } err := t.unsetRoutes() if err != nil { return err } - t.options = tunOptions return t.setRoutes() } diff --git a/tun_linux.go b/tun_linux.go index b19d5da..7f22644 100644 --- a/tun_linux.go +++ b/tun_linux.go @@ -125,22 +125,23 @@ func (t *NativeTun) configure(tunLink netlink.Link) error { } else if err != nil { return err } - - if len(t.options.Inet4Address) > 0 { - for _, address := range t.options.Inet4Address { - addr4, _ := netlink.ParseAddr(address.String()) - err = netlink.AddrAdd(tunLink, addr4) - if err != nil { - return err + if !t.options.EXP_ExternalConfiguration { + if len(t.options.Inet4Address) > 0 { + for _, address := range t.options.Inet4Address { + addr4, _ := netlink.ParseAddr(address.String()) + err = netlink.AddrAdd(tunLink, addr4) + if err != nil { + return err + } } } - } - if len(t.options.Inet6Address) > 0 { - for _, address := range t.options.Inet6Address { - addr6, _ := netlink.ParseAddr(address.String()) - err = netlink.AddrAdd(tunLink, addr6) - if err != nil { - return err + if len(t.options.Inet6Address) > 0 { + for _, address := range t.options.Inet6Address { + addr6, _ := netlink.ParseAddr(address.String()) + err = netlink.AddrAdd(tunLink, addr6) + if err != nil { + return err + } } } } @@ -257,7 +258,9 @@ func (t *NativeTun) Start() error { if t.options.FileDescriptor != 0 { return nil } - t.options.InterfaceMonitor.RegisterMyInterface(t.options.Name) + if !t.options.EXP_ExternalConfiguration { + t.options.InterfaceMonitor.RegisterMyInterface(t.options.Name) + } tunLink, err := netlink.LinkByName(t.options.Name) if err != nil { return err @@ -277,6 +280,10 @@ func (t *NativeTun) Start() error { } } + if t.options.EXP_ExternalConfiguration { + return nil + } + if t.options.IPRoute2TableIndex == 0 { for { t.options.IPRoute2TableIndex = int(rand.Uint32()) @@ -315,6 +322,9 @@ func (t *NativeTun) Close() error { if t.interfaceCallback != nil { t.options.InterfaceMonitor.UnregisterCallback(t.interfaceCallback) } + if t.options.EXP_ExternalConfiguration { + return common.Close(common.PtrOrNil(t.tunFile)) + } return E.Errors(t.unsetRoute(), t.unsetRules(), common.Close(common.PtrOrNil(t.tunFile))) } @@ -476,6 +486,9 @@ func prefixToIPNet(prefix netip.Prefix) *net.IPNet { func (t *NativeTun) UpdateRouteOptions(tunOptions Options) error { if t.options.FileDescriptor > 0 { return nil + } else if t.options.EXP_ExternalConfiguration { + t.options = tunOptions + return nil } else if !t.options.AutoRoute { t.options = tunOptions return nil diff --git a/tun_windows.go b/tun_windows.go index f33addf..60c43e3 100644 --- a/tun_windows.go +++ b/tun_windows.go @@ -65,6 +65,9 @@ func New(options Options) (WinTun, error) { } func (t *NativeTun) configure() error { + if t.options.EXP_ExternalConfiguration { + return nil + } luid := winipcfg.LUID(t.adapter.LUID()) if len(t.options.Inet4Address) > 0 { err := luid.SetIPAddressesForFamily(winipcfg.AddressFamily(windows.AF_INET), t.options.Inet4Address) @@ -162,10 +165,10 @@ func (t *NativeTun) Name() (string, error) { } func (t *NativeTun) Start() error { - t.options.InterfaceMonitor.RegisterMyInterface(t.options.Name) - if !t.options.AutoRoute { + if t.options.EXP_ExternalConfiguration || !t.options.AutoRoute { return nil } + t.options.InterfaceMonitor.RegisterMyInterface(t.options.Name) luid := winipcfg.LUID(t.adapter.LUID()) gateway4, gateway6 := t.options.Inet4GatewayAddr(), t.options.Inet6GatewayAddr() routeRanges, err := t.options.BuildAutoRouteRanges(false) @@ -393,6 +396,21 @@ retry: } } +func (t *NativeTun) MTU() (int, error) { + return int(t.options.MTU), nil +} + +func (t *NativeTun) ForceMTU(mtu int) { + if mtu <= 0 { + return + } + t.options.MTU = uint32(mtu) +} + +func (t *NativeTun) LUID() uint64 { + return t.adapter.LUID() +} + func (t *NativeTun) ReadPacket() ([]byte, func(), error) { t.running.Add(1) retry: @@ -543,6 +561,9 @@ func (t *NativeTun) Close() error { func (t *NativeTun) UpdateRouteOptions(tunOptions Options) error { t.options = tunOptions + if t.options.EXP_ExternalConfiguration { + return nil + } if !t.options.AutoRoute { return nil }