github.com/sagernet/sing-tun@v0.3.0-beta.5/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 it = netlink.NewRule() 577 it.Priority = priority 578 it.Table = t.options.TableIndex 579 it.SuppressPrefixlen = 0 580 it.Family = unix.AF_INET 581 rules = append(rules, it) 582 priority++ 583 } 584 if p6 { 585 it = netlink.NewRule() 586 it.Priority = priority6 587 it.Table = t.options.TableIndex 588 it.SuppressPrefixlen = 0 589 it.Family = unix.AF_INET6 590 rules = append(rules, it) 591 priority6++ 592 } 593 if p4 && !t.options.StrictRoute { 594 it = netlink.NewRule() 595 it.Priority = priority 596 it.Invert = true 597 it.Dport = netlink.NewRulePortRange(53, 53) 598 it.Table = unix.RT_TABLE_MAIN 599 it.SuppressPrefixlen = 0 600 it.Family = unix.AF_INET 601 rules = append(rules, it) 602 603 it = netlink.NewRule() 604 it.Priority = priority 605 it.IPProto = syscall.IPPROTO_ICMP 606 it.Goto = nopPriority 607 it.Family = unix.AF_INET 608 rules = append(rules, it) 609 priority++ 610 } 611 if p6 && !t.options.StrictRoute { 612 it = netlink.NewRule() 613 it.Priority = priority6 614 it.Invert = true 615 it.Dport = netlink.NewRulePortRange(53, 53) 616 it.Table = unix.RT_TABLE_MAIN 617 it.SuppressPrefixlen = 0 618 it.Family = unix.AF_INET6 619 rules = append(rules, it) 620 621 it = netlink.NewRule() 622 it.Priority = priority6 623 it.IPProto = syscall.IPPROTO_ICMPV6 624 it.Goto = nopPriority 625 it.Family = unix.AF_INET6 626 rules = append(rules, it) 627 priority6++ 628 } 629 } 630 631 if p4 { 632 if t.options.StrictRoute { 633 it = netlink.NewRule() 634 it.Priority = priority 635 it.Table = t.options.TableIndex 636 it.Family = unix.AF_INET 637 rules = append(rules, it) 638 } else { 639 it = netlink.NewRule() 640 it.Priority = priority 641 it.Invert = true 642 it.IifName = "lo" 643 it.Table = t.options.TableIndex 644 it.Family = unix.AF_INET 645 rules = append(rules, it) 646 647 it = netlink.NewRule() 648 it.Priority = priority 649 it.IifName = "lo" 650 it.Src = netip.PrefixFrom(netip.IPv4Unspecified(), 32) 651 it.Table = t.options.TableIndex 652 it.Family = unix.AF_INET 653 rules = append(rules, it) 654 655 for _, address := range t.options.Inet4Address { 656 it = netlink.NewRule() 657 it.Priority = priority 658 it.IifName = "lo" 659 it.Src = address.Masked() 660 it.Table = t.options.TableIndex 661 it.Family = unix.AF_INET 662 rules = append(rules, it) 663 } 664 } 665 priority++ 666 } 667 if p6 { 668 if !t.options.StrictRoute { 669 for _, address := range t.options.Inet6Address { 670 it = netlink.NewRule() 671 it.Priority = priority6 672 it.IifName = "lo" 673 it.Src = address.Masked() 674 it.Table = t.options.TableIndex 675 it.Family = unix.AF_INET6 676 rules = append(rules, it) 677 } 678 priority6++ 679 680 it = netlink.NewRule() 681 it.Priority = priority6 682 it.IifName = "lo" 683 it.Src = netip.PrefixFrom(netip.IPv6Unspecified(), 1) 684 it.Goto = nopPriority 685 it.Family = unix.AF_INET6 686 rules = append(rules, it) 687 688 it = netlink.NewRule() 689 it.Priority = priority6 690 it.IifName = "lo" 691 it.Src = netip.PrefixFrom(netip.AddrFrom16([16]byte{0: 128}), 1) 692 it.Goto = nopPriority 693 it.Family = unix.AF_INET6 694 rules = append(rules, it) 695 696 priority6++ 697 } 698 699 it = netlink.NewRule() 700 it.Priority = priority6 701 it.Table = t.options.TableIndex 702 it.Family = unix.AF_INET6 703 rules = append(rules, it) 704 priority6++ 705 } 706 if p4 { 707 it = netlink.NewRule() 708 it.Priority = nopPriority 709 it.Family = unix.AF_INET 710 rules = append(rules, it) 711 } 712 if p6 { 713 it = netlink.NewRule() 714 it.Priority = nopPriority 715 it.Family = unix.AF_INET6 716 rules = append(rules, it) 717 } 718 return rules 719 } 720 721 func (t *NativeTun) setRoute(tunLink netlink.Link) error { 722 routes, err := t.routes(tunLink) 723 if err != nil { 724 return err 725 } 726 for i, route := range routes { 727 err := netlink.RouteAdd(&route) 728 if err != nil { 729 return E.Cause(err, "add route ", i) 730 } 731 } 732 return nil 733 } 734 735 func (t *NativeTun) setRules() error { 736 for i, rule := range t.rules() { 737 err := netlink.RuleAdd(rule) 738 if err != nil { 739 return E.Cause(err, "add rule ", i, "/", len(t.rules())) 740 } 741 } 742 return nil 743 } 744 745 func (t *NativeTun) unsetRoute() error { 746 if t.options.FileDescriptor > 0 { 747 return nil 748 } 749 tunLink, err := netlink.LinkByName(t.options.Name) 750 if err != nil { 751 return err 752 } 753 return t.unsetRoute0(tunLink) 754 } 755 756 func (t *NativeTun) unsetRoute0(tunLink netlink.Link) error { 757 if routes, err := t.routes(tunLink); err == nil { 758 for _, route := range routes { 759 _ = netlink.RouteDel(&route) 760 } 761 } 762 return nil 763 } 764 765 func (t *NativeTun) unsetRules() error { 766 if t.options.FileDescriptor > 0 { 767 return nil 768 } 769 if len(t.ruleIndex6) > 0 { 770 for _, index := range t.ruleIndex6 { 771 ruleToDel := netlink.NewRule() 772 ruleToDel.Family = unix.AF_INET6 773 ruleToDel.Priority = index 774 err := netlink.RuleDel(ruleToDel) 775 if err != nil { 776 return E.Cause(err, "unset rule6 ", index) 777 } 778 } 779 t.ruleIndex6 = nil 780 } 781 if t.options.AutoRoute { 782 ruleList, err := netlink.RuleList(netlink.FAMILY_ALL) 783 if err != nil { 784 return err 785 } 786 for _, rule := range ruleList { 787 if rule.Priority >= ruleStart && rule.Priority <= ruleEnd { 788 ruleToDel := netlink.NewRule() 789 ruleToDel.Family = rule.Family 790 ruleToDel.Priority = rule.Priority 791 err = netlink.RuleDel(ruleToDel) 792 if err != nil { 793 return E.Cause(err, "unset rule ", rule.Priority, " for ", rule.Family) 794 } 795 } 796 } 797 } 798 return nil 799 } 800 801 func (t *NativeTun) resetRules() error { 802 t.unsetRules() 803 return t.setRules() 804 } 805 806 func (t *NativeTun) routeUpdate(event int) { 807 if event&EventAndroidVPNUpdate == 0 { 808 return 809 } 810 err := t.resetRules() 811 if err != nil { 812 if t.options.Logger != nil { 813 t.options.Logger.Error(E.Cause(err, "reset route")) 814 } 815 } 816 } 817 818 func (t *NativeTun) setSearchDomainForSystemdResolved() { 819 ctlPath, err := exec.LookPath("resolvectl") 820 if err != nil { 821 return 822 } 823 var dnsServer []netip.Addr 824 if len(t.options.Inet4Address) > 0 { 825 dnsServer = append(dnsServer, t.options.Inet4Address[0].Addr().Next()) 826 } 827 if len(t.options.Inet6Address) > 0 { 828 dnsServer = append(dnsServer, t.options.Inet6Address[0].Addr().Next()) 829 } 830 go shell.Exec(ctlPath, "domain", t.options.Name, "~.").Run() 831 if t.options.AutoRoute { 832 go shell.Exec(ctlPath, "default-route", t.options.Name, "true").Run() 833 go shell.Exec(ctlPath, append([]string{"dns", t.options.Name}, common.Map(dnsServer, netip.Addr.String)...)...).Run() 834 } 835 }