85 #define STREAMTCP_DEFAULT_PREALLOC 2048
86 #define STREAMTCP_DEFAULT_MEMCAP (64 * 1024 * 1024)
87 #define STREAMTCP_DEFAULT_REASSEMBLY_MEMCAP (256 * 1024 * 1024)
88 #define STREAMTCP_DEFAULT_TOSERVER_CHUNK_SIZE 2560
89 #define STREAMTCP_DEFAULT_TOCLIENT_CHUNK_SIZE 2560
90 #define STREAMTCP_DEFAULT_MAX_SYN_QUEUED 10
91 #define STREAMTCP_DEFAULT_MAX_SYNACK_QUEUED 5
106 .valid_settings_ips = {
132 .valid_settings_ips = {
158 .valid_settings_ips = {
184 .valid_settings_ips = {
207 static int StreamTcpStateDispatch(
216 static uint64_t ssn_pool_cnt = 0;
236 #if defined(DEBUG_VALIDATION) && defined(UNITTESTS)
239 BUG_ON(presize > UINT_MAX);
245 #if defined(DEBUG_VALIDATION) && defined(UNITTESTS)
248 BUG_ON(postsize > presize);
269 if (memcapcopy == 0 || size +
SC_ATOMIC_GET(st_memuse) <= memcapcopy)
281 if (size == 0 || (uint64_t)
SC_ATOMIC_GET(st_memuse) < size) {
302 if (stream != NULL) {
309 static void StreamTcp3wsFreeQueue(
TcpSession *ssn)
336 StreamTcp3wsFreeQueue(ssn);
397 static void *StreamTcpSessionPoolAlloc(
void)
411 static int StreamTcpSessionPoolInit(
void *data,
void* initdata)
421 static void StreamTcpSessionPoolCleanup(
void *s)
435 static inline bool StreamTcpInlineDropInvalid(
void)
444 static int RandomGetWrap(
void)
450 }
while(r >= ULONG_MAX - (ULONG_MAX % RAND_MAX));
464 uint16_t rdrange = 10;
473 if ((
ConfGetInt(
"stream.max-sessions", &value)) == 1) {
475 "Number of concurrent sessions is now only limited by Flow and "
476 "TCP stream engine memcaps.");
479 if ((
ConfGetInt(
"stream.prealloc-sessions", &value)) == 1) {
486 if (
ConfGetNode(
"stream.prealloc-sessions") != NULL) {
494 SCLogConfig(
"stream \"prealloc-sessions\": %"PRIu32
" (per thread)",
498 const char *temp_stream_memcap_str;
499 if (
ConfGet(
"stream.memcap", &temp_stream_memcap_str) == 1) {
500 uint64_t stream_memcap_copy;
503 "from conf file - %s. Killing engine",
504 temp_stream_memcap_str);
518 (void)
ConfGetBool(
"stream.midstream", &imidstream);
526 (void)
ConfGetBool(
"stream.async-oneside", &async_oneside);
535 if ((
ConfGetBool(
"stream.checksum-validation", &csum)) == 1) {
547 "enabled" :
"disabled");
550 const char *temp_stream_inline_str;
551 if (
ConfGet(
"stream.inline", &temp_stream_inline_str) == 1) {
556 if (strcmp(temp_stream_inline_str,
"auto") == 0) {
560 }
else if (
ConfGetBool(
"stream.inline", &inl) == 1) {
579 ?
"enabled" :
"disabled");
583 if ((
ConfGetBool(
"stream.bypass", &bypass)) == 1) {
592 ?
"enabled" :
"disabled");
595 int drop_invalid = 0;
596 if ((
ConfGetBool(
"stream.drop-invalid", &drop_invalid)) == 1) {
597 if (drop_invalid == 1) {
604 if ((
ConfGetInt(
"stream.max-syn-queued", &value)) == 1) {
605 if (value >= 0 && value <= 255) {
617 if ((
ConfGetInt(
"stream.max-synack-queued", &value)) == 1) {
618 if (value >= 0 && value <= 255) {
630 const char *temp_stream_reassembly_memcap_str;
631 if (
ConfGet(
"stream.reassembly.memcap", &temp_stream_reassembly_memcap_str) == 1) {
632 uint64_t stream_reassembly_memcap_copy;
634 &stream_reassembly_memcap_copy) < 0) {
636 "stream.reassembly.memcap "
637 "from conf file - %s. Killing engine",
638 temp_stream_reassembly_memcap_str);
648 SCLogConfig(
"stream.reassembly \"memcap\": %"PRIu64
"",
652 const char *temp_stream_reassembly_depth_str;
653 if (
ConfGet(
"stream.reassembly.depth", &temp_stream_reassembly_depth_str) == 1) {
657 "stream.reassembly.depth "
658 "from conf file - %s. Killing engine",
659 temp_stream_reassembly_depth_str);
671 if ((
ConfGetBool(
"stream.reassembly.randomize-chunk-size", &randomize)) == 0) {
679 const char *temp_rdrange;
680 if (
ConfGet(
"stream.reassembly.randomize-chunk-range", &temp_rdrange) == 1) {
683 "stream.reassembly.randomize-chunk-range "
684 "from conf file - %s. Killing engine",
687 }
else if (rdrange >= 100) {
688 FatalError(
"stream.reassembly.randomize-chunk-range "
689 "must be lower than 100");
694 const char *temp_stream_reassembly_toserver_chunk_size_str;
695 if (
ConfGet(
"stream.reassembly.toserver-chunk-size",
696 &temp_stream_reassembly_toserver_chunk_size_str) == 1) {
700 "stream.reassembly.toserver-chunk-size "
701 "from conf file - %s. Killing engine",
702 temp_stream_reassembly_toserver_chunk_size_str);
711 long int r = RandomGetWrap();
716 const char *temp_stream_reassembly_toclient_chunk_size_str;
717 if (
ConfGet(
"stream.reassembly.toclient-chunk-size",
718 &temp_stream_reassembly_toclient_chunk_size_str) == 1) {
722 "stream.reassembly.toclient-chunk-size "
723 "from conf file - %s. Killing engine",
724 temp_stream_reassembly_toclient_chunk_size_str);
733 long int r = RandomGetWrap();
739 SCLogConfig(
"stream.reassembly \"toserver-chunk-size\": %"PRIu16,
741 SCLogConfig(
"stream.reassembly \"toclient-chunk-size\": %"PRIu16,
746 if (
ConfGetBool(
"stream.reassembly.raw", &enable_raw) == 1) {
754 SCLogConfig(
"stream.reassembly.raw: %s", enable_raw ?
"enabled" :
"disabled");
758 int liberal_timestamps = 0;
759 if (
ConfGetBool(
"stream.liberal-timestamps", &liberal_timestamps) == 1) {
763 SCLogConfig(
"stream.liberal-timestamps: %s", liberal_timestamps ?
"enabled" :
"disabled");
783 StreamTcpSessionPoolAlloc,
784 StreamTcpSessionPoolInit, NULL,
785 StreamTcpSessionPoolCleanup, NULL);
804 SCLogDebug(
"ssn_pool_cnt %"PRIu64
"", ssn_pool_cnt);
807 static bool IsReassemblyMemcapExceptionPolicyStatsValid(
enum ExceptionPolicy exception_policy)
815 static bool IsStreamTcpSessionMemcapExceptionPolicyStatsValid(
enum ExceptionPolicy policy)
823 static void StreamTcpSsnMemcapExceptionPolicyStatsIncr(
867 if (
unlikely((g_eps_stream_ssn_memcap != UINT64_MAX &&
868 g_eps_stream_ssn_memcap ==
t_pcapcnt))) {
883 const TCPHdr *tcph = PacketGetTCP(p);
942 if (PacketIsIPv4(p)) {
952 }
else if (PacketIsIPv6(p)) {
978 #define StreamTcpUpdateLastAck(ssn, stream, ack) { \
979 if (SEQ_GT((ack), (stream)->last_ack)) \
981 SCLogDebug("ssn %p: last_ack set to %"PRIu32", moved %u forward", (ssn), (ack), (ack) - (stream)->last_ack); \
982 if ((SEQ_LEQ((stream)->last_ack, (stream)->next_seq) && SEQ_GT((ack),(stream)->next_seq))) { \
983 SCLogDebug("last_ack just passed next_seq: %u (was %u) > %u", (ack), (stream)->last_ack, (stream)->next_seq); \
985 SCLogDebug("next_seq (%u) <> last_ack now %d", (stream)->next_seq, (int)(stream)->next_seq - (ack)); \
987 (stream)->last_ack = (ack); \
988 StreamTcpSackPruneList((stream)); \
990 SCLogDebug("ssn %p: no update: ack %u, last_ack %"PRIu32", next_seq %u (state %u)", \
991 (ssn), (ack), (stream)->last_ack, (stream)->next_seq, (ssn)->state); \
995 #define StreamTcpAsyncLastAckUpdate(ssn, stream) { \
996 if ((ssn)->flags & STREAMTCP_FLAG_ASYNC) { \
997 if (SEQ_GT((stream)->next_seq, (stream)->last_ack)) { \
998 uint32_t ack_diff = (stream)->next_seq - (stream)->last_ack; \
999 (stream)->last_ack += ack_diff; \
1000 SCLogDebug("ssn %p: ASYNC last_ack set to %"PRIu32", moved %u forward", \
1001 (ssn), (stream)->next_seq, ack_diff); \
1006 #define StreamTcpUpdateNextSeq(ssn, stream, seq) { \
1007 (stream)->next_seq = seq; \
1008 SCLogDebug("ssn %p: next_seq %" PRIu32, (ssn), (stream)->next_seq); \
1009 StreamTcpAsyncLastAckUpdate((ssn), (stream)); \
1019 #define StreamTcpUpdateNextWin(ssn, stream, win) { \
1020 uint32_t sacked_size__ = StreamTcpSackedSize((stream)); \
1021 if (SEQ_GT(((win) + sacked_size__), (stream)->next_win)) { \
1022 (stream)->next_win = ((win) + sacked_size__); \
1023 SCLogDebug("ssn %p: next_win set to %"PRIu32, (ssn), (stream)->next_win); \
1031 SCLogDebug(
"ssn %p: (state: %s) Reset received and state changed to "
1035 static bool IsMidstreamExceptionPolicyStatsValid(
enum ExceptionPolicy policy)
1049 static void StreamTcpMidstreamExceptionPolicyStatsIncr(
1058 static int StreamTcpPacketIsRetransmission(
TcpStream *stream,
Packet *p)
1063 const TCPHdr *tcph = PacketGetTCP(p);
1101 static int StreamTcpPacketStateNone(
1104 const TCPHdr *tcph = PacketGetTCP(p);
1107 SCLogDebug(
"RST packet received, no session setup");
1117 SCLogDebug(
"FIN packet received, no session setup");
1123 SCLogDebug(
"FIN packet received, no session setup");
1140 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1172 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
", "
1173 "ssn->server.next_win %" PRIu32
"",
1175 SCLogDebug(
"ssn %p: ssn->client.last_ack %" PRIu32
", "
1176 "ssn->server.last_ack %" PRIu32
"",
1184 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1185 "ssn->client.last_ts %" PRIu32
"",
1204 SCLogDebug(
"ssn %p: assuming SACK permitted for both sides", ssn);
1213 SCLogDebug(
"Midstream not enabled, so won't pick up a session");
1218 SCLogDebug(
"Midstream policy not permissive, so won't pick up a session");
1241 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1242 "TCP_SYN_RECV", ssn);
1273 SCLogDebug(
"ssn %p: wscale enabled. client %u server %u",
1277 SCLogDebug(
"ssn %p: ssn->client.isn %"PRIu32
", ssn->client.next_seq"
1278 " %"PRIu32
", ssn->client.last_ack %"PRIu32
"", ssn,
1281 SCLogDebug(
"ssn %p: ssn->server.isn %"PRIu32
", ssn->server.next_seq"
1282 " %"PRIu32
", ssn->server.last_ack %"PRIu32
"", ssn,
1291 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1292 "ssn->client.last_ts %" PRIu32
"", ssn,
1310 SCLogDebug(
"ssn %p: SYN/ACK with SACK permitted, assuming "
1311 "SACK permitted for both sides", ssn);
1329 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_SYN_SENT", ssn);
1362 SCLogDebug(
"ssn %p: SACK permitted on SYN packet", ssn);
1369 SCLogDebug(
"ssn: %p (TFO) isn %u base_seq %u next_seq %u payload len %u", ssn,
1376 SCLogDebug(
"ssn %p: ssn->client.isn %" PRIu32
", "
1377 "ssn->client.next_seq %" PRIu32
", ssn->client.last_ack "
1387 SCLogDebug(
"Midstream not enabled, so won't pick up a session");
1392 SCLogDebug(
"Midstream policy not permissive, so won't pick up a session");
1409 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1410 "TCP_ESTABLISHED", ssn);
1431 SCLogDebug(
"ssn %p: ssn->client.isn %u, ssn->client.next_seq %u",
1440 SCLogDebug(
"ssn %p: ssn->client.next_win %"PRIu32
", "
1441 "ssn->server.next_win %"PRIu32
"", ssn,
1443 SCLogDebug(
"ssn %p: ssn->client.last_ack %"PRIu32
", "
1444 "ssn->server.last_ack %"PRIu32
"", ssn,
1452 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1453 "ssn->client.last_ts %" PRIu32
"", ssn,
1472 SCLogDebug(
"ssn %p: assuming SACK permitted for both sides", ssn);
1486 const TCPHdr *tcph = PacketGetTCP(p);
1516 StreamTcp3whsSynAckToStateQueue(p, &search);
1524 search.
ts == q->
ts) {
1537 if (StreamTcp3whsFindSynAckBySynAck(ssn, p) != NULL)
1541 SCLogDebug(
"ssn %p: =~ SYN/ACK queue limit reached", ssn);
1547 SCLogDebug(
"ssn %p: =~ SYN/ACK queue failed: stream memcap reached", ssn);
1553 SCLogDebug(
"ssn %p: =~ SYN/ACK queue failed: alloc failed", ssn);
1558 StreamTcp3whsSynAckToStateQueue(p, q);
1572 const TCPHdr *tcph = PacketGetTCP(p);
1607 StreamTcp3whsSynAckToStateQueue(p, &update);
1614 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_SYN_RECV", ssn);
1630 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1631 "ssn->client.last_ts %" PRIu32
"", ssn,
1659 SCLogDebug(
"ssn %p: SACK permitted for session", ssn);
1666 SCLogDebug(
"ssn %p: ssn->server.next_win %" PRIu32
"", ssn,
1668 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
"", ssn,
1670 SCLogDebug(
"ssn %p: ssn->server.isn %" PRIu32
", "
1671 "ssn->server.next_seq %" PRIu32
", "
1672 "ssn->server.last_ack %" PRIu32
" "
1673 "(ssn->client.last_ack %" PRIu32
")", ssn,
1680 SCLogDebug(
"ssn %p: STREAMTCP_FLAG_4WHS unset, normal SYN/ACK"
1681 " so considering 3WHS", ssn);
1692 static inline bool StateSynSentValidateTimestamp(
TcpSession *ssn,
Packet *p)
1702 if (receiver_stream->
last_ts != 0 && ts_echo != 0 &&
1703 ts_echo != receiver_stream->
last_ts)
1705 SCLogDebug(
"ssn %p: BAD TSECR echo %u recv %u", ssn,
1706 ts_echo, receiver_stream->
last_ts);
1710 if (receiver_stream->
last_ts == 0 && ts_echo != 0) {
1711 SCLogDebug(
"ssn %p: BAD TSECR echo %u recv %u", ssn,
1712 ts_echo, receiver_stream->
last_ts);
1722 memset(q, 0,
sizeof(*q));
1742 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1748 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1752 memset(q, 0,
sizeof(*q));
1753 const TCPHdr *tcph = PacketGetTCP(p);
1771 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1778 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1785 memset(q, 0,
sizeof(*q));
1787 const TCPHdr *tcph = PacketGetTCP(p);
1804 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1814 SCLogDebug(
"ssn %p: search state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, s, s->
seq, s->
win,
1818 SCLogDebug(
"ssn %p: queue state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq,
1832 TcpStateQueueInitFromSsnSyn(ssn, &search);
1835 if (ssn->
queue != NULL && StreamTcp3whsFindSyn(ssn, &search) != NULL)
1839 SCLogDebug(
"ssn %p: =~ SYN queue limit reached", ssn);
1845 SCLogDebug(
"ssn %p: =~ SYN queue failed: stream memcap reached", ssn);
1851 SCLogDebug(
"ssn %p: =~ SYN queue failed: alloc failed", ssn);
1898 static int StreamTcpPacketStateSynSent(
1902 const TCPHdr *tcph = PacketGetTCP(p);
1908 SCLogDebug(
"ssn %p: SYN/ACK on SYN_SENT state for packet %" PRIu64, ssn, p->
pcap_cnt);
1915 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
1916 "%" PRIu32
" from stream",
1922 SCLogDebug(
"ssn %p: (TFO) ACK matches next_seq, packet ACK %" PRIu32
" == "
1923 "%" PRIu32
" from stream",
1926 SCLogDebug(
"ssn %p: (TFO) ACK matches ISN+1, packet ACK %" PRIu32
" == "
1927 "%" PRIu32
" from stream",
1935 SCLogDebug(
"ssn %p: (TFO) ACK mismatch, packet ACK %" PRIu32
" != "
1936 "%" PRIu32
" from stream",
1944 const bool ts_mismatch = !StateSynSentValidateTimestamp(ssn, p);
1949 TcpStateQueueInitFromPktSynAck(p, &search);
1951 const TcpStateQueue *q = StreamTcp3whsFindSyn(ssn, &search);
1957 SCLogDebug(
"ssn %p: found queued SYN state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u",
1961 StreamTcp3whsStoreSynApplyToSsn(ssn, q);
1971 StreamTcp3wsFreeQueue(ssn);
1973 StreamTcp3whsSynAckUpdate(ssn, p, NULL);
1980 SCLogDebug(
"ssn %p: SYN/ACK received in the wrong direction", ssn);
1984 SCLogDebug(
"ssn %p: SYN/ACK received on 4WHS session", ssn);
1991 SCLogDebug(
"ssn %p: 4WHS ACK mismatch, packet ACK %" PRIu32
""
1992 " != %" PRIu32
" from stream",
2002 SCLogDebug(
"ssn %p: 4WHS SEQ mismatch, packet SEQ %" PRIu32
""
2003 " != %" PRIu32
" from *first* SYN pkt",
2010 SCLogDebug(
"ssn %p: =~ 4WHS ssn state is now TCP_SYN_RECV", ssn);
2024 SCLogDebug(
"ssn %p: 4WHS ssn->client.last_ts %" PRIu32
" "
2025 "ssn->server.last_ts %" PRIu32
"",
2050 SCLogDebug(
"ssn %p: SACK permitted for 4WHS session", ssn);
2057 SCLogDebug(
"ssn %p: 4WHS ssn->client.isn %" PRIu32
", "
2058 "ssn->client.next_seq %" PRIu32
", "
2059 "ssn->client.last_ack %" PRIu32
" "
2060 "(ssn->server.last_ack %" PRIu32
")",
2069 if (StateSynSentValidateTimestamp(ssn, p) ==
false) {
2077 if (!StreamTcpValidateRst(ssn, p))
2084 SCLogDebug(
"ssn->server.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2086 StreamTcpCloseSsnWithReset(p, ssn);
2087 StreamTcp3wsFreeQueue(ssn);
2091 SCLogDebug(
"ssn->client.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2092 StreamTcpCloseSsnWithReset(p, ssn);
2093 StreamTcp3wsFreeQueue(ssn);
2101 SCLogDebug(
"ssn %p: SYN packet on state SYN_SENT... resent", ssn);
2103 SCLogDebug(
"ssn %p: SYN packet on state SYN_SENT... resent of "
2116 SCLogDebug(
"ssn %p: STREAMTCP_FLAG_4WHS flag set", ssn);
2153 SCLogDebug(
"ssn %p: 4WHS ssn->server.isn %" PRIu32
", "
2154 "ssn->server.next_seq %" PRIu32
", "
2155 "ssn->server.last_ack %"PRIu32
"", ssn,
2158 SCLogDebug(
"ssn %p: 4WHS ssn->client.isn %" PRIu32
", "
2159 "ssn->client.next_seq %" PRIu32
", "
2160 "ssn->client.last_ack %"PRIu32
"", ssn,
2169 TcpStateQueueInitFromPktSyn(p, &syn_pkt);
2170 TcpStateQueueInitFromSsnSyn(ssn, &syn_ssn);
2172 if (memcmp(&syn_pkt, &syn_ssn,
sizeof(
TcpStateQueue)) != 0) {
2174 StreamTcp3whsStoreSyn(ssn, p);
2175 SCLogDebug(
"ssn %p: Retransmitted SYN. Updating ssn from packet %" PRIu64
2176 ". Stored previous state",
2179 StreamTcp3whsStoreSynApplyToSsn(ssn, &syn_pkt);
2195 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
2196 "%" PRIu32
" from stream",
2203 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2204 StreamTcp3wsFreeQueue(ssn);
2217 SCLogDebug(
"ssn %p: synsent => Asynchronous stream, packet SEQ"
2218 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2219 "ssn->client.next_seq %" PRIu32
"",
2268 static int StreamTcpPacketStateSynRecv(
2272 const TCPHdr *tcph = PacketGetTCP(p);
2275 if (!StreamTcpValidateRst(ssn, p))
2292 SCLogDebug(
"Detection evasion has been attempted, so"
2293 " not resetting the connection !!");
2301 SCLogDebug(
"Detection evasion has been attempted, so"
2302 " not resetting the connection !!");
2308 StreamTcpCloseSsnWithReset(p, ssn);
2311 StreamTcpHandleTimestamp(ssn, p);
2318 if (!StreamTcpValidateTimestamp(ssn, p))
2322 if ((StreamTcpHandleFin(
tv, stt, ssn, p)) == -1)
2327 SCLogDebug(
"ssn %p: SYN/ACK packet on state SYN_RECV. resent", ssn);
2330 SCLogDebug(
"ssn %p: SYN/ACK-pkt to server in SYN_RECV state", ssn);
2339 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
2340 "%" PRIu32
" from stream",
2350 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
2351 "%" PRIu32
" from stream",
2354 if (StreamTcp3whsQueueSynAck(ssn, p) == -1)
2356 SCLogDebug(
"ssn %p: queued different SYN/ACK", ssn);
2360 SCLogDebug(
"ssn %p: SYN packet on state SYN_RECV... resent", ssn);
2363 SCLogDebug(
"ssn %p: SYN-pkt to client in SYN_RECV state", ssn);
2370 SCLogDebug(
"ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
2378 SCLogDebug(
"ssn %p: checking ACK against queued SYN/ACKs", ssn);
2381 SCLogDebug(
"ssn %p: here we update state against queued SYN/ACK", ssn);
2382 StreamTcp3whsSynAckUpdate(ssn, p, q);
2384 SCLogDebug(
"ssn %p: none found, now checking ACK against original SYN/ACK (state)", ssn);
2394 if (!(StreamTcpValidateTimestamp(ssn, p))) {
2400 SCLogDebug(
"ssn %p: ACK received on 4WHS session",ssn);
2403 SCLogDebug(
"ssn %p: 4WHS wrong seq nr on packet", ssn);
2408 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
2409 SCLogDebug(
"ssn %p: 4WHS invalid ack nr on packet", ssn);
2415 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
2416 "%" PRIu32
", ACK %" PRIu32
"",
2420 StreamTcpHandleTimestamp(ssn, p);
2429 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2433 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
", "
2434 "ssn->client.last_ack %"PRIu32
"", ssn,
2439 bool ack_indicates_missed_3whs_ack_packet =
false;
2449 SCLogDebug(
"ssn %p: ACK received on midstream SYN/ACK "
2450 "pickup session",ssn);
2453 SCLogDebug(
"ssn %p: ACK received on TFO session",ssn);
2470 SCLogDebug(
"ssn %p: possible data injection", ssn);
2475 SCLogDebug(
"ssn %p: ACK received in the wrong direction",
2480 ack_indicates_missed_3whs_ack_packet =
true;
2484 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ %" PRIu32
""
2485 ", ACK %" PRIu32
"",
2497 StreamTcpHandleTimestamp(ssn, p);
2521 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2547 StreamTcpHandleTimestamp(ssn, p);
2560 SCLogDebug(
"ssn %p: synrecv => Asynchronous stream, packet SEQ"
2561 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2562 "ssn->server.next_seq %" PRIu32,
2567 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2576 SCLogDebug(
"ssn %p: wrong ack nr on packet, possible evasion!!",
2586 SCLogDebug(
"ssn %p: ACK for missing data", ssn);
2589 StreamTcpHandleTimestamp(ssn, p);
2595 SCLogDebug(
"ssn %p: ACK for missing data: ssn->server.next_seq %u", ssn,
2605 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2614 SCLogDebug(
"ssn %p: ACK for missing data", ssn);
2617 StreamTcpHandleTimestamp(ssn, p);
2639 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2644 }
else if ((ack_indicates_missed_3whs_ack_packet ||
2648 if (ack_indicates_missed_3whs_ack_packet) {
2649 SCLogDebug(
"ssn %p: packet fits perfectly after a missed 3whs-ACK", ssn);
2651 SCLogDebug(
"ssn %p: (TFO) expected packet fits perfectly after SYN/ACK", ssn);
2660 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2665 SCLogDebug(
"ssn %p: wrong seq nr on packet", ssn);
2671 SCLogDebug(
"ssn %p: ssn->server.next_win %" PRIu32
", "
2672 "ssn->server.last_ack %"PRIu32
"", ssn,
2694 static int HandleEstablishedPacketToServer(
2697 const TCPHdr *tcph = PacketGetTCP(p);
2702 SCLogDebug(
"ssn %p: =+ pkt (%" PRIu32
") is to server: SEQ %" PRIu32
","
2703 "ACK %" PRIu32
", WIN %" PRIu16
"",
2709 SCLogDebug(
"ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
2712 }
else if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
2713 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
2721 SCLogDebug(
"ssn %p: pkt is keep alive", ssn);
2726 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ"
2727 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
2728 " ssn->client.last_ack %" PRIu32
", ssn->client.next_win"
2729 "%" PRIu32
"(%" PRIu32
")",
2739 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ."
2740 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2741 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2742 "%" PRIu32
"(%" PRIu32
")",
2754 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ"
2755 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2756 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2757 "%" PRIu32
"(%" PRIu32
")",
2772 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
2773 " before last_ack %" PRIu32
", after next_seq %" PRIu32
":"
2774 " acked data that we haven't seen before",
2777 SCLogDebug(
"ssn %p: server => SEQ before last_ack, packet SEQ"
2778 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2779 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2780 "%" PRIu32
"(%" PRIu32
")",
2784 SCLogDebug(
"ssn %p: rejecting because pkt before last_ack", ssn);
2790 int zerowindowprobe = 0;
2793 SCLogDebug(
"ssn %p: zero window probe", ssn);
2794 zerowindowprobe = 1;
2804 if (zerowindowprobe) {
2805 SCLogDebug(
"ssn %p: zero window probe, skipping oow check", ssn);
2808 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
2813 SCLogDebug(
"ssn %p: ssn->server.window %"PRIu32
"", ssn,
2830 StreamTcpHandleTimestamp(ssn, p);
2842 SCLogDebug(
"ssn %p: toserver => SEQ out of window, packet SEQ "
2843 "%" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
2844 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2845 "%" PRIu32
"(%" PRIu32
")",
2849 StreamTcpSackedSize(&ssn->
client));
2869 static int HandleEstablishedPacketToClient(
2872 const TCPHdr *tcph = PacketGetTCP(p);
2877 SCLogDebug(
"ssn %p: =+ pkt (%" PRIu32
") is to client: SEQ %" PRIu32
","
2878 " ACK %" PRIu32
", WIN %" PRIu16
"",
2884 SCLogDebug(
"ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
2887 }
else if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
2888 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
2902 SCLogDebug(
"ssn %p: adjusted midstream ssn->server.next_win to "
2908 SCLogDebug(
"ssn %p: pkt is keep alive", ssn);
2914 SCLogDebug(
"ssn %p: client => Asynchronous stream, packet SEQ"
2915 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
2916 " ssn->client.last_ack %" PRIu32
", ssn->client.next_win"
2917 " %" PRIu32
"(%" PRIu32
")",
2928 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
2929 " before last_ack %" PRIu32
", after next_seq %" PRIu32
":"
2930 " acked data that we haven't seen before",
2933 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
2934 " before last_ack %" PRIu32
". next_seq %" PRIu32,
2941 int zerowindowprobe = 0;
2944 SCLogDebug(
"ssn %p: zero window probe", ssn);
2945 zerowindowprobe = 1;
2956 if (zerowindowprobe) {
2957 SCLogDebug(
"ssn %p: zero window probe, skipping oow check", ssn);
2960 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
2964 SCLogDebug(
"ssn %p: ssn->client.window %"PRIu32
"", ssn,
2977 StreamTcpHandleTimestamp(ssn, p);
2986 SCLogDebug(
"ssn %p: client => SEQ out of window, packet SEQ"
2987 "%" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
2988 " ssn->server.last_ack %" PRIu32
", ssn->server.next_win "
2989 "%" PRIu32
"(%" PRIu32
")",
3010 static inline uint32_t StreamTcpResetGetMaxAck(
TcpStream *stream, uint32_t
seq)
3016 if (
SEQ_GT(tail_seq, ack)) {
3024 static bool StreamTcpPacketIsZeroWindowProbeAck(
const TcpSession *ssn,
const Packet *p)
3026 const TCPHdr *tcph = PacketGetTCP(p);
3050 if (pkt_win != rcv->
window)
3057 SCLogDebug(
"ssn %p: packet %" PRIu64
" is a Zero Window Probe ACK", ssn, p->
pcap_cnt);
3064 static bool StreamTcpPacketIsDupAck(
const TcpSession *ssn,
const Packet *p)
3066 const TCPHdr *tcph = PacketGetTCP(p);
3084 if (pkt_win == 0 || rcv->
window == 0)
3086 if (pkt_win != rcv->
window)
3094 SCLogDebug(
"ssn %p: packet:%" PRIu64
" seq:%u ack:%u win:%u snd %u:%u:%u rcv %u:%u:%u", ssn,
3118 const TCPHdr *tcph = PacketGetTCP(p);
3169 static int StreamTcpPacketIsSpuriousRetransmission(
const TcpSession *ssn,
Packet *p)
3180 const TCPHdr *tcph = PacketGetTCP(p);
3186 "ssn %p: spurious retransmission; packet entirely before base_seq: SEQ %u(%u) "
3187 "last_ack %u base_seq %u",
3196 SCLogDebug(
"ssn %p: spurious retransmission; packet entirely before last_ack: SEQ %u(%u) "
3204 SCLogDebug(
"ssn %p: NOT spurious retransmission; packet NOT entirely before last_ack: SEQ "
3205 "%u(%u) last_ack %u, base_seq %u",
3222 static int StreamTcpPacketStateEstablished(
3226 const TCPHdr *tcph = PacketGetTCP(p);
3232 if (!StreamTcpValidateRst(ssn, p))
3236 StreamTcpCloseSsnWithReset(p, ssn);
3240 SCLogDebug(
"ssn %p: ssn->server.next_seq %" PRIu32
"", ssn,
3246 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, window));
3251 StreamTcpHandleTimestamp(ssn, p);
3255 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3263 StreamTcpCloseSsnWithReset(p, ssn);
3268 SCLogDebug(
"ssn %p: ssn->server.next_seq %" PRIu32
"", ssn,
3274 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
3279 StreamTcpHandleTimestamp(ssn, p);
3283 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3294 if (!StreamTcpValidateTimestamp(ssn, p))
3299 " %" PRIu32
", last ACK %" PRIu32
", next win %"PRIu32
","
3304 if ((StreamTcpHandleFin(
tv, stt, ssn, p)) == -1)
3309 SCLogDebug(
"ssn %p: SYN/ACK packet on state ESTABLISHED... resent",
3313 SCLogDebug(
"ssn %p: SYN/ACK-pkt to server in ESTABLISHED state", ssn);
3322 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
3323 "%" PRIu32
" from stream",
3333 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
3334 "%" PRIu32
" from stream",
3347 SCLogDebug(
"ssn %p: SYN/ACK packet on state ESTABLISHED... resent. "
3348 "Likely due server not receiving final ACK in 3whs", ssn);
3352 SCLogDebug(
"ssn %p: SYN packet on state ESTABLISHED... resent", ssn);
3354 SCLogDebug(
"ssn %p: SYN-pkt to client in EST state", ssn);
3361 SCLogDebug(
"ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
3382 if (!StreamTcpValidateTimestamp(ssn, p))
3388 HandleEstablishedPacketToServer(
tv, ssn, p, stt);
3390 SCLogDebug(
"ssn %p: next SEQ %" PRIu32
", last ACK %" PRIu32
","
3391 " next win %" PRIu32
", win %" PRIu32
"", ssn,
3398 SCLogDebug(
"3whs is now confirmed by server");
3402 HandleEstablishedPacketToClient(
tv, ssn, p, stt);
3404 SCLogDebug(
"ssn %p: next SEQ %" PRIu32
", last ACK %" PRIu32
","
3405 " next win %" PRIu32
", win %" PRIu32
"", ssn,
3430 const TCPHdr *tcph = PacketGetTCP(p);
3436 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ %" PRIu32
","
3440 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3441 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3447 SCLogDebug(
"ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn,
seq, pkt_re,
3452 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
" != "
3453 "%" PRIu32
" from stream",
3466 SCLogDebug(
"ssn %p: state changed to TCP_CLOSE_WAIT", ssn);
3471 SCLogDebug(
"ssn %p: ssn->client.next_seq %" PRIu32
"", ssn,
3476 StreamTcpHandleTimestamp(ssn, p);
3489 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK %" PRIu32
"",
3492 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ %" PRIu32
", "
3496 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3497 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3503 SCLogDebug(
"ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn,
seq, pkt_re,
3508 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
" != "
3509 "%" PRIu32
" from stream (last_ack %u win %u = %u)",
3518 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT1", ssn);
3527 StreamTcpHandleTimestamp(ssn, p);
3540 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK %" PRIu32
"",
3560 static int StreamTcpPacketStateFinWait1(
3564 const TCPHdr *tcph = PacketGetTCP(p);
3570 if (!StreamTcpValidateRst(ssn, p))
3573 StreamTcpCloseSsnWithReset(p, ssn);
3578 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, ack));
3583 StreamTcpHandleTimestamp(ssn, p);
3590 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
3595 StreamTcpHandleTimestamp(ssn, p);
3603 if (!StreamTcpValidateTimestamp(ssn, p))
3608 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3609 "%" PRIu32
", ACK %" PRIu32
"",
3611 int retransmission = 0;
3613 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
3614 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3620 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3621 " != %" PRIu32
" from stream",
3627 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3628 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3633 if (!retransmission) {
3635 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
3641 StreamTcpHandleTimestamp(ssn, p);
3657 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3661 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3662 "%" PRIu32
", ACK %" PRIu32
"",
3664 int retransmission = 0;
3666 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
3667 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3672 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3678 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3679 " != %" PRIu32
" from stream",
3685 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3686 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3692 StreamTcpHandleTimestamp(ssn, p);
3695 if (!retransmission) {
3697 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
3715 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3722 if (!StreamTcpValidateTimestamp(ssn, p))
3727 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3728 "%" PRIu32
", ACK %" PRIu32
"",
3730 int retransmission = 0;
3732 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
3733 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3739 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3740 " != %" PRIu32
" from stream",
3746 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3747 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3752 if (!retransmission) {
3754 SCLogDebug(
"ssn %p: state changed to TCP_CLOSING", ssn);
3760 StreamTcpHandleTimestamp(ssn, p);
3777 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3781 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3782 "%" PRIu32
", ACK %" PRIu32
"",
3785 int retransmission = 0;
3787 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
3788 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3794 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3795 " != %" PRIu32
" from stream",
3801 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3802 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3807 if (!retransmission) {
3809 SCLogDebug(
"ssn %p: state changed to TCP_CLOSING", ssn);
3815 StreamTcpHandleTimestamp(ssn, p);
3832 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3837 SCLogDebug(
"ssn (%p): SYN pkt on FinWait1", ssn);
3843 if (!StreamTcpValidateTimestamp(ssn, p))
3848 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3849 "%" PRIu32
", ACK %" PRIu32
"",
3851 int retransmission = 0;
3853 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
3854 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3859 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3860 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3867 "ssn %p: ACK's older segment as %u < %u", ssn, ack, ssn->
server.
next_seq);
3868 }
else if (!retransmission) {
3872 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
3878 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT2", ssn);
3881 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3882 " != %" PRIu32
" from stream",
3894 StreamTcpHandleTimestamp(ssn, p);
3915 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3921 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3922 "%" PRIu32
", ACK %" PRIu32
"",
3925 int retransmission = 0;
3927 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
3928 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3933 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3934 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3939 if (!retransmission) {
3942 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
3948 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT2", ssn);
3951 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3952 " != %" PRIu32
" from stream",
3962 StreamTcpHandleTimestamp(ssn, p);
3983 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4004 static int StreamTcpPacketStateFinWait2(
4008 const TCPHdr *tcph = PacketGetTCP(p);
4014 if (!StreamTcpValidateRst(ssn, p))
4017 StreamTcpCloseSsnWithReset(p, ssn);
4022 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, ack));
4027 StreamTcpHandleTimestamp(ssn, p);
4034 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
4039 StreamTcpHandleTimestamp(ssn, p);
4047 if (!StreamTcpValidateTimestamp(ssn, p))
4052 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4053 "%" PRIu32
", ACK %" PRIu32
"",
4055 int retransmission = 0;
4061 }
else if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4062 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4068 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ "
4069 "%" PRIu32
" != %" PRIu32
" from stream",
4075 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4076 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4081 if (!retransmission) {
4083 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4093 StreamTcpHandleTimestamp(ssn, p);
4106 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4110 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4111 "%" PRIu32
", ACK %" PRIu32
"",
4113 int retransmission = 0;
4119 }
else if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4120 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4126 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ "
4127 "%" PRIu32
" != %" PRIu32
" from stream",
4133 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4134 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4139 if (!retransmission) {
4141 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4147 StreamTcpHandleTimestamp(ssn, p);
4159 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4165 SCLogDebug(
"ssn (%p): SYN pkt on FinWait2", ssn);
4171 if (!StreamTcpValidateTimestamp(ssn, p))
4176 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4177 "%" PRIu32
", ACK %" PRIu32
"",
4179 int retransmission = 0;
4181 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4182 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4187 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4188 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4193 if (!retransmission) {
4196 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
4201 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4202 " != %" PRIu32
" from stream",
4212 StreamTcpHandleTimestamp(ssn, p);
4228 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4232 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4233 "%" PRIu32
", ACK %" PRIu32
"",
4235 int retransmission = 0;
4237 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4238 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4243 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4244 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4249 if (!retransmission) {
4252 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
4256 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4257 " != %" PRIu32
" from stream",
4267 StreamTcpHandleTimestamp(ssn, p);
4283 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4304 static int StreamTcpPacketStateClosing(
4308 const TCPHdr *tcph = PacketGetTCP(p);
4314 if (!StreamTcpValidateRst(ssn, p))
4317 StreamTcpCloseSsnWithReset(p, ssn);
4322 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, ack));
4327 StreamTcpHandleTimestamp(ssn, p);
4334 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
4339 StreamTcpHandleTimestamp(ssn, p);
4346 SCLogDebug(
"ssn (%p): SYN pkt on Closing", ssn);
4352 if (!StreamTcpValidateTimestamp(ssn, p))
4357 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4358 "%" PRIu32
", ACK %" PRIu32
"",
4360 int retransmission = 0;
4361 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4362 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4368 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4369 " != %" PRIu32
" from stream",
4375 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4376 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4381 if (!retransmission) {
4383 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4389 StreamTcpHandleTimestamp(ssn, p);
4399 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4403 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4404 "%" PRIu32
", ACK %" PRIu32
"",
4406 int retransmission = 0;
4407 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4408 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4414 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4415 " != %" PRIu32
" from stream",
4421 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4422 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4427 if (!retransmission) {
4429 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4435 StreamTcpHandleTimestamp(ssn, p);
4446 SCLogDebug(
"StreamTcpPacketStateClosing (%p): =+ next SEQ "
4447 "%" PRIu32
", last ACK %" PRIu32
"", ssn,
4467 static int StreamTcpPacketStateCloseWait(
4471 const TCPHdr *tcph = PacketGetTCP(p);
4479 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4480 "%" PRIu32
", ACK %" PRIu32
"",
4483 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4484 "%" PRIu32
", ACK %" PRIu32
"",
4489 if (!StreamTcpValidateRst(ssn, p))
4492 StreamTcpCloseSsnWithReset(p, ssn);
4497 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, ack));
4502 StreamTcpHandleTimestamp(ssn, p);
4509 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
4514 StreamTcpHandleTimestamp(ssn, p);
4522 if (!StreamTcpValidateTimestamp(ssn, p))
4527 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4528 "%" PRIu32
", ACK %" PRIu32
"",
4531 int retransmission = 0;
4532 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4533 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4538 if (!retransmission) {
4541 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4542 " != %" PRIu32
" from stream",
4549 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4550 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4557 if (!retransmission)
4561 StreamTcpHandleTimestamp(ssn, p);
4573 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4577 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4578 "%" PRIu32
", ACK %" PRIu32
"",
4581 int retransmission = 0;
4582 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4583 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4588 if (!retransmission) {
4591 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4592 " != %" PRIu32
" from stream",
4599 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4600 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4605 if (!retransmission) {
4607 SCLogDebug(
"ssn %p: state changed to TCP_LAST_ACK", ssn);
4613 StreamTcpHandleTimestamp(ssn, p);
4625 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4631 SCLogDebug(
"ssn (%p): SYN pkt on CloseWait", ssn);
4637 if (!StreamTcpValidateTimestamp(ssn, p))
4642 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4643 "%" PRIu32
", ACK %" PRIu32
"",
4646 int retransmission = 0;
4647 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4648 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4654 SCLogDebug(
"ssn %p: -> retransmission", ssn);
4659 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4660 " != %" PRIu32
" from stream",
4666 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4667 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4672 if (!retransmission) {
4677 StreamTcpHandleTimestamp(ssn, p);
4691 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4695 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4696 "%" PRIu32
", ACK %" PRIu32
"",
4698 int retransmission = 0;
4699 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4700 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4706 SCLogDebug(
"ssn %p: -> retransmission", ssn);
4711 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4712 " != %" PRIu32
" from stream",
4718 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4719 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4724 if (!retransmission) {
4729 StreamTcpHandleTimestamp(ssn, p);
4743 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4764 static int StreamTcpPacketStateLastAck(
4768 const TCPHdr *tcph = PacketGetTCP(p);
4774 if (!StreamTcpValidateRst(ssn, p))
4777 StreamTcpCloseSsnWithReset(p, ssn);
4782 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, ack));
4787 StreamTcpHandleTimestamp(ssn, p);
4794 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
4799 StreamTcpHandleTimestamp(ssn, p);
4807 SCLogDebug(
"ssn (%p): FIN pkt on LastAck", ssn);
4810 SCLogDebug(
"ssn (%p): SYN pkt on LastAck", ssn);
4816 if (!StreamTcpValidateTimestamp(ssn, p))
4821 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4822 "%" PRIu32
", ACK %" PRIu32
"",
4825 int retransmission = 0;
4826 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4827 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4832 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4833 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4838 if (!retransmission) {
4840 SCLogDebug(
"ssn %p: not updating state as packet is before next_seq", ssn);
4842 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4843 " != %" PRIu32
" from stream",
4849 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
4855 StreamTcpHandleTimestamp(ssn, p);
4866 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4887 static int StreamTcpPacketStateTimeWait(
4891 const TCPHdr *tcph = PacketGetTCP(p);
4897 if (!StreamTcpValidateRst(ssn, p))
4900 StreamTcpCloseSsnWithReset(p, ssn);
4905 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, ack));
4910 StreamTcpHandleTimestamp(ssn, p);
4917 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
4922 StreamTcpHandleTimestamp(ssn, p);
4932 SCLogDebug(
"ssn (%p): SYN pkt on TimeWait", ssn);
4938 if (!StreamTcpValidateTimestamp(ssn, p))
4943 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4944 "%" PRIu32
", ACK %" PRIu32
"",
4946 int retransmission = 0;
4947 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4948 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4953 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4954 " != %" PRIu32
" from stream",
4960 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4961 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4966 if (!retransmission) {
4968 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
4974 StreamTcpHandleTimestamp(ssn, p);
4985 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4989 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4990 "%" PRIu32
", ACK %" PRIu32
"",
4992 int retransmission = 0;
4993 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4994 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4999 SCLogDebug(
"ssn %p: -> retransmission", ssn);
5002 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5003 " != %" PRIu32
" from stream",
5010 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
5011 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5016 if (!retransmission) {
5018 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5024 StreamTcpHandleTimestamp(ssn, p);
5035 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5047 static int StreamTcpPacketStateClosed(
5052 const TCPHdr *tcph = PacketGetTCP(p);
5058 TcpStream *stream = NULL, *ostream = NULL;
5075 if (StreamTcpStateDispatch(
tv, p, stt, ssn, ssn->
pstate) < 0)
5090 const TCPHdr *tcph = PacketGetTCP(p);
5104 SCLogDebug(
"regular packet %"PRIu64
" from same sender as "
5105 "the previous RST. Looks like it injected!", p->
pcap_cnt);
5131 const TCPHdr *tcph = PacketGetTCP(p);
5136 TcpStream *stream = NULL, *ostream = NULL;
5147 if (ack == ostream->last_ack &&
seq == (stream->
next_seq - 1)) {
5163 TcpStream *stream = NULL, *ostream = NULL;
5174 const TCPHdr *tcph = PacketGetTCP(p);
5193 if (pkt_win != ostream->window)
5202 SCLogDebug(
"seq %u (%u), ack %u (%u) FLAG_KEEPALIVE: %s",
seq, stream->
next_seq, ack, ostream->last_ack,
5232 TcpStream *stream = NULL, *ostream = NULL;
5246 const TCPHdr *tcph = PacketGetTCP(p);
5265 if (pkt_win == ostream->window)
5268 if (ack == ostream->last_ack &&
seq == stream->
next_seq) {
5283 TcpStream *stream = NULL, *ostream = NULL;
5291 const TCPHdr *tcph = PacketGetTCP(p);
5308 SCLogDebug(
"%"PRIu64
", seq %u ack %u stream->next_seq %u ostream->next_seq %u",
5336 TcpStream *stream = NULL, *ostream = NULL;
5347 const TCPHdr *tcph = PacketGetTCP(p);
5363 if (pkt_win < ostream->window) {
5364 uint32_t diff = ostream->window - pkt_win;
5366 SEQ_GT(ack, ostream->next_seq) &&
5369 SCLogDebug(
"%"PRIu64
", pkt_win %u, stream win %u, diff %u, dsize %u",
5371 SCLogDebug(
"%"PRIu64
", pkt_win %u, stream win %u",
5372 p->
pcap_cnt, pkt_win, ostream->window);
5373 SCLogDebug(
"%"PRIu64
", seq %u ack %u ostream->next_seq %u ostream->last_ack %u, ostream->next_win %u, diff %u (%u)",
5374 p->
pcap_cnt,
seq, ack, ostream->next_seq, ostream->last_ack, ostream->next_win,
5375 ostream->next_seq - ostream->last_ack, stream->
next_seq - stream->
last_ack);
5382 uint32_t adiff = ack - ostream->last_ack;
5383 if (((pkt_win > 1024) && (diff > (adiff + 32))) ||
5384 ((pkt_win <= 1024) && (diff > adiff)))
5386 SCLogDebug(
"pkt ACK %u is %u bytes beyond last_ack %u, shrinks window by %u "
5387 "(allowing 32 bytes extra): pkt WIN %u", ack, adiff, ostream->last_ack, diff, pkt_win);
5388 SCLogDebug(
"%u - %u = %u (state %u)", diff, adiff, diff - adiff, ssn->
state);
5403 static inline int StreamTcpStateDispatch(
5411 SCLogDebug(
"packet received on TCP_SYN_SENT state");
5412 if (StreamTcpPacketStateSynSent(
tv, p, stt, ssn)) {
5417 SCLogDebug(
"packet received on TCP_SYN_RECV state");
5418 if (StreamTcpPacketStateSynRecv(
tv, p, stt, ssn)) {
5423 SCLogDebug(
"packet received on TCP_ESTABLISHED state");
5424 if (StreamTcpPacketStateEstablished(
tv, p, stt, ssn)) {
5429 SCLogDebug(
"packet received on TCP_FIN_WAIT1 state");
5430 if (StreamTcpPacketStateFinWait1(
tv, p, stt, ssn)) {
5435 SCLogDebug(
"packet received on TCP_FIN_WAIT2 state");
5436 if (StreamTcpPacketStateFinWait2(
tv, p, stt, ssn)) {
5441 SCLogDebug(
"packet received on TCP_CLOSING state");
5442 if (StreamTcpPacketStateClosing(
tv, p, stt, ssn)) {
5447 SCLogDebug(
"packet received on TCP_CLOSE_WAIT state");
5448 if (StreamTcpPacketStateCloseWait(
tv, p, stt, ssn)) {
5453 SCLogDebug(
"packet received on TCP_LAST_ACK state");
5454 if (StreamTcpPacketStateLastAck(
tv, p, stt, ssn)) {
5459 SCLogDebug(
"packet received on TCP_TIME_WAIT state");
5460 if (StreamTcpPacketStateTimeWait(
tv, p, stt, ssn)) {
5466 SCLogDebug(
"packet received on closed state");
5468 if (StreamTcpPacketStateClosed(
tv, p, stt, ssn)) {
5474 SCLogDebug(
"packet received on default state");
5510 const TCPHdr *tcph = PacketGetTCP(p);
5525 SCLogDebug(
"ssn %p: removing ASYNC flag as we have packets on both sides", ssn);
5539 if (StreamTcpCheckFlowDrops(p) == 1) {
5549 if (StreamTcpPacketStateNone(
tv, p, stt, ssn) == -1) {
5575 if (StreamTcpPacketIsKeepAlive(ssn, p) == 1) {
5578 if (StreamTcpPacketIsKeepAliveACK(ssn, p) == 1) {
5579 StreamTcpClearKeepAliveFlag(ssn, p);
5582 StreamTcpClearKeepAliveFlag(ssn, p);
5584 const bool is_zwp_ack = StreamTcpPacketIsZeroWindowProbeAck(ssn, p);
5595 if (StreamTcpPacketIsDupAck(ssn, p) ==
true) {
5602 if (StreamTcpPacketIsFinShutdownAck(ssn, p) == 0) {
5603 if (StreamTcpPacketIsWindowUpdate(ssn, p) == 0) {
5604 if (StreamTcpPacketIsBadWindowUpdate(ssn,p))
5606 if (StreamTcpPacketIsOutdatedAck(ssn, p))
5611 int ret = StreamTcpPacketIsSpuriousRetransmission(ssn, p);
5620 if (StreamTcpStateDispatch(
tv, p, stt, ssn, ssn->
state) < 0)
5624 StreamTcpPacketCheckPostRst(ssn, p);
5673 SCLogDebug(
"bypass as stream is dead and we have no rules");
5686 if (StreamTcpInlineDropInvalid()) {
5690 DecodeSetNoPayloadInspectionFlag(p);
5704 static inline int StreamTcpValidateChecksum(
Packet *p)
5712 const TCPHdr *tcph = PacketGetTCP(p);
5713 if (PacketIsIPv4(p)) {
5714 const IPV4Hdr *ip4h = PacketGetIPv4(p);
5715 p->
l4.
csum = TCPChecksum(ip4h->s_ip_addrs, (uint16_t *)tcph,
5718 }
else if (PacketIsIPv6(p)) {
5719 const IPV6Hdr *ip6h = PacketGetIPv6(p);
5720 p->
l4.
csum = TCPV6Checksum(ip6h->s_ip6_addrs, (uint16_t *)tcph,
5741 static int TcpSessionPacketIsStreamStarter(
const Packet *p)
5743 const TCPHdr *tcph = PacketGetTCP(p);
5766 static bool TcpSessionReuseDoneEnoughSyn(
const Packet *p,
const Flow *f,
const TcpSession *ssn)
5768 const TCPHdr *tcph = PacketGetTCP(p);
5773 SCLogDebug(
"steam starter packet %" PRIu64
", ssn %p null. Reuse.", p->
pcap_cnt, ssn);
5778 ", ssn %p. STREAMTCP_FLAG_TFO_DATA_IGNORED set. Reuse.",
5783 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.", p->
pcap_cnt, ssn);
5787 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5790 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5793 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
5803 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5806 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5809 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
5822 static bool TcpSessionReuseDoneEnoughSynAck(
const Packet *p,
const Flow *f,
const TcpSession *ssn)
5824 const TCPHdr *tcph = PacketGetTCP(p);
5827 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p null. No reuse.", p->
pcap_cnt, ssn);
5831 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.", p->
pcap_cnt, ssn);
5835 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5838 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5841 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
5851 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5854 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5857 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
5873 const TCPHdr *tcph = PacketGetTCP(p);
5875 return TcpSessionReuseDoneEnoughSyn(p, f, ssn);
5880 return TcpSessionReuseDoneEnoughSynAck(p, f, ssn);
5889 if (p->
proto == IPPROTO_TCP && PacketIsTCP(p)) {
5890 if (TcpSessionPacketIsStreamStarter(p) == 1) {
5891 if (TcpSessionReuseDoneEnough(p, f, tcp_ssn) == 1) {
5914 if (!(PacketIsTCP(p))) {
5918 HandleThreadId(
tv, p, stt);
5924 if (StreamTcpValidateChecksum(p) == 0) {
5950 *data = (
void *)stt;
5959 IsStreamTcpSessionMemcapExceptionPolicyStatsValid);
5968 "tcp.midstream_exception_policy.", IsMidstreamExceptionPolicyStatsValid);
5972 "tcp.midstream_exception_policy.", IsMidstreamExceptionPolicyStatsValid);
5987 "tcp.reassembly_exception_policy.", IsReassemblyMemcapExceptionPolicyStatsValid);
6000 SCLogDebug(
"StreamTcp thread specific ctx online at %p, reassembly ctx %p",
6009 StreamTcpSessionPoolAlloc,
6010 StreamTcpSessionPoolInit, NULL,
6011 StreamTcpSessionPoolCleanup, NULL);
6021 SCLogError(
"failed to setup/expand stream session pool. Expand stream.memcap?");
6066 const TCPHdr *tcph = PacketGetTCP(p);
6074 if (!StreamTcpValidateTimestamp(ssn, p)) {
6103 StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
6104 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
6116 StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
6117 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
6130 receiver_stream = &ssn->
server;
6132 receiver_stream = &ssn->
client;
6134 SCLogDebug(
"ssn %p: setting STREAMTCP_STREAM_FLAG_RST_RECV on receiver stream", ssn);
6154 switch (os_policy) {
6161 SCLogDebug(
"reset is not Valid! Packet SEQ: %" PRIu32
" "
6162 "and server SEQ: %" PRIu32
"",
6171 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" "
6172 "and client SEQ: %" PRIu32
"",
6189 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6190 " server SEQ: %" PRIu32
"",
6202 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6203 " client SEQ: %" PRIu32
"",
6224 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" "
6225 "and server SEQ: %" PRIu32
"",
6231 SCLogDebug(
"reset is valid! Packet SEQ: %" PRIu32
" Stream %u",
seq,
6235 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6236 " client SEQ: %" PRIu32
"",
6267 uint8_t check_ts = 1;
6268 const TCPHdr *tcph = PacketGetTCP(p);
6272 sender_stream = &ssn->
client;
6273 receiver_stream = &ssn->
server;
6275 sender_stream = &ssn->
server;
6276 receiver_stream = &ssn->
client;
6287 uint32_t last_pkt_ts = sender_stream->
last_pkt_ts;
6288 uint32_t last_ts = sender_stream->
last_ts;
6338 SCLogDebug(
"ts %"PRIu32
", last_ts %"PRIu32
"",
ts, last_ts);
6342 result = (int32_t) ((
ts - last_ts) + 1);
6344 result = (int32_t) (
ts - last_ts);
6347 SCLogDebug(
"result %" PRIi32
", p->ts(secs) %" PRIuMAX
"", result,
6350 if (last_pkt_ts == 0 &&
6358 "%" PRIu32
" p->tcpvars->ts %" PRIu32
" result "
6359 "%" PRId32
"", last_ts,
ts, result);
6362 }
else if ((sender_stream->
last_ts != 0) &&
6364 SCLogDebug(
"packet is not valid last_pkt_ts "
6365 "%" PRIu32
" p->ts(sec) %" PRIu32
"",
6377 SCLogDebug(
"timestamp considered valid anyway");
6409 uint8_t check_ts = 1;
6410 const TCPHdr *tcph = PacketGetTCP(p);
6414 sender_stream = &ssn->
client;
6415 receiver_stream = &ssn->
server;
6417 sender_stream = &ssn->
server;
6418 receiver_stream = &ssn->
client;
6486 result = (int32_t) ((
ts - sender_stream->
last_ts) + 1);
6488 result = (int32_t) (
ts - sender_stream->
last_ts);
6491 SCLogDebug(
"result %" PRIi32
", p->ts(sec) %" PRIuMAX
"", result,
6501 SCLogDebug(
"timestamp is not valid sender_stream->last_ts "
6502 "%" PRIu32
" p->tcpvars->ts %" PRIu32
" result "
6503 "%" PRId32
"", sender_stream->
last_ts,
ts, result);
6506 }
else if ((sender_stream->
last_ts != 0) &&
6509 SCLogDebug(
"packet is not valid sender_stream->last_pkt_ts "
6510 "%" PRIu32
" p->ts(sec) %" PRIu32
"",
6524 }
else if (ret == 0) {
6534 SCLogDebug(
"timestamp considered valid anyway");
6570 const TCPHdr *tcph = PacketGetTCP(p);
6585 SCLogDebug(
"ssn %p: pkt ACK %" PRIu32
" == stream last ACK %" PRIu32, ssn, ack,
6598 SCLogDebug(
"ACK %"PRIu32
" is before last_ack %"PRIu32
" - window "
6599 "%"PRIu32
" = %"PRIu32, ack, stream->
last_ack,
6622 SCLogDebug(
"default path leading to invalid: ACK %"PRIu32
", last_ack %"PRIu32
6635 const uint32_t progress)
6693 static void StreamTcpPseudoPacketCreateDetectLogFlush(
ThreadVars *
tv,
6716 np->
proto = IPPROTO_TCP;
6717 FlowReference(&np->
flow, f);
6727 DecodeSetNoPacketInspectionFlag(np);
6730 DecodeSetNoPayloadInspectionFlag(np);
6770 ip4h->
ip_len = htons(40);
6776 ip4h->s_ip_src.s_addr = f->
src.addr_data32[0];
6777 ip4h->s_ip_dst.s_addr = f->
dst.addr_data32[0];
6779 ip4h->s_ip_src.s_addr = f->
dst.addr_data32[0];
6780 ip4h->s_ip_dst.s_addr = f->
src.addr_data32[0];
6813 ip6h->s_ip6_vfc = 0x60;
6814 ip6h->s_ip6_flow = 0;
6815 ip6h->s_ip6_nxt = IPPROTO_TCP;
6816 ip6h->s_ip6_plen = htons(20);
6817 ip6h->s_ip6_hlim = 64;
6819 ip6h->s_ip6_src[0] = f->
src.addr_data32[0];
6820 ip6h->s_ip6_src[1] = f->
src.addr_data32[1];
6821 ip6h->s_ip6_src[2] = f->
src.addr_data32[2];
6822 ip6h->s_ip6_src[3] = f->
src.addr_data32[3];
6823 ip6h->s_ip6_dst[0] = f->
dst.addr_data32[0];
6824 ip6h->s_ip6_dst[1] = f->
dst.addr_data32[1];
6825 ip6h->s_ip6_dst[2] = f->
dst.addr_data32[2];
6826 ip6h->s_ip6_dst[3] = f->
dst.addr_data32[3];
6828 ip6h->s_ip6_src[0] = f->
dst.addr_data32[0];
6829 ip6h->s_ip6_src[1] = f->
dst.addr_data32[1];
6830 ip6h->s_ip6_src[2] = f->
dst.addr_data32[2];
6831 ip6h->s_ip6_src[3] = f->
dst.addr_data32[3];
6832 ip6h->s_ip6_dst[0] = f->
src.addr_data32[0];
6833 ip6h->s_ip6_dst[1] = f->
src.addr_data32[1];
6834 ip6h->s_ip6_dst[2] = f->
src.addr_data32[2];
6835 ip6h->s_ip6_dst[3] = f->
src.addr_data32[3];
6867 np->
ts = parent->
ts;
6875 FlowDeReference(&np->
flow);
6894 StreamTcpPseudoPacketCreateDetectLogFlush(
tv, stt, p, ssn, pq,
ts^0);
6895 StreamTcpPseudoPacketCreateDetectLogFlush(
tv, stt, p, ssn, pq,
ts^1);
6915 if (p->
flow == NULL)
6943 const uint8_t *seg_data;
6944 uint32_t seg_datalen;
6947 int ret = CallbackFunc(p, seg, data, seg_data, seg_datalen);
6975 if (p->
flow == NULL)
6989 if (server_node == NULL && client_node == NULL) {
6993 while (server_node != NULL || client_node != NULL) {
6994 const uint8_t *seg_data;
6995 uint32_t seg_datalen;
6996 if (server_node == NULL) {
7003 &client_stream->
sb, &client_node->
sbseg, &seg_data, &seg_datalen);
7004 ret = CallbackFunc(p, client_node, data, seg_data, seg_datalen);
7009 client_node = TCPSEG_RB_NEXT(client_node);
7010 }
else if (client_node == NULL) {
7017 &server_stream->
sb, &server_node->
sbseg, &seg_data, &seg_datalen);
7018 ret = CallbackFunc(p, server_node, data, seg_data, seg_datalen);
7023 server_node = TCPSEG_RB_NEXT(server_node);
7028 &client_stream->
sb, &client_node->
sbseg, &seg_data, &seg_datalen);
7029 ret = CallbackFunc(p, client_node, data, seg_data, seg_datalen);
7034 client_node = TCPSEG_RB_NEXT(client_node);
7037 &server_stream->
sb, &server_node->
sbseg, &seg_data, &seg_datalen);
7038 ret = CallbackFunc(p, server_node, data, seg_data, seg_datalen);
7043 server_node = TCPSEG_RB_NEXT(server_node);
7078 const char *tcp_state = NULL;
7084 tcp_state =
"syn_sent";
7087 tcp_state =
"syn_recv";
7090 tcp_state =
"established";
7093 tcp_state =
"fin_wait1";
7096 tcp_state =
"fin_wait2";
7099 tcp_state =
"time_wait";
7102 tcp_state =
"last_ack";
7105 tcp_state =
"close_wait";
7108 tcp_state =
"closing";
7111 tcp_state =
"closed";