diff --git a/tun.go b/tun.go index c953943..b0f573a 100644 --- a/tun.go +++ b/tun.go @@ -28,6 +28,7 @@ type Tun interface { Name() (string, error) Start() error Close() error + UpdateRouteOptions(tunOptions Options) error } type WinTun interface { diff --git a/tun_darwin.go b/tun_darwin.go index 52872fa..e887ce8 100644 --- a/tun_darwin.go +++ b/tun_darwin.go @@ -29,7 +29,7 @@ type NativeTun struct { options Options inet4Address [4]byte inet6Address [16]byte - routerSet bool + routeSet bool } func (t *NativeTun) Name() (string, error) { @@ -258,9 +258,17 @@ func configure(tunFd int, ifIndex int, name string, options Options) error { return nil } +func (t *NativeTun) UpdateRouteOptions(tunOptions Options) error { + err := t.unsetRoutes() + if err != nil { + return err + } + t.options = tunOptions + return t.setRoutes() +} + func (t *NativeTun) setRoutes() error { if t.options.AutoRoute && t.options.FileDescriptor == 0 { - routeRanges, err := t.options.BuildAutoRouteRanges(false) if err != nil { return err @@ -298,13 +306,13 @@ func (t *NativeTun) setRoutes() error { } } flushDNSCache() - t.routerSet = true + t.routeSet = true } return nil } func (t *NativeTun) unsetRoutes() error { - if !t.routerSet { + if !t.routeSet { return nil } routeRanges, err := t.options.BuildAutoRouteRanges(false) diff --git a/tun_linux.go b/tun_linux.go index ea0cef6..8c7bac6 100644 --- a/tun_linux.go +++ b/tun_linux.go @@ -495,6 +495,25 @@ 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.AutoRoute { + t.options = tunOptions + return nil + } + tunLink, err := netlink.LinkByName(t.options.Name) + if err != nil { + return err + } + err = t.unsetRoute0(tunLink) + if err != nil { + return err + } + t.options = tunOptions + return t.setRoute(tunLink) +} + func (t *NativeTun) routes(tunLink netlink.Link) ([]netlink.Route, error) { routeRanges, err := t.options.BuildAutoRouteRanges(false) if err != nil { diff --git a/tun_windows.go b/tun_windows.go index bab359f..57d52e3 100644 --- a/tun_windows.go +++ b/tun_windows.go @@ -178,9 +178,9 @@ func (t *NativeTun) Start() error { } else { err = luid.AddRoute(routeRange, gateway6, 0) } - } - if err != nil { - return err + if err != nil { + return err + } } err = windnsapi.FlushResolverCache() if err != nil { @@ -545,6 +545,38 @@ func (t *NativeTun) Close() error { return err } +func (t *NativeTun) UpdateRouteOptions(tunOptions Options) error { + t.options = tunOptions + if !t.options.AutoRoute { + return nil + } + gateway4, gateway6 := t.options.Inet4GatewayAddr(), t.options.Inet6GatewayAddr() + routeRanges, err := t.options.BuildAutoRouteRanges(false) + if err != nil { + return err + } + luid := winipcfg.LUID(t.adapter.LUID()) + err = luid.FlushRoutes(windows.AF_UNSPEC) + if err != nil { + return err + } + for _, routeRange := range routeRanges { + if routeRange.Addr().Is4() { + err = luid.AddRoute(routeRange, gateway4, 0) + } else { + err = luid.AddRoute(routeRange, gateway6, 0) + } + if err != nil { + return err + } + } + err = windnsapi.FlushResolverCache() + if err != nil { + return err + } + return nil +} + func generateGUIDByDeviceName(name string) *windows.GUID { hash := md5.New() hash.Write([]byte("wintun"))