@@ -2,13 +2,17 @@ package tun
22
33import (
44 "context"
5+ "net/netip"
56 "os"
7+ "runtime"
68 "sort"
79 "strconv"
810
911 "github.com/sagernet/sing/common"
1012 E "github.com/sagernet/sing/common/exceptions"
1113 "github.com/sagernet/sing/common/ranges"
14+
15+ "go4.org/netipx"
1216)
1317
1418const (
@@ -96,3 +100,74 @@ func buildExcludedRanges(includeRanges []ranges.Range[uint32], excludeRanges []r
96100 }
97101 return ranges .Merge (uidRanges )
98102}
103+
104+ const autoRouteUseSubRanges = runtime .GOOS == "darwin"
105+
106+ func (o * Options ) BuildAutoRouteRanges (underNetworkExtension bool ) ([]netip.Prefix , error ) {
107+ var routeRanges []netip.Prefix
108+ if o .AutoRoute && len (o .Inet4Address ) > 0 {
109+ var inet4Ranges []netip.Prefix
110+ if len (o .Inet4RouteAddress ) > 0 {
111+ inet4Ranges = o .Inet4RouteAddress
112+ } else if autoRouteUseSubRanges && ! underNetworkExtension {
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 && ! underNetworkExtension {
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+ }
0 commit comments