diff --git a/src/iface/interface/ipv4.rs b/src/iface/interface/ipv4.rs index 7fda3ae3b..d6d6b3c38 100644 --- a/src/iface/interface/ipv4.rs +++ b/src/iface/interface/ipv4.rs @@ -227,7 +227,9 @@ impl InterfaceInner { } #[cfg(feature = "socket-tcp")] - IpProtocol::Tcp => self.process_tcp(sockets, ip_repr, ip_payload), + IpProtocol::Tcp => { + self.process_tcp(sockets, handled_by_raw_socket, ip_repr, ip_payload) + } _ if handled_by_raw_socket => None, diff --git a/src/iface/interface/ipv6.rs b/src/iface/interface/ipv6.rs index ca8c2ef35..bb78cacf5 100644 --- a/src/iface/interface/ipv6.rs +++ b/src/iface/interface/ipv6.rs @@ -342,7 +342,9 @@ impl InterfaceInner { ), #[cfg(feature = "socket-tcp")] - IpProtocol::Tcp => self.process_tcp(sockets, ipv6_repr.into(), ip_payload), + IpProtocol::Tcp => { + self.process_tcp(sockets, handled_by_raw_socket, ipv6_repr.into(), ip_payload) + } #[cfg(feature = "socket-raw")] _ if handled_by_raw_socket => None, diff --git a/src/iface/interface/tcp.rs b/src/iface/interface/tcp.rs index 85fe0702a..140bdcda1 100644 --- a/src/iface/interface/tcp.rs +++ b/src/iface/interface/tcp.rs @@ -6,6 +6,7 @@ impl InterfaceInner { pub(crate) fn process_tcp<'frame>( &mut self, sockets: &mut SocketSet, + handled_by_raw_socket: bool, ip_repr: IpRepr, ip_payload: &'frame [u8], ) -> Option> { @@ -32,9 +33,11 @@ impl InterfaceInner { if tcp_repr.control == TcpControl::Rst || ip_repr.dst_addr().is_unspecified() || ip_repr.src_addr().is_unspecified() + || handled_by_raw_socket { - // Never reply to a TCP RST packet with another TCP RST packet. We also never want to - // send a TCP RST packet with unspecified addresses. + // Never reply to a TCP RST packet with another TCP RST packet. + // Never send a TCP RST packet with unspecified addresses. + // Never send a TCP RST when packet has been handled by raw socket. None } else { // The packet wasn't handled by a socket, send a TCP RST packet. diff --git a/src/iface/interface/tests/ipv4.rs b/src/iface/interface/tests/ipv4.rs index 37685a7ba..f6d3e04b1 100644 --- a/src/iface/interface/tests/ipv4.rs +++ b/src/iface/interface/tests/ipv4.rs @@ -835,14 +835,9 @@ fn test_packet_len(#[case] medium: Medium) { } } -#[rstest] -#[case(Medium::Ip)] -#[cfg(all(feature = "socket-raw", feature = "medium-ip"))] -#[case(Medium::Ethernet)] -#[cfg(all(feature = "socket-raw", feature = "medium-ethernet"))] -fn test_raw_socket_no_reply(#[case] medium: Medium) { - use crate::wire::{IpVersion, UdpPacket, UdpRepr}; - +/// Check no reply is emitted when using a raw socket +#[cfg(feature = "socket-raw")] +fn check_no_reply_raw_socket(medium: Medium, frame: &crate::wire::ipv4::Packet<&[u8]>) { let (mut iface, mut sockets, _) = setup(medium); let packets = 1; @@ -852,14 +847,30 @@ fn test_raw_socket_no_reply(#[case] medium: Medium) { vec![raw::PacketMetadata::EMPTY; packets], vec![0; 48 * packets], ); - let raw_socket = raw::Socket::new( - Some(IpVersion::Ipv4), - Some(IpProtocol::Udp), - rx_buffer, - tx_buffer, - ); + let raw_socket = raw::Socket::new(Some(IpVersion::Ipv4), None, rx_buffer, tx_buffer); sockets.add(raw_socket); + assert_eq!( + iface.inner.process_ipv4( + &mut sockets, + PacketMeta::default(), + HardwareAddress::default(), + frame, + &mut iface.fragments + ), + None + ); +} + +#[rstest] +#[case(Medium::Ip)] +#[cfg(all(feature = "socket-raw", feature = "medium-ip"))] +#[case(Medium::Ethernet)] +#[cfg(all(feature = "socket-raw", feature = "medium-ethernet"))] +/// Test no reply to received UDP when using raw socket which accepts all protocols +fn test_raw_socket_no_reply_udp(#[case] medium: Medium) { + use crate::wire::{UdpPacket, UdpRepr}; + let src_addr = Ipv4Address::new(127, 0, 0, 2); let dst_addr = Ipv4Address::new(127, 0, 0, 1); @@ -869,16 +880,6 @@ fn test_raw_socket_no_reply(#[case] medium: Medium) { src_port: 67, dst_port: 68, }; - let mut bytes = vec![0xff; udp_repr.header_len() + PAYLOAD_LEN]; - let mut packet = UdpPacket::new_unchecked(&mut bytes[..]); - udp_repr.emit( - &mut packet, - &src_addr.into(), - &dst_addr.into(), - PAYLOAD_LEN, - |buf| fill_slice(buf, 0x2a), - &ChecksumCapabilities::default(), - ); let ipv4_repr = Ipv4Repr { src_addr, dst_addr, @@ -905,16 +906,63 @@ fn test_raw_socket_no_reply(#[case] medium: Medium) { Ipv4Packet::new_unchecked(&bytes[..]) }; - assert_eq!( - iface.inner.process_ipv4( - &mut sockets, - PacketMeta::default(), - HardwareAddress::default(), - &frame, - &mut iface.fragments - ), - None - ); + check_no_reply_raw_socket(medium, &frame); +} + +#[rstest] +#[case(Medium::Ip)] +#[cfg(all(feature = "socket-raw", feature = "medium-ip"))] +#[case(Medium::Ethernet)] +#[cfg(all(feature = "socket-raw", feature = "medium-ethernet"))] +/// Test no reply to received TCP when using raw socket which accepts all protocols +fn test_raw_socket_no_reply_tcp(#[case] medium: Medium) { + use crate::wire::{TcpPacket, TcpRepr}; + + let src_addr = Ipv4Address::new(127, 0, 0, 2); + let dst_addr = Ipv4Address::new(127, 0, 0, 1); + + const PAYLOAD_LEN: usize = 10; + const PAYLOAD: [u8; PAYLOAD_LEN] = [0x2a; PAYLOAD_LEN]; + + let tcp_repr = TcpRepr { + src_port: 67, + dst_port: 68, + control: TcpControl::Syn, + seq_number: TcpSeqNumber(1), + ack_number: None, + window_len: 10, + window_scale: None, + max_seg_size: None, + sack_permitted: false, + sack_ranges: [None, None, None], + timestamp: None, + payload: &PAYLOAD, + }; + let ipv4_repr = Ipv4Repr { + src_addr, + dst_addr, + next_header: IpProtocol::Tcp, + hop_limit: 64, + payload_len: tcp_repr.header_len() + PAYLOAD_LEN, + }; + + // Emit to frame + let mut bytes = vec![0u8; ipv4_repr.buffer_len() + tcp_repr.header_len() + PAYLOAD_LEN]; + let frame = { + ipv4_repr.emit( + &mut Ipv4Packet::new_unchecked(&mut bytes), + &ChecksumCapabilities::default(), + ); + tcp_repr.emit( + &mut TcpPacket::new_unchecked(&mut bytes[ipv4_repr.buffer_len()..]), + &src_addr.into(), + &dst_addr.into(), + &ChecksumCapabilities::default(), + ); + Ipv4Packet::new_unchecked(&bytes[..]) + }; + + check_no_reply_raw_socket(medium, &frame); } #[rstest] diff --git a/src/iface/interface/tests/mod.rs b/src/iface/interface/tests/mod.rs index 1d70f88c2..907b22bbd 100644 --- a/src/iface/interface/tests/mod.rs +++ b/src/iface/interface/tests/mod.rs @@ -187,6 +187,7 @@ pub fn tcp_not_accepted() { assert_eq!( iface.inner.process_tcp( &mut sockets, + false, IpRepr::Ipv6(Ipv6Repr { src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2), dst_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), @@ -231,6 +232,7 @@ pub fn tcp_not_accepted() { assert_eq!( iface.inner.process_tcp( &mut sockets, + false, IpRepr::Ipv6(Ipv6Repr { src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2), dst_addr: Ipv6Address::UNSPECIFIED,