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