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,
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) {
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
&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));