fix(shared-tun): restore routed IPv6 replies

Forward route-owned packets unchanged when a member has no address
suitable for source translation. This preserves public IPv6 provider
replies while keeping cross-member source translation when an address
is available.

Keep the shared DNS route backend available in tun-only builds and
use the current error conversion in the FreeBSD IPv4 setup path.
This commit is contained in:
KKRainbow
2026-08-13 02:51:04 +08:00
parent daf30bff6e
commit 86bf3df0fd
3 changed files with 25 additions and 5 deletions
+1 -3
View File
@@ -100,9 +100,7 @@ impl IfConfiguerTrait for MacIfConfiger {
cidr_prefix: u8,
) -> Result<(), Error> {
let addr = Ipv4Inet::new(address, cidr_prefix).map_err(|err| {
Error::RouteError(Some(format!(
"invalid IPv4 address {address}/{cidr_prefix}: {err:?}"
)))
anyhow::anyhow!("invalid IPv4 address {address}/{cidr_prefix}: {err:?}")
})?;
let mut configured_ipv4 = self.configured_ipv4.lock().await;
let has_configured_ipv4 = configured_ipv4
@@ -1251,7 +1251,7 @@ impl SharedVirtualNicDispatcherState {
.source_table
.source_for_member_destination(member_id, key.dst)
else {
return Err(packet);
return self.send_packet_to_member(member_id, packet).await;
};
let original_packet = packet.clone();
let nat_entry = if key.src == translated_src {
@@ -2490,6 +2490,29 @@ mod tests {
assert!(owner_receiver.try_recv().is_ok());
}
#[tokio::test]
async fn dispatcher_forwards_external_ipv6_to_route_only_owner() {
let route_owner = uuid::Uuid::from_u128(1);
let source = "2001:db8:ffff::2".parse::<Ipv6Addr>().unwrap();
let destination = "2001:db8:100::2".parse::<Ipv6Addr>().unwrap();
let (sender, mut receiver) = mpsc::channel(1);
let mut state = SharedVirtualNicDispatcherState::default();
state.register(route_owner, member_entry(sender));
state.source_table.update_member_sources(
route_owner,
member_sources_with_ipv6_routes(&[], &["2001:db8:100::2/128"]),
);
state
.forward_tun_packet_to_member(ipv6_packet(source, destination))
.await;
let packet = receiver.try_recv().unwrap();
let ipv6 = pnet_packet::ipv6::Ipv6Packet::new(packet.payload()).unwrap();
assert_eq!(ipv6.get_source(), source);
assert_eq!(ipv6.get_destination(), destination);
}
#[tokio::test]
async fn dispatcher_drops_inactive_source_owner_without_fallback() {
let fallback = uuid::Uuid::from_u128(1);
-1
View File
@@ -1197,7 +1197,6 @@ impl NicCtx {
)
}
#[cfg(feature = "magic-dns")]
pub(crate) fn shared_route_backend_for_dns(&self) -> Option<NicBackend> {
match self.backend {
NicBackend::Dedicated(_) => None,