stream/tcp: support TCP fast open

pull/4115/head
Victor Julien 7 years ago
parent 8f8581beda
commit bc2267f131

@ -186,6 +186,8 @@ enum
#define STREAMTCP_FLAG_APP_LAYER_DISABLED 0x2000
/** Stream can be bypass */
#define STREAMTCP_FLAG_BYPASS 0x4000
/** SSN uses TCP Fast Open */
#define STREAMTCP_FLAG_TCP_FAST_OPEN 0x8000
/*
* Per STREAM flags

@ -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));

Loading…
Cancel
Save