Skip to content

Commit 2e56256

Browse files
committed
Update default interface on VPN interface change
1 parent 4243419 commit 2e56256

File tree

1 file changed

+41
-31
lines changed
  • talpid-core/src/split_tunnel/macos

1 file changed

+41
-31
lines changed

talpid-core/src/split_tunnel/macos/tun.rs

+41-31
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ pub struct VpnInterface {
149149
pub struct SplitTunnelHandle {
150150
redir_handle: Option<RedirectHandle>,
151151
tun_name: String,
152+
route_manager: RouteManagerHandle,
152153
}
153154

154155
impl SplitTunnelHandle {
@@ -169,7 +170,9 @@ impl SplitTunnelHandle {
169170
vpn_interface: Option<VpnInterface>,
170171
) -> Result<Self, Error> {
171172
let handle = self.redir_handle.take().unwrap();
172-
let (st_utun, pktap_stream, classify, default_interface, _) = handle.stop().await?;
173+
let (st_utun, pktap_stream, classify, _default_interface, _) = handle.stop().await?;
174+
175+
let default_interface = get_default_interface(&self.route_manager).await?;
173176

174177
self.redir_handle = Some(
175178
redirect_packets_for_pktap_stream(
@@ -198,6 +201,42 @@ pub async fn create_split_tunnel(
198201
vpn_interface: Option<VpnInterface>,
199202
classify: impl Fn(&PktapPacket) -> RoutingDecision + Send + 'static,
200203
) -> Result<SplitTunnelHandle, Error> {
204+
let default_interface = get_default_interface(&route_manager).await?;
205+
206+
let mut tun_config = tun::configure();
207+
tun_config.address(ST_IFACE_IPV4).up();
208+
let tun_device =
209+
tun::create_as_async(&tun_config).map_err(Error::CreateSplitTunnelInterface)?;
210+
let tun_name = tun_device.get_ref().name().to_owned();
211+
212+
// Add IPv6 address
213+
// TODO: Only add IPv6 address if there's either a tun or a non-tun IPv6 route
214+
// FIXME: Solve cleanly rather than using subcmd
215+
let output = tokio::process::Command::new("ifconfig")
216+
.args([&tun_name, "inet6", &ST_IFACE_IPV6.to_string(), "alias"])
217+
.output()
218+
.await
219+
.map_err(Error::AddIpv6Address)?;
220+
if !output.status.success() {
221+
return Err(Error::AddIpv6Address(io::Error::new(
222+
io::ErrorKind::Other,
223+
"ifconfig failed",
224+
)));
225+
}
226+
227+
let redir_handle =
228+
redirect_packets(tun_device, default_interface, vpn_interface, classify).await?;
229+
230+
Ok(SplitTunnelHandle {
231+
redir_handle: Some(redir_handle),
232+
tun_name,
233+
route_manager,
234+
})
235+
}
236+
237+
async fn get_default_interface(
238+
route_manager: &RouteManagerHandle,
239+
) -> Result<DefaultInterface, Error> {
201240
let (v4_default, v6_default) = route_manager
202241
.get_default_routes()
203242
.await
@@ -267,39 +306,10 @@ pub async fn create_split_tunnel(
267306
None
268307
};
269308

270-
let default_interface = DefaultInterface {
309+
Ok(DefaultInterface {
271310
name: default_interface,
272311
v4_addrs: default_v4,
273312
v6_addrs: default_v6,
274-
};
275-
276-
let mut tun_config = tun::configure();
277-
tun_config.address(ST_IFACE_IPV4).up();
278-
let tun_device =
279-
tun::create_as_async(&tun_config).map_err(Error::CreateSplitTunnelInterface)?;
280-
let tun_name = tun_device.get_ref().name().to_owned();
281-
282-
// Add IPv6 address
283-
// TODO: Only add IPv6 address if there's either a tun or a non-tun IPv6 route
284-
// FIXME: Solve cleanly rather than using subcmd
285-
let output = tokio::process::Command::new("ifconfig")
286-
.args([&tun_name, "inet6", &ST_IFACE_IPV6.to_string(), "alias"])
287-
.output()
288-
.await
289-
.map_err(Error::AddIpv6Address)?;
290-
if !output.status.success() {
291-
return Err(Error::AddIpv6Address(io::Error::new(
292-
io::ErrorKind::Other,
293-
"ifconfig failed",
294-
)));
295-
}
296-
297-
let redir_handle =
298-
redirect_packets(tun_device, default_interface, vpn_interface, classify).await?;
299-
300-
Ok(SplitTunnelHandle {
301-
redir_handle: Some(redir_handle),
302-
tun_name,
303313
})
304314
}
305315

0 commit comments

Comments
 (0)