github.com/MerlinKodo/sing-tun@v0.1.15/tun_rules.go (about) 1 package tun 2 3 import ( 4 "context" 5 "net/netip" 6 "os" 7 "runtime" 8 "sort" 9 "strconv" 10 11 "github.com/sagernet/sing/common" 12 E "github.com/sagernet/sing/common/exceptions" 13 "github.com/sagernet/sing/common/ranges" 14 15 "go4.org/netipx" 16 ) 17 18 const ( 19 androidUserRange = 100000 20 userEnd uint32 = 0xFFFFFFFF - 1 21 ) 22 23 func (o *Options) BuildAndroidRules(packageManager PackageManager, errorHandler E.Handler) { 24 var includeUser []uint32 25 if len(o.IncludeAndroidUser) > 0 { 26 o.IncludeAndroidUser = common.Uniq(o.IncludeAndroidUser) 27 sort.Ints(o.IncludeAndroidUser) 28 var userExcludeRange []ranges.Range[uint32] 29 for _, androidUser := range o.IncludeAndroidUser { 30 includeUser = append(includeUser, uint32(androidUser)) 31 userExcludeRange = append(userExcludeRange, ranges.New[uint32](uint32(androidUser)*androidUserRange, uint32(androidUser+1)*androidUserRange-1)) 32 } 33 userExcludeRange = ranges.Revert(0, userEnd, userExcludeRange) 34 o.ExcludeUID = append(o.ExcludeUID, userExcludeRange...) 35 } 36 if len(includeUser) == 0 { 37 userDirs, err := os.ReadDir("/data/user") 38 if err == nil { 39 var userId uint64 40 for _, userDir := range userDirs { 41 userId, err = strconv.ParseUint(userDir.Name(), 10, 32) 42 if err != nil { 43 continue 44 } 45 includeUser = append(includeUser, uint32(userId)) 46 } 47 } 48 } 49 if len(includeUser) == 0 { 50 includeUser = []uint32{0} 51 } 52 if len(o.IncludePackage) > 0 { 53 o.IncludePackage = common.Uniq(o.IncludePackage) 54 for _, packageName := range o.IncludePackage { 55 if sharedId, loaded := packageManager.IDBySharedPackage(packageName); loaded { 56 for _, androidUser := range includeUser { 57 o.IncludeUID = append(o.IncludeUID, ranges.NewSingle(sharedId+androidUser*androidUserRange)) 58 } 59 continue 60 } 61 if userId, loaded := packageManager.IDByPackage(packageName); loaded { 62 for _, androidUser := range includeUser { 63 o.IncludeUID = append(o.IncludeUID, ranges.NewSingle(userId+androidUser*androidUserRange)) 64 } 65 continue 66 } 67 errorHandler.NewError(context.Background(), E.New("package to include not found: ", packageName)) 68 } 69 } 70 if len(o.ExcludePackage) > 0 { 71 o.ExcludePackage = common.Uniq(o.ExcludePackage) 72 for _, packageName := range o.ExcludePackage { 73 if sharedId, loaded := packageManager.IDBySharedPackage(packageName); loaded { 74 for _, androidUser := range includeUser { 75 o.ExcludeUID = append(o.ExcludeUID, ranges.NewSingle(sharedId+androidUser*androidUserRange)) 76 } 77 } 78 if userId, loaded := packageManager.IDByPackage(packageName); loaded { 79 for _, androidUser := range includeUser { 80 o.ExcludeUID = append(o.ExcludeUID, ranges.NewSingle(userId+androidUser*androidUserRange)) 81 } 82 continue 83 } 84 errorHandler.NewError(context.Background(), E.New("package to exclude not found: ", packageName)) 85 } 86 } 87 } 88 89 func (o *Options) ExcludedRanges() (uidRanges []ranges.Range[uint32]) { 90 return buildExcludedRanges(o.IncludeUID, o.ExcludeUID) 91 } 92 93 func buildExcludedRanges(includeRanges []ranges.Range[uint32], excludeRanges []ranges.Range[uint32]) (uidRanges []ranges.Range[uint32]) { 94 uidRanges = includeRanges 95 if len(uidRanges) > 0 { 96 uidRanges = ranges.Exclude(uidRanges, excludeRanges) 97 uidRanges = ranges.Revert(0, userEnd, uidRanges) 98 } else { 99 uidRanges = excludeRanges 100 } 101 return ranges.Merge(uidRanges) 102 } 103 104 const autoRouteUseSubRanges = runtime.GOOS == "darwin" 105 106 func (o *Options) BuildAutoRouteRanges() ([]netip.Prefix, error) { 107 var routeRanges []netip.Prefix 108 if len(o.Inet4Address) > 0 { 109 var inet4Ranges []netip.Prefix 110 if len(o.Inet4RouteAddress) > 0 { 111 inet4Ranges = o.Inet4RouteAddress 112 } else if autoRouteUseSubRanges { 113 inet4Ranges = []netip.Prefix{ 114 netip.PrefixFrom(netip.AddrFrom4([4]byte{1, 0, 0, 0}), 8), 115 netip.PrefixFrom(netip.AddrFrom4([4]byte{2, 0, 0, 0}), 7), 116 netip.PrefixFrom(netip.AddrFrom4([4]byte{4, 0, 0, 0}), 6), 117 netip.PrefixFrom(netip.AddrFrom4([4]byte{8, 0, 0, 0}), 5), 118 netip.PrefixFrom(netip.AddrFrom4([4]byte{16, 0, 0, 0}), 4), 119 netip.PrefixFrom(netip.AddrFrom4([4]byte{32, 0, 0, 0}), 3), 120 netip.PrefixFrom(netip.AddrFrom4([4]byte{64, 0, 0, 0}), 2), 121 netip.PrefixFrom(netip.AddrFrom4([4]byte{128, 0, 0, 0}), 1), 122 } 123 } else { 124 inet4Ranges = []netip.Prefix{netip.PrefixFrom(netip.IPv4Unspecified(), 0)} 125 } 126 if len(o.Inet4RouteExcludeAddress) == 0 { 127 routeRanges = append(routeRanges, inet4Ranges...) 128 } else { 129 var builder netipx.IPSetBuilder 130 for _, inet4Range := range inet4Ranges { 131 builder.AddPrefix(inet4Range) 132 } 133 for _, prefix := range o.Inet4RouteExcludeAddress { 134 builder.RemovePrefix(prefix) 135 } 136 resultSet, err := builder.IPSet() 137 if err != nil { 138 return nil, E.Cause(err, "build IPv4 route address") 139 } 140 routeRanges = append(routeRanges, resultSet.Prefixes()...) 141 } 142 } 143 if len(o.Inet6Address) > 0 { 144 var inet6Ranges []netip.Prefix 145 if len(o.Inet6RouteAddress) > 0 { 146 inet6Ranges = o.Inet6RouteAddress 147 } else if autoRouteUseSubRanges { 148 inet6Ranges = []netip.Prefix{ 149 netip.PrefixFrom(netip.IPv6Unspecified(), 1), 150 netip.PrefixFrom(netip.AddrFrom16([16]byte{0: 128}), 1), 151 } 152 } else { 153 inet6Ranges = []netip.Prefix{netip.PrefixFrom(netip.IPv6Unspecified(), 0)} 154 } 155 if len(o.Inet6RouteExcludeAddress) == 0 { 156 routeRanges = append(routeRanges, inet6Ranges...) 157 } else { 158 var builder netipx.IPSetBuilder 159 for _, inet6Range := range inet6Ranges { 160 builder.AddPrefix(inet6Range) 161 } 162 for _, prefix := range o.Inet6RouteExcludeAddress { 163 builder.RemovePrefix(prefix) 164 } 165 resultSet, err := builder.IPSet() 166 if err != nil { 167 return nil, E.Cause(err, "build IPv6 route address") 168 } 169 routeRanges = append(routeRanges, resultSet.Prefixes()...) 170 } 171 } 172 return routeRanges, nil 173 }