Reject, not accept, TCP RST packets in LISTEN state.

These packets may have been destined for a different socket.
This commit is contained in:
whitequark 2017-01-17 04:33:37 +00:00
parent ac38ddd936
commit 591993014e
2 changed files with 21 additions and 20 deletions

View File

@ -228,24 +228,25 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
if !handled && protocol == IpProtocol::Tcp {
let tcp_packet = try!(TcpPacket::new(ipv4_packet.payload()));
let tcp_reply_repr = TcpRepr {
src_port: tcp_packet.dst_port(),
dst_port: tcp_packet.src_port(),
control: TcpControl::Rst,
seq_number: tcp_packet.ack_number(),
ack_number: Some(tcp_packet.seq_number() +
tcp_packet.segment_len()),
window_len: 0,
payload: &[]
};
let ipv4_reply_repr = Ipv4Repr {
src_addr: dst_addr,
dst_addr: src_addr,
protocol: IpProtocol::Tcp,
payload_len: tcp_reply_repr.buffer_len()
};
response = Response::Tcpv4(ipv4_reply_repr, tcp_reply_repr);
if !tcp_packet.rst() {
let tcp_reply_repr = TcpRepr {
src_port: tcp_packet.dst_port(),
dst_port: tcp_packet.src_port(),
control: TcpControl::Rst,
seq_number: tcp_packet.ack_number(),
ack_number: Some(tcp_packet.seq_number() +
tcp_packet.segment_len()),
window_len: 0,
payload: &[]
};
let ipv4_reply_repr = Ipv4Repr {
src_addr: dst_addr,
dst_addr: src_addr,
protocol: IpProtocol::Tcp,
payload_len: tcp_reply_repr.buffer_len()
};
response = Response::Tcpv4(ipv4_reply_repr, tcp_reply_repr);
}
} else if !handled {
let reason;
if protocol == IpProtocol::Udp {

View File

@ -657,7 +657,7 @@ impl<'a> TcpSocket<'a> {
match (self.state, repr) {
// RSTs are ignored in the LISTEN state.
(State::Listen, TcpRepr { control: TcpControl::Rst, .. }) =>
return Ok(()),
return Err(Error::Rejected),
// RSTs in SYN-RECEIVED flip the socket back to the LISTEN state.
(State::SynReceived, TcpRepr { control: TcpControl::Rst, .. }) => {
@ -1224,7 +1224,7 @@ mod test {
seq_number: REMOTE_SEQ,
ack_number: None,
..SEND_TEMPL
});
}, Err(Error::Rejected));
}
#[test]