stream: handle zero window probe acks

These can be skipped for the most part.
pull/8638/head
Victor Julien 2 years ago
parent 7bc16af939
commit d9008614a2

@ -357,6 +357,8 @@ static int EveStreamLogger(ThreadVars *tv, void *thread_data, const Packet *p)
jb_append_string(js, "tcp_port_reuse");
if (p->tcpvars.stream_pkt_flags & STREAM_PKT_FLAG_TCP_ZERO_WIN_PROBE)
jb_append_string(js, "zero_window_probe");
if (p->tcpvars.stream_pkt_flags & STREAM_PKT_FLAG_TCP_ZERO_WIN_PROBE_ACK)
jb_append_string(js, "zero_window_probe_ack");
jb_close(js);
}
jb_close(js);

@ -318,6 +318,7 @@ typedef struct TcpSession_ {
#define STREAM_PKT_FLAG_ACK_UNSEEN_DATA BIT_U16(9)
#define STREAM_PKT_FLAG_TCP_PORT_REUSE BIT_U16(10)
#define STREAM_PKT_FLAG_TCP_ZERO_WIN_PROBE BIT_U16(11)
#define STREAM_PKT_FLAG_TCP_ZERO_WIN_PROBE_ACK BIT_U16(12)
#define STREAM_PKT_FLAG_SET(p, f) (p)->tcpvars.stream_pkt_flags |= (f)

@ -2851,6 +2851,42 @@ static inline uint32_t StreamTcpResetGetMaxAck(TcpStream *stream, uint32_t seq)
SCReturnUInt(ack);
}
static bool StreamTcpPacketIsZeroWindowProbeAck(const TcpSession *ssn, const Packet *p)
{
if (ssn->state < TCP_ESTABLISHED)
return false;
if (p->payload_len != 0)
return false;
if ((p->tcph->th_flags & (TH_ACK | TH_SYN | TH_FIN | TH_RST)) != TH_ACK)
return false;
const TcpStream *snd, *rcv;
if (PKT_IS_TOCLIENT(p)) {
snd = &ssn->server;
rcv = &ssn->client;
if (!(ssn->flags & STREAMTCP_FLAG_ZWP_TS))
return false;
} else {
snd = &ssn->client;
rcv = &ssn->server;
if (!(ssn->flags & STREAMTCP_FLAG_ZWP_TC))
return false;
}
const uint32_t pkt_win = TCP_GET_WINDOW(p) << snd->wscale;
if (pkt_win != 0)
return false;
if (pkt_win != rcv->window)
return false;
if (TCP_GET_SEQ(p) != snd->next_seq)
return false;
if (TCP_GET_ACK(p) != rcv->last_ack)
return false;
SCLogDebug("ssn %p: packet %" PRIu64 " is a Zero Window Probe ACK", ssn, p->pcap_cnt);
return true;
}
/** \internal
* \brief check if an ACK packet is a dup-ACK
*/
@ -5364,6 +5400,17 @@ int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt,
}
StreamTcpClearKeepAliveFlag(ssn, p);
const bool is_zwp_ack = StreamTcpPacketIsZeroWindowProbeAck(ssn, p);
if (PKT_IS_TOCLIENT(p)) {
ssn->flags &= ~STREAMTCP_FLAG_ZWP_TS;
} else {
ssn->flags &= ~STREAMTCP_FLAG_ZWP_TC;
}
if (is_zwp_ack) {
STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_TCP_ZERO_WIN_PROBE_ACK);
goto skip;
}
if (StreamTcpPacketIsDupAck(ssn, p) == true) {
STREAM_PKT_FLAG_SET(p, STREAM_PKT_FLAG_DUP_ACK);
// TODO see if we can skip work on these

Loading…
Cancel
Save