@@ -13,6 +13,7 @@ import (
1313 "syscall"
1414
1515 "github.com/tailscale/tailscale-android/libtailscale/ifaceparse"
16+ rangescalc "github.com/tailscale/tailscale-android/libtailscale/ranges_calc"
1617 "github.com/tailscale/wireguard-go/tun"
1718 "tailscale.com/net/dns"
1819 "tailscale.com/net/netmon"
@@ -117,36 +118,69 @@ func (b *backend) updateTUN(rcfg *router.Config, dcfg *dns.OSConfig) error {
117118 b .logger .Logf ("updateTUN: set nameservers" )
118119 }
119120
120- // Calculate effective allowed routes (Routes minus LocalRoutes) and add them to the builder.
121- prefixesV4 , prefixesV6 := newRangesCalc (rcfg .Routes , rcfg .LocalRoutes ).calculate ()
121+ // Decide whether to use ExcludeRoute (API 33+) or compute included prefixes
122+ // and pass them to AddRoute (older APIs).
123+ useExclude := false
124+ if sdk , err := b .appCtx .GetSDKInt (); err == nil && sdk >= 33 {
125+ useExclude = true
126+ }
122127
123- for _ , route := range prefixesV4 {
124- // Normalize route address; Builder.addRoute does not accept non-zero masked bits.
125- route = route .Masked ()
126- if err := builder .AddRoute (route .Addr ().String (), int32 (route .Bits ())); err != nil {
127- return err
128+ if useExclude {
129+ // For API 33+, use ExcludeRoute for LocalRoutes and AddRoute for Routes.
130+ for _ , route := range rcfg .Routes {
131+ // Normalize route address; Builder.addRoute does not accept non-zero masked bits.
132+ route = route .Masked ()
133+ if err := builder .AddRoute (route .Addr ().String (), int32 (route .Bits ())); err != nil {
134+ return err
135+ }
128136 }
129- }
130- for _ , route := range prefixesV6 {
131- // Normalize route address; Builder.addRoute does not accept non-zero masked bits.
132- route = route .Masked ()
133- if err := builder .AddRoute (route .Addr ().String (), int32 (route .Bits ())); err != nil {
137+
138+ for _ , route := range rcfg .LocalRoutes {
139+ addr := route .Addr ()
140+ if addr .IsLoopback () {
141+ continue // Skip the loopback addresses since VpnService throws an exception for those (both IPv4 and IPv6) - see https://android.googlesource.com/platform/frameworks/base/+/c741553/core/java/android/net/VpnService.java#303
142+ }
143+ route = route .Masked ()
144+ if err := builder .ExcludeRoute (route .Addr ().String (), int32 (route .Bits ())); err != nil {
145+ return err
146+ }
147+ }
148+
149+ b .logger .Logf ("updateTUN: added %d routes (exclude-mode), localRoutes=%d" , len (rcfg .Routes ), len (rcfg .LocalRoutes ))
150+ } else {
151+ // Older APIs: compute allowed-minus-disallowed prefixes and AddRoute them.
152+ prefixesV4 , prefixesV6 , err := rangescalc .Calculate (rcfg .Routes , rcfg .LocalRoutes )
153+ if err != nil {
154+ b .logger .Logf ("updateTUN: route calculation error: %v" , err )
134155 return err
135156 }
136- }
137157
138- b .logger .Logf (
139- "updateTUN: added routes: v4=%d v6=%d total=%d (input routes=%d, localRoutes=%d)" ,
140- len (prefixesV4 ),
141- len (prefixesV6 ),
142- len (prefixesV4 )+ len (prefixesV6 ),
143- len (rcfg .Routes ),
144- len (rcfg .LocalRoutes ),
145- )
146- b .logger .Logf ("updateTUN: input routes: %v" , rcfg .Routes )
147- b .logger .Logf ("updateTUN: input local routes: %v" , rcfg .LocalRoutes )
148- b .logger .Logf ("updateTUN: effective routes v4: %v" , prefixesV4 )
149- b .logger .Logf ("updateTUN: effective routes v6: %v" , prefixesV6 )
158+ for _ , route := range prefixesV4 {
159+ route = route .Masked ()
160+ if err := builder .AddRoute (route .Addr ().String (), int32 (route .Bits ())); err != nil {
161+ return err
162+ }
163+ }
164+ for _ , route := range prefixesV6 {
165+ route = route .Masked ()
166+ if err := builder .AddRoute (route .Addr ().String (), int32 (route .Bits ())); err != nil {
167+ return err
168+ }
169+ }
170+
171+ b .logger .Logf (
172+ "updateTUN: added routes: v4=%d v6=%d total=%d (input routes=%d, localRoutes=%d)" ,
173+ len (prefixesV4 ),
174+ len (prefixesV6 ),
175+ len (prefixesV4 )+ len (prefixesV6 ),
176+ len (rcfg .Routes ),
177+ len (rcfg .LocalRoutes ),
178+ )
179+ b .logger .Logf ("updateTUN: input routes: %v" , rcfg .Routes )
180+ b .logger .Logf ("updateTUN: input local routes: %v" , rcfg .LocalRoutes )
181+ b .logger .Logf ("updateTUN: effective routes v4: %v" , prefixesV4 )
182+ b .logger .Logf ("updateTUN: effective routes v6: %v" , prefixesV6 )
183+ }
150184
151185 for _ , addr := range rcfg .LocalAddrs {
152186 if err := builder .AddAddress (addr .Addr ().String (), int32 (addr .Bits ())); err != nil {
0 commit comments