Disregard TCP FIN flag if it arrives in a segment not at window start.
Fixes #111.
This commit is contained in:
parent
b653a6e421
commit
f494200c8c
|
@ -887,6 +887,11 @@ impl<'a> TcpSocket<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
let window_start = self.remote_seq_no + self.rx_buffer.len();
|
||||
let window_end = self.remote_seq_no + self.rx_buffer.capacity();
|
||||
let segment_start = repr.seq_number;
|
||||
let segment_end = repr.seq_number + repr.segment_len();
|
||||
|
||||
let payload_offset;
|
||||
match self.state {
|
||||
// In LISTEN and SYN-SENT states, we have not yet synchronized with the remote end.
|
||||
|
@ -896,11 +901,6 @@ impl<'a> TcpSocket<'a> {
|
|||
_ => {
|
||||
let mut segment_in_window = true;
|
||||
|
||||
let window_start = self.remote_seq_no + self.rx_buffer.len();
|
||||
let window_end = self.remote_seq_no + self.rx_buffer.capacity();
|
||||
let segment_start = repr.seq_number;
|
||||
let segment_end = repr.seq_number + repr.segment_len();
|
||||
|
||||
if window_start == window_end && segment_start != segment_end {
|
||||
net_debug!("{}:{}:{}: non-zero-length segment with zero receive window, \
|
||||
will only send an ACK",
|
||||
|
@ -960,8 +960,18 @@ impl<'a> TcpSocket<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
// Disregard control flags we don't care about or shouldn't act on yet.
|
||||
let mut control = repr.control;
|
||||
control = control.quash_psh();
|
||||
|
||||
// If a FIN is received at the end of the current segment but the start of the segment
|
||||
// is not at the start of the receive window, disregard this FIN.
|
||||
if control == TcpControl::Fin && window_start != segment_start {
|
||||
control = TcpControl::None;
|
||||
}
|
||||
|
||||
// Validate and update the state.
|
||||
match (self.state, repr.control.quash_psh()) {
|
||||
match (self.state, control) {
|
||||
// RSTs are not accepted in the LISTEN state.
|
||||
(State::Listen, TcpControl::Rst) =>
|
||||
return Err(Error::Dropped),
|
||||
|
@ -2289,6 +2299,35 @@ mod test {
|
|||
sanity!(s, socket_close_wait());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_established_fin_after_missing() {
|
||||
let mut s = socket_established();
|
||||
send!(s, TcpRepr {
|
||||
control: TcpControl::Fin,
|
||||
seq_number: REMOTE_SEQ + 1 + 6,
|
||||
ack_number: Some(LOCAL_SEQ + 1),
|
||||
payload: &b"123456"[..],
|
||||
..SEND_TEMPL
|
||||
}, Ok(Some(TcpRepr {
|
||||
seq_number: LOCAL_SEQ + 1,
|
||||
ack_number: Some(REMOTE_SEQ + 1),
|
||||
..RECV_TEMPL
|
||||
})));
|
||||
assert_eq!(s.state, State::Established);
|
||||
send!(s, TcpRepr {
|
||||
seq_number: REMOTE_SEQ + 1,
|
||||
ack_number: Some(LOCAL_SEQ + 1),
|
||||
payload: &b"abcdef"[..],
|
||||
..SEND_TEMPL
|
||||
}, Ok(Some(TcpRepr {
|
||||
seq_number: LOCAL_SEQ + 1,
|
||||
ack_number: Some(REMOTE_SEQ + 1 + 6 + 6),
|
||||
window_len: 52,
|
||||
..RECV_TEMPL
|
||||
})));
|
||||
assert_eq!(s.state, State::Established);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_established_send_fin() {
|
||||
let mut s = socket_established();
|
||||
|
|
Loading…
Reference in New Issue