Skip to content

Commit 439bd5b

Browse files
committed
Update default interface on VPN interface change
1 parent a645716 commit 439bd5b

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
@@ -148,6 +148,7 @@ pub struct VpnInterface {
148148
pub struct SplitTunnelHandle {
149149
redir_handle: Option<RedirectHandle>,
150150
tun_name: String,
151+
route_manager: RouteManagerHandle,
151152
}
152153

153154
impl SplitTunnelHandle {
@@ -168,7 +169,9 @@ impl SplitTunnelHandle {
168169
vpn_interface: Option<VpnInterface>,
169170
) -> Result<Self, Error> {
170171
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?;
172175

173176
self.redir_handle = Some(
174177
redirect_packets_for_pktap_stream(
@@ -197,6 +200,42 @@ pub async fn create_split_tunnel(
197200
vpn_interface: Option<VpnInterface>,
198201
classify: impl Fn(&PktapPacket) -> RoutingDecision + Send + 'static,
199202
) -> 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> {
200239
let (v4_default, v6_default) = route_manager
201240
.get_default_routes()
202241
.await
@@ -266,39 +305,10 @@ pub async fn create_split_tunnel(
266305
None
267306
};
268307

269-
let default_interface = DefaultInterface {
308+
Ok(DefaultInterface {
270309
name: default_interface,
271310
v4_addrs: default_v4,
272311
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,
302312
})
303313
}
304314

0 commit comments

Comments
 (0)