Skip to content

Commit 17012eb

Browse files
authored
Merge pull request #1069 from KingCol13/tcp-raw-socket-no-reset
Do not send TCP reset when using raw socket which accepts TCP
2 parents e1ed3d6 + 421940b commit 17012eb

File tree

5 files changed

+95
-38
lines changed

5 files changed

+95
-38
lines changed

src/iface/interface/ipv4.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,9 @@ impl InterfaceInner {
234234
}
235235

236236
#[cfg(feature = "socket-tcp")]
237-
IpProtocol::Tcp => self.process_tcp(sockets, ip_repr, ip_payload),
237+
IpProtocol::Tcp => {
238+
self.process_tcp(sockets, handled_by_raw_socket, ip_repr, ip_payload)
239+
}
238240

239241
_ if handled_by_raw_socket => None,
240242

src/iface/interface/ipv6.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,9 @@ impl InterfaceInner {
342342
),
343343

344344
#[cfg(feature = "socket-tcp")]
345-
IpProtocol::Tcp => self.process_tcp(sockets, ipv6_repr.into(), ip_payload),
345+
IpProtocol::Tcp => {
346+
self.process_tcp(sockets, handled_by_raw_socket, ipv6_repr.into(), ip_payload)
347+
}
346348

347349
#[cfg(feature = "socket-raw")]
348350
_ if handled_by_raw_socket => None,

src/iface/interface/tcp.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ impl InterfaceInner {
66
pub(crate) fn process_tcp<'frame>(
77
&mut self,
88
sockets: &mut SocketSet,
9+
handled_by_raw_socket: bool,
910
ip_repr: IpRepr,
1011
ip_payload: &'frame [u8],
1112
) -> Option<Packet<'frame>> {
@@ -32,9 +33,11 @@ impl InterfaceInner {
3233
if tcp_repr.control == TcpControl::Rst
3334
|| ip_repr.dst_addr().is_unspecified()
3435
|| ip_repr.src_addr().is_unspecified()
36+
|| handled_by_raw_socket
3537
{
36-
// Never reply to a TCP RST packet with another TCP RST packet. We also never want to
37-
// send a TCP RST packet with unspecified addresses.
38+
// Never reply to a TCP RST packet with another TCP RST packet.
39+
// Never send a TCP RST packet with unspecified addresses.
40+
// Never send a TCP RST when packet has been handled by raw socket.
3841
None
3942
} else {
4043
// The packet wasn't handled by a socket, send a TCP RST packet.

src/iface/interface/tests/ipv4.rs

Lines changed: 82 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -871,14 +871,9 @@ fn test_packet_len(#[case] medium: Medium) {
871871
}
872872
}
873873

874-
#[rstest]
875-
#[case(Medium::Ip)]
876-
#[cfg(all(feature = "socket-raw", feature = "medium-ip"))]
877-
#[case(Medium::Ethernet)]
878-
#[cfg(all(feature = "socket-raw", feature = "medium-ethernet"))]
879-
fn test_raw_socket_no_reply(#[case] medium: Medium) {
880-
use crate::wire::{IpVersion, UdpPacket, UdpRepr};
881-
874+
/// Check no reply is emitted when using a raw socket
875+
#[cfg(feature = "socket-raw")]
876+
fn check_no_reply_raw_socket(medium: Medium, frame: &crate::wire::ipv4::Packet<&[u8]>) {
882877
let (mut iface, mut sockets, _) = setup(medium);
883878

884879
let packets = 1;
@@ -888,14 +883,30 @@ fn test_raw_socket_no_reply(#[case] medium: Medium) {
888883
vec![raw::PacketMetadata::EMPTY; packets],
889884
vec![0; 48 * packets],
890885
);
891-
let raw_socket = raw::Socket::new(
892-
Some(IpVersion::Ipv4),
893-
Some(IpProtocol::Udp),
894-
rx_buffer,
895-
tx_buffer,
896-
);
886+
let raw_socket = raw::Socket::new(Some(IpVersion::Ipv4), None, rx_buffer, tx_buffer);
897887
sockets.add(raw_socket);
898888

889+
assert_eq!(
890+
iface.inner.process_ipv4(
891+
&mut sockets,
892+
PacketMeta::default(),
893+
HardwareAddress::default(),
894+
frame,
895+
&mut iface.fragments
896+
),
897+
None
898+
);
899+
}
900+
901+
#[rstest]
902+
#[case(Medium::Ip)]
903+
#[cfg(all(feature = "socket-raw", feature = "medium-ip"))]
904+
#[case(Medium::Ethernet)]
905+
#[cfg(all(feature = "socket-raw", feature = "medium-ethernet"))]
906+
/// Test no reply to received UDP when using raw socket which accepts all protocols
907+
fn test_raw_socket_no_reply_udp(#[case] medium: Medium) {
908+
use crate::wire::{UdpPacket, UdpRepr};
909+
899910
let src_addr = Ipv4Address::new(127, 0, 0, 2);
900911
let dst_addr = Ipv4Address::new(127, 0, 0, 1);
901912

@@ -905,16 +916,6 @@ fn test_raw_socket_no_reply(#[case] medium: Medium) {
905916
src_port: 67,
906917
dst_port: 68,
907918
};
908-
let mut bytes = vec![0xff; udp_repr.header_len() + PAYLOAD_LEN];
909-
let mut packet = UdpPacket::new_unchecked(&mut bytes[..]);
910-
udp_repr.emit(
911-
&mut packet,
912-
&src_addr.into(),
913-
&dst_addr.into(),
914-
PAYLOAD_LEN,
915-
|buf| fill_slice(buf, 0x2a),
916-
&ChecksumCapabilities::default(),
917-
);
918919
let ipv4_repr = Ipv4Repr {
919920
src_addr,
920921
dst_addr,
@@ -941,16 +942,63 @@ fn test_raw_socket_no_reply(#[case] medium: Medium) {
941942
Ipv4Packet::new_unchecked(&bytes[..])
942943
};
943944

944-
assert_eq!(
945-
iface.inner.process_ipv4(
946-
&mut sockets,
947-
PacketMeta::default(),
948-
HardwareAddress::default(),
949-
&frame,
950-
&mut iface.fragments
951-
),
952-
None
953-
);
945+
check_no_reply_raw_socket(medium, &frame);
946+
}
947+
948+
#[rstest]
949+
#[case(Medium::Ip)]
950+
#[cfg(all(feature = "socket-raw", feature = "medium-ip"))]
951+
#[case(Medium::Ethernet)]
952+
#[cfg(all(feature = "socket-raw", feature = "medium-ethernet"))]
953+
/// Test no reply to received TCP when using raw socket which accepts all protocols
954+
fn test_raw_socket_no_reply_tcp(#[case] medium: Medium) {
955+
use crate::wire::{TcpPacket, TcpRepr};
956+
957+
let src_addr = Ipv4Address::new(127, 0, 0, 2);
958+
let dst_addr = Ipv4Address::new(127, 0, 0, 1);
959+
960+
const PAYLOAD_LEN: usize = 10;
961+
const PAYLOAD: [u8; PAYLOAD_LEN] = [0x2a; PAYLOAD_LEN];
962+
963+
let tcp_repr = TcpRepr {
964+
src_port: 67,
965+
dst_port: 68,
966+
control: TcpControl::Syn,
967+
seq_number: TcpSeqNumber(1),
968+
ack_number: None,
969+
window_len: 10,
970+
window_scale: None,
971+
max_seg_size: None,
972+
sack_permitted: false,
973+
sack_ranges: [None, None, None],
974+
timestamp: None,
975+
payload: &PAYLOAD,
976+
};
977+
let ipv4_repr = Ipv4Repr {
978+
src_addr,
979+
dst_addr,
980+
next_header: IpProtocol::Tcp,
981+
hop_limit: 64,
982+
payload_len: tcp_repr.header_len() + PAYLOAD_LEN,
983+
};
984+
985+
// Emit to frame
986+
let mut bytes = vec![0u8; ipv4_repr.buffer_len() + tcp_repr.header_len() + PAYLOAD_LEN];
987+
let frame = {
988+
ipv4_repr.emit(
989+
&mut Ipv4Packet::new_unchecked(&mut bytes),
990+
&ChecksumCapabilities::default(),
991+
);
992+
tcp_repr.emit(
993+
&mut TcpPacket::new_unchecked(&mut bytes[ipv4_repr.buffer_len()..]),
994+
&src_addr.into(),
995+
&dst_addr.into(),
996+
&ChecksumCapabilities::default(),
997+
);
998+
Ipv4Packet::new_unchecked(&bytes[..])
999+
};
1000+
1001+
check_no_reply_raw_socket(medium, &frame);
9541002
}
9551003

9561004
#[rstest]

src/iface/interface/tests/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ pub fn tcp_not_accepted() {
187187
assert_eq!(
188188
iface.inner.process_tcp(
189189
&mut sockets,
190+
false,
190191
IpRepr::Ipv6(Ipv6Repr {
191192
src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2),
192193
dst_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
@@ -231,6 +232,7 @@ pub fn tcp_not_accepted() {
231232
assert_eq!(
232233
iface.inner.process_tcp(
233234
&mut sockets,
235+
false,
234236
IpRepr::Ipv6(Ipv6Repr {
235237
src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2),
236238
dst_addr: Ipv6Address::UNSPECIFIED,

0 commit comments

Comments
 (0)