|
|
|
|
@ -1058,6 +1058,16 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p,
|
|
|
|
|
SCLogDebug("ssn %p: SACK permited on SYN packet", ssn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (TCP_HAS_TFO(p)) {
|
|
|
|
|
ssn->flags |= STREAMTCP_FLAG_TCP_FAST_OPEN;
|
|
|
|
|
if (p->payload_len) {
|
|
|
|
|
StreamTcpUpdateNextSeq(ssn, &ssn->client, (ssn->client.next_seq + p->payload_len));
|
|
|
|
|
SCLogNotice("ssn: %p (TFO) [len: %d] isn %u base_seq %u next_seq %u payload len %u",
|
|
|
|
|
ssn, p->tcpvars.tfo.len, ssn->client.isn, ssn->client.base_seq, ssn->client.next_seq, p->payload_len);
|
|
|
|
|
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p, pq);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SCLogDebug("ssn %p: ssn->client.isn %" PRIu32 ", "
|
|
|
|
|
"ssn->client.next_seq %" PRIu32 ", ssn->client.last_ack "
|
|
|
|
|
"%"PRIu32"", ssn, ssn->client.isn, ssn->client.next_seq,
|
|
|
|
|
@ -1504,16 +1514,31 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p,
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check if the SYN/ACK packet ack's the earlier
|
|
|
|
|
* received SYN packet. */
|
|
|
|
|
if (!(SEQ_EQ(TCP_GET_ACK(p), ssn->client.isn + 1))) {
|
|
|
|
|
StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_WITH_WRONG_ACK);
|
|
|
|
|
SCLogDebug("ssn %p: ACK mismatch, packet ACK %" PRIu32 " != "
|
|
|
|
|
if (!(TCP_HAS_TFO(p) || (ssn->flags & STREAMTCP_FLAG_TCP_FAST_OPEN))) {
|
|
|
|
|
/* Check if the SYN/ACK packet ack's the earlier
|
|
|
|
|
* received SYN packet. */
|
|
|
|
|
if (!(SEQ_EQ(TCP_GET_ACK(p), ssn->client.isn + 1))) {
|
|
|
|
|
StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_WITH_WRONG_ACK);
|
|
|
|
|
SCLogDebug("ssn %p: ACK mismatch, packet ACK %" PRIu32 " != "
|
|
|
|
|
"%" PRIu32 " from stream", ssn, TCP_GET_ACK(p),
|
|
|
|
|
ssn->client.isn + 1);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (!(SEQ_EQ(TCP_GET_ACK(p), ssn->client.next_seq))) {
|
|
|
|
|
StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_WITH_WRONG_ACK);
|
|
|
|
|
SCLogDebug("ssn %p: (TFO) ACK mismatch, packet ACK %" PRIu32 " != "
|
|
|
|
|
"%" PRIu32 " from stream", ssn, TCP_GET_ACK(p),
|
|
|
|
|
ssn->client.next_seq);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
SCLogDebug("ssn %p: (TFO) ACK match, packet ACK %" PRIu32 " == "
|
|
|
|
|
"%" PRIu32 " from stream", ssn, TCP_GET_ACK(p),
|
|
|
|
|
ssn->client.isn + 1);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
ssn->client.next_seq);
|
|
|
|
|
|
|
|
|
|
ssn->flags |= STREAMTCP_FLAG_TCP_FAST_OPEN;
|
|
|
|
|
StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED);
|
|
|
|
|
}
|
|
|
|
|
StreamTcp3whsSynAckUpdate(ssn, p, /* no queue override */NULL);
|
|
|
|
|
|
|
|
|
|
} else if (p->tcph->th_flags & TH_SYN) {
|
|
|
|
|
@ -1857,6 +1882,9 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p,
|
|
|
|
|
SCLogDebug("ssn %p: ACK received on midstream SYN/ACK "
|
|
|
|
|
"pickup session",ssn);
|
|
|
|
|
/* fall through */
|
|
|
|
|
} else if (ssn->flags & STREAMTCP_FLAG_TCP_FAST_OPEN) {
|
|
|
|
|
SCLogDebug("ssn %p: ACK received on TFO session",ssn);
|
|
|
|
|
/* fall through */
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
/* if we missed traffic between the S/SA and the current
|
|
|
|
|
@ -2019,11 +2047,16 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p,
|
|
|
|
|
&ssn->client, p, pq);
|
|
|
|
|
|
|
|
|
|
/* toclient packet: after having missed the 3whs's final ACK */
|
|
|
|
|
} else if (ack_indicates_missed_3whs_ack_packet &&
|
|
|
|
|
} else if ((ack_indicates_missed_3whs_ack_packet ||
|
|
|
|
|
(ssn->flags & STREAMTCP_FLAG_TCP_FAST_OPEN)) &&
|
|
|
|
|
SEQ_EQ(TCP_GET_ACK(p), ssn->client.last_ack) &&
|
|
|
|
|
SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq))
|
|
|
|
|
{
|
|
|
|
|
SCLogDebug("ssn %p: packet fits perfectly after a missed 3whs-ACK", ssn);
|
|
|
|
|
if (ack_indicates_missed_3whs_ack_packet) {
|
|
|
|
|
SCLogDebug("ssn %p: packet fits perfectly after a missed 3whs-ACK", ssn);
|
|
|
|
|
} else {
|
|
|
|
|
SCLogDebug("ssn %p: (TFO) expected packet fits perfectly after SYN/ACK", ssn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
StreamTcpUpdateNextSeq(ssn, &ssn->server, (TCP_GET_SEQ(p) + p->payload_len));
|
|
|
|
|
|
|
|
|
|
|