Skip to content

Commit

Permalink
issue: 2246994 Set proper FIN/RST flags for split segments
Browse files Browse the repository at this point in the history
When a segment with FIN flag is split into multiple segments, the
leftmost segment retains all its flags including FIN. This leads to
corrupted TCP stream.

To fix this, move FIN/RST flags to the rightmost among the split
segments. Currently, VMA doesn't support RST flag in the pending
segments, however, it may be changed in the future.

Signed-off-by: Dmytro Podgornyi <[email protected]>
  • Loading branch information
pasis authored and igor-ivanov committed Mar 10, 2021
1 parent da44080 commit b8a3a9e
Showing 1 changed file with 16 additions and 0 deletions.
16 changes: 16 additions & 0 deletions src/vma/lwip/tcp_out.c
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,17 @@ tcp_send_empty_ack(struct tcp_pcb *pcb)
return ERR_OK;
}

/* Used by split functions to move FIN/RST flags to the rightmost segment. */
static void tcp_seg_move_flags(struct tcp_seg *from, struct tcp_seg *to, u8_t flags)
{
u16_t from_flags = TCPH_FLAGS(from->tcphdr) & flags;

if ((from != to) && (to != NULL) && from_flags) {
TCPH_SET_FLAG(to->tcphdr, from_flags);
TCPH_UNSET_FLAG(from->tcphdr, flags);
}
}

#if LWIP_TSO
/**
* Called by tcp_output() to actually join few following TCP segments
Expand Down Expand Up @@ -1130,6 +1141,7 @@ tcp_split_one_segment(struct tcp_pcb *pcb, struct tcp_seg *seg, u32_t lentosend,
pcb->unsent_oversize = result ? oversize : 0;
#endif /* TCP_OVERSIZE */
}
tcp_seg_move_flags(seg, cur_seg, TCP_FIN | TCP_RST);
return result;
}

Expand Down Expand Up @@ -1229,6 +1241,8 @@ tcp_rexmit_segment(struct tcp_pcb *pcb, struct tcp_seg *seg, u32_t wnd)
#endif /* TCP_OVERSIZE */
}

tcp_seg_move_flags(cur_seg, new_seg, TCP_FIN | TCP_RST);

if (NULL == tcp_split_one_segment(pcb, cur_seg, mss_local, optflags, optlen)) {
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_split_one_segment: could not allocate memory for segment\n"));
if (new_seg->len > pcb->mss) {
Expand Down Expand Up @@ -1400,6 +1414,8 @@ tcp_split_segment(struct tcp_pcb *pcb, struct tcp_seg *seg, u32_t wnd)
LWIP_ASSERT("tcp_split_segment: We should not be here [else]",0);
}

tcp_seg_move_flags(seg, newseg, TCP_FIN | TCP_RST);

#if TCP_TSO_DEBUG
LWIP_DEBUGF(TCP_TSO_DEBUG | LWIP_DBG_TRACE,
("tcp_split: max: %-5d unsent %s\n",
Expand Down

0 comments on commit b8a3a9e

Please sign in to comment.