diff --git a/src/iface/interface/mod.rs b/src/iface/interface/mod.rs index 4a2458ab6..6e0a4cc29 100644 --- a/src/iface/interface/mod.rs +++ b/src/iface/interface/mod.rs @@ -650,6 +650,7 @@ impl Interface { enum EgressError { Exhausted, + MismatchedSrcIp, Dispatch, } @@ -665,6 +666,12 @@ impl Interface { let mut neighbor_addr = None; let mut respond = |inner: &mut InterfaceInner, meta: PacketMeta, response: Packet| { neighbor_addr = Some(response.ip_repr().dst_addr()); + + if !inner.has_ip_addr(response.ip_repr().src_addr()) { + net_debug!("failed to transmit IP: mismatched src addr"); + return Err(EgressError::MismatchedSrcIp); + } + let t = device.transmit(inner.now).ok_or_else(|| { net_debug!("failed to transmit IP: device exhausted"); EgressError::Exhausted @@ -714,13 +721,20 @@ impl Interface { }) } #[cfg(feature = "socket-tcp")] - Socket::Tcp(socket) => socket.dispatch(&mut self.inner, |inner, (ip, tcp)| { + Socket::Tcp(socket) => match socket.dispatch(&mut self.inner, |inner, (ip, tcp)| { respond( inner, PacketMeta::default(), Packet::new(ip, IpPayload::Tcp(tcp)), ) - }), + }) { + Err(EgressError::MismatchedSrcIp) => { + // FIXME: Should this be `close()` or `abort()`? + socket.reset(); + Err(EgressError::MismatchedSrcIp) + } + r => r, + }, #[cfg(feature = "socket-dhcpv4")] Socket::Dhcpv4(socket) => { socket.dispatch(&mut self.inner, |inner, (ip, udp, dhcp)| { @@ -753,6 +767,7 @@ impl Interface { neighbor_addr.expect("non-IP response packet"), ); } + Err(EgressError::MismatchedSrcIp) => {}, Ok(()) => {} } } diff --git a/src/socket/tcp.rs b/src/socket/tcp.rs index 42f99175f..6471d6247 100644 --- a/src/socket/tcp.rs +++ b/src/socket/tcp.rs @@ -825,7 +825,7 @@ impl<'a> Socket<'a> { self.state } - fn reset(&mut self) { + pub fn reset(&mut self) { let rx_cap_log2 = mem::size_of::() * 8 - self.rx_buffer.capacity().leading_zeros() as usize;