github.com/apernet/sing-tun@v0.2.6-0.20240323130332-b9f6511036ad/tun_linux.go (about)

     1  package tun
     2  
     3  import (
     4  	"math/rand"
     5  	"net"
     6  	"net/netip"
     7  	"os"
     8  	"os/exec"
     9  	"runtime"
    10  	"sync"
    11  	"syscall"
    12  	"unsafe"
    13  
    14  	"github.com/sagernet/netlink"
    15  	"github.com/sagernet/sing/common"
    16  	"github.com/sagernet/sing/common/buf"
    17  	"github.com/sagernet/sing/common/bufio"
    18  	E "github.com/sagernet/sing/common/exceptions"
    19  	N "github.com/sagernet/sing/common/network"
    20  	"github.com/sagernet/sing/common/rw"
    21  	"github.com/sagernet/sing/common/shell"
    22  	"github.com/sagernet/sing/common/x/list"
    23  
    24  	"golang.org/x/sys/unix"
    25  )
    26  
    27  var _ LinuxTUN = (*NativeTun)(nil)
    28  
    29  type NativeTun struct {
    30  	tunFd             int
    31  	tunFile           *os.File
    32  	tunWriter         N.VectorisedWriter
    33  	interfaceCallback *list.Element[DefaultInterfaceUpdateCallback]
    34  	options           Options
    35  	ruleIndex6        []int
    36  	gsoEnabled        bool
    37  	gsoBuffer         []byte
    38  	gsoToWrite        []int
    39  	gsoReadAccess     sync.Mutex
    40  	tcpGROAccess      sync.Mutex
    41  	tcp4GROTable      *tcpGROTable
    42  	tcp6GROTable      *tcpGROTable
    43  	txChecksumOffload bool
    44  }
    45  
    46  func New(options Options) (Tun, error) {
    47  	var nativeTun *NativeTun
    48  	if options.FileDescriptor == 0 {
    49  		tunFd, err := open(options.Name, options.GSO)
    50  		if err != nil {
    51  			return nil, err
    52  		}
    53  		tunLink, err := netlink.LinkByName(options.Name)
    54  		if err != nil {
    55  			return nil, E.Errors(err, unix.Close(tunFd))
    56  		}
    57  		nativeTun = &NativeTun{
    58  			tunFd:   tunFd,
    59  			tunFile: os.NewFile(uintptr(tunFd), "tun"),
    60  			options: options,
    61  		}
    62  		err = nativeTun.configure(tunLink)
    63  		if err != nil {
    64  			return nil, E.Errors(err, unix.Close(tunFd))
    65  		}
    66  	} else {
    67  		nativeTun = &NativeTun{
    68  			tunFd:   options.FileDescriptor,
    69  			tunFile: os.NewFile(uintptr(options.FileDescriptor), "tun"),
    70  			options: options,
    71  		}
    72  	}
    73  	var ok bool
    74  	nativeTun.tunWriter, ok = bufio.CreateVectorisedWriter(nativeTun.tunFile)
    75  	if !ok {
    76  		panic("create vectorised writer")
    77  	}
    78  	return nativeTun, nil
    79  }
    80  
    81  func (t *NativeTun) FrontHeadroom() int {
    82  	if t.gsoEnabled {
    83  		return virtioNetHdrLen
    84  	}
    85  	return 0
    86  }
    87  
    88  func (t *NativeTun) Read(p []byte) (n int, err error) {
    89  	if t.gsoEnabled {
    90  		n, err = t.tunFile.Read(t.gsoBuffer)
    91  		if err != nil {
    92  			return
    93  		}
    94  		var sizes [1]int
    95  		n, err = handleVirtioRead(t.gsoBuffer[:n], [][]byte{p}, sizes[:], 0)
    96  		if err != nil {
    97  			return
    98  		}
    99  		if n == 0 {
   100  			return
   101  		}
   102  		n = sizes[0]
   103  		return
   104  	} else {
   105  		return t.tunFile.Read(p)
   106  	}
   107  }
   108  
   109  func (t *NativeTun) Write(p []byte) (n int, err error) {
   110  	if t.gsoEnabled {
   111  		err = t.BatchWrite([][]byte{p}, virtioNetHdrLen)
   112  		if err != nil {
   113  			return
   114  		}
   115  		n = len(p)
   116  		return
   117  	}
   118  	return t.tunFile.Write(p)
   119  }
   120  
   121  func (t *NativeTun) WriteVectorised(buffers []*buf.Buffer) error {
   122  	if t.gsoEnabled {
   123  		n := buf.LenMulti(buffers)
   124  		buffer := buf.NewSize(virtioNetHdrLen + n)
   125  		buffer.Truncate(virtioNetHdrLen)
   126  		buf.CopyMulti(buffer.Extend(n), buffers)
   127  		_, err := t.tunFile.Write(buffer.Bytes())
   128  		buffer.Release()
   129  		return err
   130  	} else {
   131  		return t.tunWriter.WriteVectorised(buffers)
   132  	}
   133  }
   134  
   135  func (t *NativeTun) BatchSize() int {
   136  	if !t.gsoEnabled {
   137  		return 1
   138  	}
   139  	/* // Not works on some devices: https://github.com/SagerNet/sing-box/issues/1605
   140  	batchSize := int(gsoMaxSize/t.options.MTU) * 2
   141  	if batchSize > idealBatchSize {
   142  		batchSize = idealBatchSize
   143  	}
   144  	return batchSize*/
   145  	return idealBatchSize
   146  }
   147  
   148  func (t *NativeTun) BatchRead(buffers [][]byte, offset int, readN []int) (n int, err error) {
   149  	t.gsoReadAccess.Lock()
   150  	defer t.gsoReadAccess.Unlock()
   151  	n, err = t.tunFile.Read(t.gsoBuffer)
   152  	if err != nil {
   153  		return
   154  	}
   155  	return handleVirtioRead(t.gsoBuffer[:n], buffers, readN, offset)
   156  }
   157  
   158  func (t *NativeTun) BatchWrite(buffers [][]byte, offset int) error {
   159  	t.tcpGROAccess.Lock()
   160  	defer func() {
   161  		t.tcp4GROTable.reset()
   162  		t.tcp6GROTable.reset()
   163  		t.tcpGROAccess.Unlock()
   164  	}()
   165  	t.gsoToWrite = t.gsoToWrite[:0]
   166  	err := handleGRO(buffers, offset, t.tcp4GROTable, t.tcp6GROTable, &t.gsoToWrite)
   167  	if err != nil {
   168  		return err
   169  	}
   170  	offset -= virtioNetHdrLen
   171  	for _, bufferIndex := range t.gsoToWrite {
   172  		_, err = t.tunFile.Write(buffers[bufferIndex][offset:])
   173  		if err != nil {
   174  			return err
   175  		}
   176  	}
   177  	return nil
   178  }
   179  
   180  var controlPath string
   181  
   182  func init() {
   183  	const defaultTunPath = "/dev/net/tun"
   184  	const androidTunPath = "/dev/tun"
   185  	if rw.FileExists(androidTunPath) {
   186  		controlPath = androidTunPath
   187  	} else {
   188  		controlPath = defaultTunPath
   189  	}
   190  }
   191  
   192  func open(name string, vnetHdr bool) (int, error) {
   193  	fd, err := unix.Open(controlPath, unix.O_RDWR, 0)
   194  	if err != nil {
   195  		return -1, err
   196  	}
   197  
   198  	var ifr struct {
   199  		name  [16]byte
   200  		flags uint16
   201  		_     [22]byte
   202  	}
   203  
   204  	copy(ifr.name[:], name)
   205  	ifr.flags = unix.IFF_TUN | unix.IFF_NO_PI
   206  	if vnetHdr {
   207  		ifr.flags |= unix.IFF_VNET_HDR
   208  	}
   209  	_, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), unix.TUNSETIFF, uintptr(unsafe.Pointer(&ifr)))
   210  	if errno != 0 {
   211  		unix.Close(fd)
   212  		return -1, errno
   213  	}
   214  
   215  	if err = unix.SetNonblock(fd, true); err != nil {
   216  		unix.Close(fd)
   217  		return -1, err
   218  	}
   219  
   220  	return fd, nil
   221  }
   222  
   223  func (t *NativeTun) configure(tunLink netlink.Link) error {
   224  	err := netlink.LinkSetMTU(tunLink, int(t.options.MTU))
   225  	if err == unix.EPERM {
   226  		// unprivileged
   227  		return nil
   228  	} else if err != nil {
   229  		return err
   230  	}
   231  
   232  	if len(t.options.Inet4Address) > 0 {
   233  		for _, address := range t.options.Inet4Address {
   234  			addr4, _ := netlink.ParseAddr(address.String())
   235  			err = netlink.AddrAdd(tunLink, addr4)
   236  			if err != nil {
   237  				return err
   238  			}
   239  		}
   240  	}
   241  	if len(t.options.Inet6Address) > 0 {
   242  		for _, address := range t.options.Inet6Address {
   243  			addr6, _ := netlink.ParseAddr(address.String())
   244  			err = netlink.AddrAdd(tunLink, addr6)
   245  			if err != nil {
   246  				return err
   247  			}
   248  		}
   249  	}
   250  
   251  	if t.options.GSO {
   252  		var vnetHdrEnabled bool
   253  		vnetHdrEnabled, err = checkVNETHDREnabled(t.tunFd, t.options.Name)
   254  		if err != nil {
   255  			return E.Cause(err, "enable offload: check IFF_VNET_HDR enabled")
   256  		}
   257  		if !vnetHdrEnabled {
   258  			return E.Cause(err, "enable offload: IFF_VNET_HDR not enabled")
   259  		}
   260  		err = setTCPOffload(t.tunFd)
   261  		if err != nil {
   262  			return err
   263  		}
   264  		t.gsoEnabled = true
   265  		t.gsoBuffer = make([]byte, virtioNetHdrLen+int(gsoMaxSize))
   266  		t.tcp4GROTable = newTCPGROTable()
   267  		t.tcp6GROTable = newTCPGROTable()
   268  	}
   269  
   270  	var rxChecksumOffload bool
   271  	rxChecksumOffload, err = checkChecksumOffload(t.options.Name, unix.ETHTOOL_GRXCSUM)
   272  	if err == nil && !rxChecksumOffload {
   273  		_ = setChecksumOffload(t.options.Name, unix.ETHTOOL_SRXCSUM)
   274  	}
   275  
   276  	if t.options._TXChecksumOffload {
   277  		var txChecksumOffload bool
   278  		txChecksumOffload, err = checkChecksumOffload(t.options.Name, unix.ETHTOOL_GTXCSUM)
   279  		if err != nil {
   280  			return err
   281  		}
   282  		if err == nil && !txChecksumOffload {
   283  			err = setChecksumOffload(t.options.Name, unix.ETHTOOL_STXCSUM)
   284  			if err != nil {
   285  				return err
   286  			}
   287  		}
   288  		t.txChecksumOffload = true
   289  	}
   290  
   291  	err = netlink.LinkSetUp(tunLink)
   292  	if err != nil {
   293  		return err
   294  	}
   295  
   296  	if t.options.TableIndex == 0 {
   297  		for {
   298  			t.options.TableIndex = int(rand.Uint32())
   299  			routeList, fErr := netlink.RouteListFiltered(netlink.FAMILY_ALL, &netlink.Route{Table: t.options.TableIndex}, netlink.RT_FILTER_TABLE)
   300  			if len(routeList) == 0 || fErr != nil {
   301  				break
   302  			}
   303  		}
   304  	}
   305  
   306  	err = t.setRoute(tunLink)
   307  	if err != nil {
   308  		_ = t.unsetRoute0(tunLink)
   309  		return err
   310  	}
   311  
   312  	err = t.unsetRules()
   313  	if err != nil {
   314  		return E.Cause(err, "cleanup rules")
   315  	}
   316  	err = t.setRules()
   317  	if err != nil {
   318  		_ = t.unsetRules()
   319  		return err
   320  	}
   321  
   322  	t.setSearchDomainForSystemdResolved()
   323  
   324  	if t.options.AutoRoute && runtime.GOOS == "android" {
   325  		t.interfaceCallback = t.options.InterfaceMonitor.RegisterCallback(t.routeUpdate)
   326  	}
   327  	return nil
   328  }
   329  
   330  func (t *NativeTun) Close() error {
   331  	if t.interfaceCallback != nil {
   332  		t.options.InterfaceMonitor.UnregisterCallback(t.interfaceCallback)
   333  	}
   334  	return E.Errors(t.unsetRoute(), t.unsetRules(), common.Close(common.PtrOrNil(t.tunFile)))
   335  }
   336  
   337  func (t *NativeTun) TXChecksumOffload() bool {
   338  	return t.txChecksumOffload
   339  }
   340  
   341  func prefixToIPNet(prefix netip.Prefix) *net.IPNet {
   342  	return &net.IPNet{
   343  		IP:   prefix.Addr().AsSlice(),
   344  		Mask: net.CIDRMask(prefix.Bits(), prefix.Addr().BitLen()),
   345  	}
   346  }
   347  
   348  func (t *NativeTun) routes(tunLink netlink.Link) ([]netlink.Route, error) {
   349  	routeRanges, err := t.options.BuildAutoRouteRanges(false)
   350  	if err != nil {
   351  		return nil, err
   352  	}
   353  	return common.Map(routeRanges, func(it netip.Prefix) netlink.Route {
   354  		return netlink.Route{
   355  			Dst:       prefixToIPNet(it),
   356  			LinkIndex: tunLink.Attrs().Index,
   357  			Table:     t.options.TableIndex,
   358  		}
   359  	}), nil
   360  }
   361  
   362  const (
   363  	ruleStart = 9000
   364  	ruleEnd   = ruleStart + 10
   365  )
   366  
   367  func (t *NativeTun) nextIndex6() int {
   368  	ruleList, err := netlink.RuleList(netlink.FAMILY_V6)
   369  	if err != nil {
   370  		return -1
   371  	}
   372  	var minIndex int
   373  	for _, rule := range ruleList {
   374  		if rule.Priority > 0 && (minIndex == 0 || rule.Priority < minIndex) {
   375  			minIndex = rule.Priority
   376  		}
   377  	}
   378  	minIndex--
   379  	t.ruleIndex6 = append(t.ruleIndex6, minIndex)
   380  	return minIndex
   381  }
   382  
   383  func (t *NativeTun) rules() []*netlink.Rule {
   384  	if !t.options.AutoRoute {
   385  		if len(t.options.Inet6Address) > 0 {
   386  			it := netlink.NewRule()
   387  			it.Priority = t.nextIndex6()
   388  			it.Table = t.options.TableIndex
   389  			it.Family = unix.AF_INET6
   390  			it.OifName = t.options.Name
   391  			return []*netlink.Rule{it}
   392  		}
   393  		return nil
   394  	}
   395  
   396  	var p4, p6 bool
   397  	var pRule int
   398  	if len(t.options.Inet4Address) > 0 {
   399  		p4 = true
   400  		pRule += 1
   401  	}
   402  	if len(t.options.Inet6Address) > 0 {
   403  		p6 = true
   404  		pRule += 1
   405  	}
   406  	if pRule == 0 {
   407  		return []*netlink.Rule{}
   408  	}
   409  
   410  	var rules []*netlink.Rule
   411  	var it *netlink.Rule
   412  
   413  	excludeRanges := t.options.ExcludedRanges()
   414  	priority := ruleStart
   415  	priority6 := priority
   416  	nopPriority := ruleEnd
   417  
   418  	for _, excludeRange := range excludeRanges {
   419  		if p4 {
   420  			it = netlink.NewRule()
   421  			it.Priority = priority
   422  			it.UIDRange = netlink.NewRuleUIDRange(excludeRange.Start, excludeRange.End)
   423  			it.Goto = nopPriority
   424  			it.Family = unix.AF_INET
   425  			rules = append(rules, it)
   426  		}
   427  		if p6 {
   428  			it = netlink.NewRule()
   429  			it.Priority = priority6
   430  			it.UIDRange = netlink.NewRuleUIDRange(excludeRange.Start, excludeRange.End)
   431  			it.Goto = nopPriority
   432  			it.Family = unix.AF_INET6
   433  			rules = append(rules, it)
   434  		}
   435  	}
   436  	if len(excludeRanges) > 0 {
   437  		if p4 {
   438  			priority++
   439  		}
   440  		if p6 {
   441  			priority6++
   442  		}
   443  	}
   444  	if len(t.options.IncludeInterface) > 0 {
   445  		matchPriority := priority + 2*len(t.options.IncludeInterface) + 1
   446  		for _, includeInterface := range t.options.IncludeInterface {
   447  			if p4 {
   448  				it = netlink.NewRule()
   449  				it.Priority = priority
   450  				it.IifName = includeInterface
   451  				it.Goto = matchPriority
   452  				it.Family = unix.AF_INET
   453  				rules = append(rules, it)
   454  				priority++
   455  			}
   456  			if p6 {
   457  				it = netlink.NewRule()
   458  				it.Priority = priority6
   459  				it.IifName = includeInterface
   460  				it.Goto = matchPriority
   461  				it.Family = unix.AF_INET6
   462  				rules = append(rules, it)
   463  				priority6++
   464  			}
   465  		}
   466  		if p4 {
   467  			it = netlink.NewRule()
   468  			it.Priority = priority
   469  			it.Family = unix.AF_INET
   470  			it.Goto = nopPriority
   471  			rules = append(rules, it)
   472  			priority++
   473  
   474  			it = netlink.NewRule()
   475  			it.Priority = matchPriority
   476  			it.Family = unix.AF_INET
   477  			rules = append(rules, it)
   478  			priority++
   479  		}
   480  		if p6 {
   481  			it = netlink.NewRule()
   482  			it.Priority = priority6
   483  			it.Family = unix.AF_INET6
   484  			it.Goto = nopPriority
   485  			rules = append(rules, it)
   486  			priority6++
   487  
   488  			it = netlink.NewRule()
   489  			it.Priority = matchPriority
   490  			it.Family = unix.AF_INET6
   491  			rules = append(rules, it)
   492  			priority6++
   493  		}
   494  	} else if len(t.options.ExcludeInterface) > 0 {
   495  		for _, excludeInterface := range t.options.ExcludeInterface {
   496  			if p4 {
   497  				it = netlink.NewRule()
   498  				it.Priority = priority
   499  				it.IifName = excludeInterface
   500  				it.Goto = nopPriority
   501  				it.Family = unix.AF_INET
   502  				rules = append(rules, it)
   503  				priority++
   504  			}
   505  			if p6 {
   506  				it = netlink.NewRule()
   507  				it.Priority = priority6
   508  				it.IifName = excludeInterface
   509  				it.Goto = nopPriority
   510  				it.Family = unix.AF_INET6
   511  				rules = append(rules, it)
   512  				priority6++
   513  			}
   514  		}
   515  	}
   516  
   517  	if runtime.GOOS == "android" && t.options.InterfaceMonitor.AndroidVPNEnabled() {
   518  		const protectedFromVPN = 0x20000
   519  		if p4 || t.options.StrictRoute {
   520  			it = netlink.NewRule()
   521  			if t.options.InterfaceMonitor.OverrideAndroidVPN() {
   522  				it.Mark = protectedFromVPN
   523  			}
   524  			it.Mask = protectedFromVPN
   525  			it.Priority = priority
   526  			it.Family = unix.AF_INET
   527  			it.Goto = nopPriority
   528  			rules = append(rules, it)
   529  			priority++
   530  		}
   531  		if p6 || t.options.StrictRoute {
   532  			it = netlink.NewRule()
   533  			if t.options.InterfaceMonitor.OverrideAndroidVPN() {
   534  				it.Mark = protectedFromVPN
   535  			}
   536  			it.Mask = protectedFromVPN
   537  			it.Family = unix.AF_INET6
   538  			it.Priority = priority6
   539  			it.Goto = nopPriority
   540  			rules = append(rules, it)
   541  			priority6++
   542  		}
   543  	}
   544  
   545  	if t.options.StrictRoute {
   546  		if !p4 {
   547  			it = netlink.NewRule()
   548  			it.Priority = priority
   549  			it.Family = unix.AF_INET
   550  			it.Type = unix.FR_ACT_UNREACHABLE
   551  			rules = append(rules, it)
   552  			priority++
   553  		}
   554  		if !p6 {
   555  			it = netlink.NewRule()
   556  			it.Priority = priority6
   557  			it.Family = unix.AF_INET6
   558  			it.Type = unix.FR_ACT_UNREACHABLE
   559  			rules = append(rules, it)
   560  			priority6++
   561  		}
   562  	}
   563  
   564  	if runtime.GOOS != "android" {
   565  		if p4 {
   566  			for _, address := range t.options.Inet4Address {
   567  				it = netlink.NewRule()
   568  				it.Priority = priority
   569  				it.Dst = address.Masked()
   570  				it.Table = t.options.TableIndex
   571  				it.Family = unix.AF_INET
   572  				rules = append(rules, it)
   573  			}
   574  			priority++
   575  		}
   576  		/*if p6 {
   577  			it = netlink.NewRule()
   578  			it.Priority = priority
   579  			it.Dst = t.options.Inet6Address.Masked()
   580  			it.Table = tunTableIndex
   581  			it.Family = unix.AF_INET6
   582  			rules = append(rules, it)
   583  		}*/
   584  		if p4 {
   585  			it = netlink.NewRule()
   586  			it.Priority = priority
   587  			it.IPProto = syscall.IPPROTO_ICMP
   588  			it.Goto = nopPriority
   589  			it.Family = unix.AF_INET
   590  			rules = append(rules, it)
   591  			priority++
   592  		}
   593  		if p6 {
   594  			it = netlink.NewRule()
   595  			it.Priority = priority6
   596  			it.IPProto = syscall.IPPROTO_ICMPV6
   597  			it.Goto = nopPriority
   598  			it.Family = unix.AF_INET6
   599  			rules = append(rules, it)
   600  			priority6++
   601  		}
   602  		if p4 {
   603  			it = netlink.NewRule()
   604  			it.Priority = priority
   605  			it.Invert = true
   606  			it.Dport = netlink.NewRulePortRange(53, 53)
   607  			it.Table = unix.RT_TABLE_MAIN
   608  			it.SuppressPrefixlen = 0
   609  			it.Family = unix.AF_INET
   610  			rules = append(rules, it)
   611  		}
   612  		if p6 {
   613  			it = netlink.NewRule()
   614  			it.Priority = priority6
   615  			it.Invert = true
   616  			it.Dport = netlink.NewRulePortRange(53, 53)
   617  			it.Table = unix.RT_TABLE_MAIN
   618  			it.SuppressPrefixlen = 0
   619  			it.Family = unix.AF_INET6
   620  			rules = append(rules, it)
   621  		}
   622  	}
   623  
   624  	if p4 {
   625  		if t.options.StrictRoute {
   626  			it = netlink.NewRule()
   627  			it.Priority = priority
   628  			it.Table = t.options.TableIndex
   629  			it.Family = unix.AF_INET
   630  			rules = append(rules, it)
   631  		} else {
   632  			it = netlink.NewRule()
   633  			it.Priority = priority
   634  			it.Invert = true
   635  			it.IifName = "lo"
   636  			it.Table = t.options.TableIndex
   637  			it.Family = unix.AF_INET
   638  			rules = append(rules, it)
   639  
   640  			it = netlink.NewRule()
   641  			it.Priority = priority
   642  			it.IifName = "lo"
   643  			it.Src = netip.PrefixFrom(netip.IPv4Unspecified(), 32)
   644  			it.Table = t.options.TableIndex
   645  			it.Family = unix.AF_INET
   646  			rules = append(rules, it)
   647  
   648  			for _, address := range t.options.Inet4Address {
   649  				it = netlink.NewRule()
   650  				it.Priority = priority
   651  				it.IifName = "lo"
   652  				it.Src = address.Masked()
   653  				it.Table = t.options.TableIndex
   654  				it.Family = unix.AF_INET
   655  				rules = append(rules, it)
   656  			}
   657  		}
   658  		priority++
   659  	}
   660  	if p6 {
   661  		if !t.options.StrictRoute {
   662  			for _, address := range t.options.Inet6Address {
   663  				it = netlink.NewRule()
   664  				it.Priority = priority6
   665  				it.IifName = "lo"
   666  				it.Src = address.Masked()
   667  				it.Table = t.options.TableIndex
   668  				it.Family = unix.AF_INET6
   669  				rules = append(rules, it)
   670  			}
   671  			priority6++
   672  
   673  			it = netlink.NewRule()
   674  			it.Priority = priority6
   675  			it.IifName = "lo"
   676  			it.Src = netip.PrefixFrom(netip.IPv6Unspecified(), 1)
   677  			it.Goto = nopPriority
   678  			it.Family = unix.AF_INET6
   679  			rules = append(rules, it)
   680  
   681  			it = netlink.NewRule()
   682  			it.Priority = priority6
   683  			it.IifName = "lo"
   684  			it.Src = netip.PrefixFrom(netip.AddrFrom16([16]byte{0: 128}), 1)
   685  			it.Goto = nopPriority
   686  			it.Family = unix.AF_INET6
   687  			rules = append(rules, it)
   688  
   689  			priority6++
   690  		}
   691  
   692  		it = netlink.NewRule()
   693  		it.Priority = priority6
   694  		it.Table = t.options.TableIndex
   695  		it.Family = unix.AF_INET6
   696  		rules = append(rules, it)
   697  		priority6++
   698  	}
   699  	if p4 {
   700  		it = netlink.NewRule()
   701  		it.Priority = nopPriority
   702  		it.Family = unix.AF_INET
   703  		rules = append(rules, it)
   704  	}
   705  	if p6 {
   706  		it = netlink.NewRule()
   707  		it.Priority = nopPriority
   708  		it.Family = unix.AF_INET6
   709  		rules = append(rules, it)
   710  	}
   711  	return rules
   712  }
   713  
   714  func (t *NativeTun) setRoute(tunLink netlink.Link) error {
   715  	routes, err := t.routes(tunLink)
   716  	if err != nil {
   717  		return err
   718  	}
   719  	for i, route := range routes {
   720  		err := netlink.RouteAdd(&route)
   721  		if err != nil {
   722  			return E.Cause(err, "add route ", i)
   723  		}
   724  	}
   725  	return nil
   726  }
   727  
   728  func (t *NativeTun) setRules() error {
   729  	for i, rule := range t.rules() {
   730  		err := netlink.RuleAdd(rule)
   731  		if err != nil {
   732  			return E.Cause(err, "add rule ", i, "/", len(t.rules()))
   733  		}
   734  	}
   735  	return nil
   736  }
   737  
   738  func (t *NativeTun) unsetRoute() error {
   739  	if t.options.FileDescriptor > 0 {
   740  		return nil
   741  	}
   742  	tunLink, err := netlink.LinkByName(t.options.Name)
   743  	if err != nil {
   744  		return err
   745  	}
   746  	return t.unsetRoute0(tunLink)
   747  }
   748  
   749  func (t *NativeTun) unsetRoute0(tunLink netlink.Link) error {
   750  	if routes, err := t.routes(tunLink); err == nil {
   751  		for _, route := range routes {
   752  			_ = netlink.RouteDel(&route)
   753  		}
   754  	}
   755  	return nil
   756  }
   757  
   758  func (t *NativeTun) unsetRules() error {
   759  	if t.options.FileDescriptor > 0 {
   760  		return nil
   761  	}
   762  	if len(t.ruleIndex6) > 0 {
   763  		for _, index := range t.ruleIndex6 {
   764  			ruleToDel := netlink.NewRule()
   765  			ruleToDel.Family = unix.AF_INET6
   766  			ruleToDel.Priority = index
   767  			err := netlink.RuleDel(ruleToDel)
   768  			if err != nil {
   769  				return E.Cause(err, "unset rule6 ", index)
   770  			}
   771  		}
   772  		t.ruleIndex6 = nil
   773  	}
   774  	if t.options.AutoRoute {
   775  		ruleList, err := netlink.RuleList(netlink.FAMILY_ALL)
   776  		if err != nil {
   777  			return err
   778  		}
   779  		for _, rule := range ruleList {
   780  			if rule.Priority >= ruleStart && rule.Priority <= ruleEnd {
   781  				ruleToDel := netlink.NewRule()
   782  				ruleToDel.Family = rule.Family
   783  				ruleToDel.Priority = rule.Priority
   784  				err = netlink.RuleDel(ruleToDel)
   785  				if err != nil {
   786  					return E.Cause(err, "unset rule ", rule.Priority, " for ", rule.Family)
   787  				}
   788  			}
   789  		}
   790  	}
   791  	return nil
   792  }
   793  
   794  func (t *NativeTun) resetRules() error {
   795  	t.unsetRules()
   796  	return t.setRules()
   797  }
   798  
   799  func (t *NativeTun) routeUpdate(event int) {
   800  	if event&EventAndroidVPNUpdate == 0 {
   801  		return
   802  	}
   803  	err := t.resetRules()
   804  	if err != nil {
   805  		if t.options.Logger != nil {
   806  			t.options.Logger.Error(E.Cause(err, "reset route"))
   807  		}
   808  	}
   809  }
   810  
   811  func (t *NativeTun) setSearchDomainForSystemdResolved() {
   812  	ctlPath, err := exec.LookPath("resolvectl")
   813  	if err != nil {
   814  		return
   815  	}
   816  	var dnsServer []netip.Addr
   817  	if len(t.options.Inet4Address) > 0 {
   818  		dnsServer = append(dnsServer, t.options.Inet4Address[0].Addr().Next())
   819  	}
   820  	if len(t.options.Inet6Address) > 0 {
   821  		dnsServer = append(dnsServer, t.options.Inet6Address[0].Addr().Next())
   822  	}
   823  	shell.Exec(ctlPath, "domain", t.options.Name, "~.").Start()
   824  	if t.options.AutoRoute {
   825  		shell.Exec(ctlPath, "default-route", t.options.Name, "true").Start()
   826  		shell.Exec(ctlPath, append([]string{"dns", t.options.Name}, common.Map(dnsServer, netip.Addr.String)...)...).Start()
   827  	}
   828  }