@@ -148,6 +148,7 @@ pub struct VpnInterface {
148
148
pub struct SplitTunnelHandle {
149
149
redir_handle : Option < RedirectHandle > ,
150
150
tun_name : String ,
151
+ route_manager : RouteManagerHandle ,
151
152
}
152
153
153
154
impl SplitTunnelHandle {
@@ -168,7 +169,9 @@ impl SplitTunnelHandle {
168
169
vpn_interface : Option < VpnInterface > ,
169
170
) -> Result < Self , Error > {
170
171
let handle = self . redir_handle . take ( ) . unwrap ( ) ;
171
- let ( st_utun, pktap_stream, classify, default_interface, _) = handle. stop ( ) . await ?;
172
+ let ( st_utun, pktap_stream, classify, _default_interface, _) = handle. stop ( ) . await ?;
173
+
174
+ let default_interface = get_default_interface ( & self . route_manager ) . await ?;
172
175
173
176
self . redir_handle = Some (
174
177
redirect_packets_for_pktap_stream (
@@ -197,6 +200,42 @@ pub async fn create_split_tunnel(
197
200
vpn_interface : Option < VpnInterface > ,
198
201
classify : impl Fn ( & PktapPacket ) -> RoutingDecision + Send + ' static ,
199
202
) -> Result < SplitTunnelHandle , Error > {
203
+ let default_interface = get_default_interface ( & route_manager) . await ?;
204
+
205
+ let mut tun_config = tun:: configure ( ) ;
206
+ tun_config. address ( ST_IFACE_IPV4 ) . up ( ) ;
207
+ let tun_device =
208
+ tun:: create_as_async ( & tun_config) . map_err ( Error :: CreateSplitTunnelInterface ) ?;
209
+ let tun_name = tun_device. get_ref ( ) . name ( ) . to_owned ( ) ;
210
+
211
+ // Add IPv6 address
212
+ // TODO: Only add IPv6 address if there's either a tun or a non-tun IPv6 route
213
+ // FIXME: Solve cleanly rather than using subcmd
214
+ let output = tokio:: process:: Command :: new ( "ifconfig" )
215
+ . args ( [ & tun_name, "inet6" , & ST_IFACE_IPV6 . to_string ( ) , "alias" ] )
216
+ . output ( )
217
+ . await
218
+ . map_err ( Error :: AddIpv6Address ) ?;
219
+ if !output. status . success ( ) {
220
+ return Err ( Error :: AddIpv6Address ( io:: Error :: new (
221
+ io:: ErrorKind :: Other ,
222
+ "ifconfig failed" ,
223
+ ) ) ) ;
224
+ }
225
+
226
+ let redir_handle =
227
+ redirect_packets ( tun_device, default_interface, vpn_interface, classify) . await ?;
228
+
229
+ Ok ( SplitTunnelHandle {
230
+ redir_handle : Some ( redir_handle) ,
231
+ tun_name,
232
+ route_manager,
233
+ } )
234
+ }
235
+
236
+ async fn get_default_interface (
237
+ route_manager : & RouteManagerHandle ,
238
+ ) -> Result < DefaultInterface , Error > {
200
239
let ( v4_default, v6_default) = route_manager
201
240
. get_default_routes ( )
202
241
. await
@@ -266,39 +305,10 @@ pub async fn create_split_tunnel(
266
305
None
267
306
} ;
268
307
269
- let default_interface = DefaultInterface {
308
+ Ok ( DefaultInterface {
270
309
name : default_interface,
271
310
v4_addrs : default_v4,
272
311
v6_addrs : default_v6,
273
- } ;
274
-
275
- let mut tun_config = tun:: configure ( ) ;
276
- tun_config. address ( ST_IFACE_IPV4 ) . up ( ) ;
277
- let tun_device =
278
- tun:: create_as_async ( & tun_config) . map_err ( Error :: CreateSplitTunnelInterface ) ?;
279
- let tun_name = tun_device. get_ref ( ) . name ( ) . to_owned ( ) ;
280
-
281
- // Add IPv6 address
282
- // TODO: Only add IPv6 address if there's either a tun or a non-tun IPv6 route
283
- // FIXME: Solve cleanly rather than using subcmd
284
- let output = tokio:: process:: Command :: new ( "ifconfig" )
285
- . args ( [ & tun_name, "inet6" , & ST_IFACE_IPV6 . to_string ( ) , "alias" ] )
286
- . output ( )
287
- . await
288
- . map_err ( Error :: AddIpv6Address ) ?;
289
- if !output. status . success ( ) {
290
- return Err ( Error :: AddIpv6Address ( io:: Error :: new (
291
- io:: ErrorKind :: Other ,
292
- "ifconfig failed" ,
293
- ) ) ) ;
294
- }
295
-
296
- let redir_handle =
297
- redirect_packets ( tun_device, default_interface, vpn_interface, classify) . await ?;
298
-
299
- Ok ( SplitTunnelHandle {
300
- redir_handle : Some ( redir_handle) ,
301
- tun_name,
302
312
} )
303
313
}
304
314
0 commit comments