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)
446 static inline bool StreamTcpInlineDropUrg(
void)
455 static int RandomGetWrap(
void)
461 }
while(r >= ULONG_MAX - (ULONG_MAX % RAND_MAX));
491 uint16_t rdrange = 10;
500 if ((
ConfGetInt(
"stream.max-sessions", &value)) == 1) {
502 "Number of concurrent sessions is now only limited by Flow and "
503 "TCP stream engine memcaps.");
506 if ((
ConfGetInt(
"stream.prealloc-sessions", &value)) == 1) {
513 if (
ConfGetNode(
"stream.prealloc-sessions") != NULL) {
521 SCLogConfig(
"stream \"prealloc-sessions\": %"PRIu32
" (per thread)",
525 const char *temp_stream_memcap_str;
526 if (
ConfGet(
"stream.memcap", &temp_stream_memcap_str) == 1) {
527 uint64_t stream_memcap_copy;
530 "from conf file - %s. Killing engine",
531 temp_stream_memcap_str);
545 (void)
ConfGetBool(
"stream.midstream", &imidstream);
553 (void)
ConfGetBool(
"stream.async-oneside", &async_oneside);
562 if ((
ConfGetBool(
"stream.checksum-validation", &csum)) == 1) {
574 "enabled" :
"disabled");
577 const char *temp_stream_inline_str;
578 if (
ConfGet(
"stream.inline", &temp_stream_inline_str) == 1) {
583 if (strcmp(temp_stream_inline_str,
"auto") == 0) {
587 }
else if (
ConfGetBool(
"stream.inline", &inl) == 1) {
606 ?
"enabled" :
"disabled");
610 if ((
ConfGetBool(
"stream.bypass", &bypass)) == 1) {
619 ?
"enabled" :
"disabled");
622 int drop_invalid = 0;
623 if ((
ConfGetBool(
"stream.drop-invalid", &drop_invalid)) == 1) {
624 if (drop_invalid == 1) {
631 const char *temp_urgpol = NULL;
632 if (
ConfGet(
"stream.reassembly.urgent.policy", &temp_urgpol) == 1 && temp_urgpol != NULL) {
633 if (strcmp(temp_urgpol,
"inline") == 0) {
635 }
else if (strcmp(temp_urgpol,
"drop") == 0) {
637 }
else if (strcmp(temp_urgpol,
"oob") == 0) {
639 }
else if (strcmp(temp_urgpol,
"gap") == 0) {
642 FatalError(
"stream.reassembly.urgent.policy: invalid value '%s'", temp_urgpol);
651 const char *temp_urgoobpol = NULL;
652 if (
ConfGet(
"stream.reassembly.urgent.oob-limit-policy", &temp_urgoobpol) == 1 &&
653 temp_urgoobpol != NULL) {
654 if (strcmp(temp_urgoobpol,
"inline") == 0) {
656 }
else if (strcmp(temp_urgoobpol,
"drop") == 0) {
658 }
else if (strcmp(temp_urgoobpol,
"gap") == 0) {
661 FatalError(
"stream.reassembly.urgent.oob-limit-policy: invalid value '%s'", temp_urgoobpol);
671 if ((
ConfGetInt(
"stream.max-syn-queued", &value)) == 1) {
672 if (value >= 0 && value <= 255) {
684 if ((
ConfGetInt(
"stream.max-synack-queued", &value)) == 1) {
685 if (value >= 0 && value <= 255) {
697 const char *temp_stream_reassembly_memcap_str;
698 if (
ConfGet(
"stream.reassembly.memcap", &temp_stream_reassembly_memcap_str) == 1) {
699 uint64_t stream_reassembly_memcap_copy;
701 &stream_reassembly_memcap_copy) < 0) {
703 "stream.reassembly.memcap "
704 "from conf file - %s. Killing engine",
705 temp_stream_reassembly_memcap_str);
715 SCLogConfig(
"stream.reassembly \"memcap\": %"PRIu64
"",
719 const char *temp_stream_reassembly_depth_str;
720 if (
ConfGet(
"stream.reassembly.depth", &temp_stream_reassembly_depth_str) == 1) {
724 "stream.reassembly.depth "
725 "from conf file - %s. Killing engine",
726 temp_stream_reassembly_depth_str);
738 if ((
ConfGetBool(
"stream.reassembly.randomize-chunk-size", &randomize)) == 0) {
746 const char *temp_rdrange;
747 if (
ConfGet(
"stream.reassembly.randomize-chunk-range", &temp_rdrange) == 1) {
750 "stream.reassembly.randomize-chunk-range "
751 "from conf file - %s. Killing engine",
754 }
else if (rdrange >= 100) {
755 FatalError(
"stream.reassembly.randomize-chunk-range "
756 "must be lower than 100");
761 const char *temp_stream_reassembly_toserver_chunk_size_str;
762 if (
ConfGet(
"stream.reassembly.toserver-chunk-size",
763 &temp_stream_reassembly_toserver_chunk_size_str) == 1) {
767 "stream.reassembly.toserver-chunk-size "
768 "from conf file - %s. Killing engine",
769 temp_stream_reassembly_toserver_chunk_size_str);
778 long int r = RandomGetWrap();
783 const char *temp_stream_reassembly_toclient_chunk_size_str;
784 if (
ConfGet(
"stream.reassembly.toclient-chunk-size",
785 &temp_stream_reassembly_toclient_chunk_size_str) == 1) {
789 "stream.reassembly.toclient-chunk-size "
790 "from conf file - %s. Killing engine",
791 temp_stream_reassembly_toclient_chunk_size_str);
800 long int r = RandomGetWrap();
806 SCLogConfig(
"stream.reassembly \"toserver-chunk-size\": %"PRIu16,
808 SCLogConfig(
"stream.reassembly \"toclient-chunk-size\": %"PRIu16,
813 if (
ConfGetBool(
"stream.reassembly.raw", &enable_raw) == 1) {
821 SCLogConfig(
"stream.reassembly.raw: %s", enable_raw ?
"enabled" :
"disabled");
825 int liberal_timestamps = 0;
826 if (
ConfGetBool(
"stream.liberal-timestamps", &liberal_timestamps) == 1) {
830 SCLogConfig(
"stream.liberal-timestamps: %s", liberal_timestamps ?
"enabled" :
"disabled");
850 StreamTcpSessionPoolAlloc,
851 StreamTcpSessionPoolInit, NULL,
852 StreamTcpSessionPoolCleanup, NULL);
871 SCLogDebug(
"ssn_pool_cnt %"PRIu64
"", ssn_pool_cnt);
874 static bool IsReassemblyMemcapExceptionPolicyStatsValid(
enum ExceptionPolicy exception_policy)
882 static bool IsStreamTcpSessionMemcapExceptionPolicyStatsValid(
enum ExceptionPolicy policy)
890 static void StreamTcpSsnMemcapExceptionPolicyStatsIncr(
934 if (
unlikely((g_eps_stream_ssn_memcap != UINT64_MAX &&
935 g_eps_stream_ssn_memcap ==
t_pcapcnt))) {
950 const TCPHdr *tcph = PacketGetTCP(p);
1009 if (PacketIsIPv4(p)) {
1019 }
else if (PacketIsIPv6(p)) {
1045 #define StreamTcpUpdateLastAck(ssn, stream, ack) { \
1046 if (SEQ_GT((ack), (stream)->last_ack)) \
1048 SCLogDebug("ssn %p: last_ack set to %"PRIu32", moved %u forward", (ssn), (ack), (ack) - (stream)->last_ack); \
1049 if ((SEQ_LEQ((stream)->last_ack, (stream)->next_seq) && SEQ_GT((ack),(stream)->next_seq))) { \
1050 SCLogDebug("last_ack just passed next_seq: %u (was %u) > %u", (ack), (stream)->last_ack, (stream)->next_seq); \
1052 SCLogDebug("next_seq (%u) <> last_ack now %d", (stream)->next_seq, (int)(stream)->next_seq - (ack)); \
1054 (stream)->last_ack = (ack); \
1055 StreamTcpSackPruneList((stream)); \
1057 SCLogDebug("ssn %p: no update: ack %u, last_ack %"PRIu32", next_seq %u (state %u)", \
1058 (ssn), (ack), (stream)->last_ack, (stream)->next_seq, (ssn)->state); \
1062 #define StreamTcpAsyncLastAckUpdate(ssn, stream) { \
1063 if ((ssn)->flags & STREAMTCP_FLAG_ASYNC) { \
1064 if (SEQ_GT((stream)->next_seq, (stream)->last_ack)) { \
1065 uint32_t ack_diff = (stream)->next_seq - (stream)->last_ack; \
1066 (stream)->last_ack += ack_diff; \
1067 SCLogDebug("ssn %p: ASYNC last_ack set to %"PRIu32", moved %u forward", \
1068 (ssn), (stream)->next_seq, ack_diff); \
1073 #define StreamTcpUpdateNextSeq(ssn, stream, seq) { \
1074 (stream)->next_seq = seq; \
1075 SCLogDebug("ssn %p: next_seq %" PRIu32, (ssn), (stream)->next_seq); \
1076 StreamTcpAsyncLastAckUpdate((ssn), (stream)); \
1086 #define StreamTcpUpdateNextWin(ssn, stream, win) { \
1087 uint32_t sacked_size__ = StreamTcpSackedSize((stream)); \
1088 if (SEQ_GT(((win) + sacked_size__), (stream)->next_win)) { \
1089 (stream)->next_win = ((win) + sacked_size__); \
1090 SCLogDebug("ssn %p: next_win set to %"PRIu32, (ssn), (stream)->next_win); \
1098 SCLogDebug(
"ssn %p: (state: %s) Reset received and state changed to "
1102 static bool IsMidstreamExceptionPolicyStatsValid(
enum ExceptionPolicy policy)
1116 static void StreamTcpMidstreamExceptionPolicyStatsIncr(
1125 static int StreamTcpPacketIsRetransmission(
TcpStream *stream,
Packet *p)
1130 const TCPHdr *tcph = PacketGetTCP(p);
1168 static int StreamTcpPacketStateNone(
1171 const TCPHdr *tcph = PacketGetTCP(p);
1174 SCLogDebug(
"RST packet received, no session setup");
1184 SCLogDebug(
"FIN packet received, no session setup");
1190 SCLogDebug(
"FIN packet received, no session setup");
1207 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1239 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
", "
1240 "ssn->server.next_win %" PRIu32
"",
1242 SCLogDebug(
"ssn %p: ssn->client.last_ack %" PRIu32
", "
1243 "ssn->server.last_ack %" PRIu32
"",
1251 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1252 "ssn->client.last_ts %" PRIu32
"",
1271 SCLogDebug(
"ssn %p: assuming SACK permitted for both sides", ssn);
1280 SCLogDebug(
"Midstream not enabled, so won't pick up a session");
1285 SCLogDebug(
"Midstream policy not permissive, so won't pick up a session");
1308 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1309 "TCP_SYN_RECV", ssn);
1340 SCLogDebug(
"ssn %p: wscale enabled. client %u server %u",
1344 SCLogDebug(
"ssn %p: ssn->client.isn %"PRIu32
", ssn->client.next_seq"
1345 " %"PRIu32
", ssn->client.last_ack %"PRIu32
"", ssn,
1348 SCLogDebug(
"ssn %p: ssn->server.isn %"PRIu32
", ssn->server.next_seq"
1349 " %"PRIu32
", ssn->server.last_ack %"PRIu32
"", ssn,
1358 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1359 "ssn->client.last_ts %" PRIu32
"", ssn,
1377 SCLogDebug(
"ssn %p: SYN/ACK with SACK permitted, assuming "
1378 "SACK permitted for both sides", ssn);
1396 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_SYN_SENT", ssn);
1429 SCLogDebug(
"ssn %p: SACK permitted on SYN packet", ssn);
1436 SCLogDebug(
"ssn: %p (TFO) isn %u base_seq %u next_seq %u payload len %u", ssn,
1443 SCLogDebug(
"ssn %p: ssn->client.isn %" PRIu32
", "
1444 "ssn->client.next_seq %" PRIu32
", ssn->client.last_ack "
1454 SCLogDebug(
"Midstream not enabled, so won't pick up a session");
1459 SCLogDebug(
"Midstream policy not permissive, so won't pick up a session");
1476 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1477 "TCP_ESTABLISHED", ssn);
1498 SCLogDebug(
"ssn %p: ssn->client.isn %u, ssn->client.next_seq %u",
1507 SCLogDebug(
"ssn %p: ssn->client.next_win %"PRIu32
", "
1508 "ssn->server.next_win %"PRIu32
"", ssn,
1510 SCLogDebug(
"ssn %p: ssn->client.last_ack %"PRIu32
", "
1511 "ssn->server.last_ack %"PRIu32
"", ssn,
1519 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1520 "ssn->client.last_ts %" PRIu32
"", ssn,
1539 SCLogDebug(
"ssn %p: assuming SACK permitted for both sides", ssn);
1553 const TCPHdr *tcph = PacketGetTCP(p);
1583 StreamTcp3whsSynAckToStateQueue(p, &search);
1591 search.
ts == q->
ts) {
1604 if (StreamTcp3whsFindSynAckBySynAck(ssn, p) != NULL)
1608 SCLogDebug(
"ssn %p: =~ SYN/ACK queue limit reached", ssn);
1614 SCLogDebug(
"ssn %p: =~ SYN/ACK queue failed: stream memcap reached", ssn);
1620 SCLogDebug(
"ssn %p: =~ SYN/ACK queue failed: alloc failed", ssn);
1625 StreamTcp3whsSynAckToStateQueue(p, q);
1639 const TCPHdr *tcph = PacketGetTCP(p);
1674 StreamTcp3whsSynAckToStateQueue(p, &update);
1681 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_SYN_RECV", ssn);
1697 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1698 "ssn->client.last_ts %" PRIu32
"", ssn,
1726 SCLogDebug(
"ssn %p: SACK permitted for session", ssn);
1733 SCLogDebug(
"ssn %p: ssn->server.next_win %" PRIu32
"", ssn,
1735 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
"", ssn,
1737 SCLogDebug(
"ssn %p: ssn->server.isn %" PRIu32
", "
1738 "ssn->server.next_seq %" PRIu32
", "
1739 "ssn->server.last_ack %" PRIu32
" "
1740 "(ssn->client.last_ack %" PRIu32
")", ssn,
1747 SCLogDebug(
"ssn %p: STREAMTCP_FLAG_4WHS unset, normal SYN/ACK"
1748 " so considering 3WHS", ssn);
1759 static inline bool StateSynSentValidateTimestamp(
TcpSession *ssn,
Packet *p)
1769 if (receiver_stream->
last_ts != 0 && ts_echo != 0 &&
1770 ts_echo != receiver_stream->
last_ts)
1772 SCLogDebug(
"ssn %p: BAD TSECR echo %u recv %u", ssn,
1773 ts_echo, receiver_stream->
last_ts);
1777 if (receiver_stream->
last_ts == 0 && ts_echo != 0) {
1778 SCLogDebug(
"ssn %p: BAD TSECR echo %u recv %u", ssn,
1779 ts_echo, receiver_stream->
last_ts);
1789 memset(q, 0,
sizeof(*q));
1809 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1815 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1819 memset(q, 0,
sizeof(*q));
1820 const TCPHdr *tcph = PacketGetTCP(p);
1838 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1845 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1852 memset(q, 0,
sizeof(*q));
1854 const TCPHdr *tcph = PacketGetTCP(p);
1871 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1881 SCLogDebug(
"ssn %p: search state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, s, s->
seq, s->
win,
1885 SCLogDebug(
"ssn %p: queue state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq,
1899 TcpStateQueueInitFromSsnSyn(ssn, &search);
1902 if (ssn->
queue != NULL && StreamTcp3whsFindSyn(ssn, &search) != NULL)
1906 SCLogDebug(
"ssn %p: =~ SYN queue limit reached", ssn);
1912 SCLogDebug(
"ssn %p: =~ SYN queue failed: stream memcap reached", ssn);
1918 SCLogDebug(
"ssn %p: =~ SYN queue failed: alloc failed", ssn);
1965 static int StreamTcpPacketStateSynSent(
1969 const TCPHdr *tcph = PacketGetTCP(p);
1975 SCLogDebug(
"ssn %p: SYN/ACK on SYN_SENT state for packet %" PRIu64, ssn, p->
pcap_cnt);
1982 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
1983 "%" PRIu32
" from stream",
1989 SCLogDebug(
"ssn %p: (TFO) ACK matches next_seq, packet ACK %" PRIu32
" == "
1990 "%" PRIu32
" from stream",
1993 SCLogDebug(
"ssn %p: (TFO) ACK matches ISN+1, packet ACK %" PRIu32
" == "
1994 "%" PRIu32
" from stream",
2002 SCLogDebug(
"ssn %p: (TFO) ACK mismatch, packet ACK %" PRIu32
" != "
2003 "%" PRIu32
" from stream",
2011 const bool ts_mismatch = !StateSynSentValidateTimestamp(ssn, p);
2016 TcpStateQueueInitFromPktSynAck(p, &search);
2018 const TcpStateQueue *q = StreamTcp3whsFindSyn(ssn, &search);
2024 SCLogDebug(
"ssn %p: found queued SYN state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u",
2028 StreamTcp3whsStoreSynApplyToSsn(ssn, q);
2038 StreamTcp3wsFreeQueue(ssn);
2040 StreamTcp3whsSynAckUpdate(ssn, p, NULL);
2047 SCLogDebug(
"ssn %p: SYN/ACK received in the wrong direction", ssn);
2051 SCLogDebug(
"ssn %p: SYN/ACK received on 4WHS session", ssn);
2058 SCLogDebug(
"ssn %p: 4WHS ACK mismatch, packet ACK %" PRIu32
""
2059 " != %" PRIu32
" from stream",
2069 SCLogDebug(
"ssn %p: 4WHS SEQ mismatch, packet SEQ %" PRIu32
""
2070 " != %" PRIu32
" from *first* SYN pkt",
2077 SCLogDebug(
"ssn %p: =~ 4WHS ssn state is now TCP_SYN_RECV", ssn);
2091 SCLogDebug(
"ssn %p: 4WHS ssn->client.last_ts %" PRIu32
" "
2092 "ssn->server.last_ts %" PRIu32
"",
2117 SCLogDebug(
"ssn %p: SACK permitted for 4WHS session", ssn);
2124 SCLogDebug(
"ssn %p: 4WHS ssn->client.isn %" PRIu32
", "
2125 "ssn->client.next_seq %" PRIu32
", "
2126 "ssn->client.last_ack %" PRIu32
" "
2127 "(ssn->server.last_ack %" PRIu32
")",
2136 if (StateSynSentValidateTimestamp(ssn, p) ==
false) {
2144 if (!StreamTcpValidateRst(ssn, p))
2151 SCLogDebug(
"ssn->server.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2153 StreamTcpCloseSsnWithReset(p, ssn);
2154 StreamTcp3wsFreeQueue(ssn);
2158 SCLogDebug(
"ssn->client.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2159 StreamTcpCloseSsnWithReset(p, ssn);
2160 StreamTcp3wsFreeQueue(ssn);
2168 SCLogDebug(
"ssn %p: SYN packet on state SYN_SENT... resent", ssn);
2170 SCLogDebug(
"ssn %p: SYN packet on state SYN_SENT... resent of "
2183 SCLogDebug(
"ssn %p: STREAMTCP_FLAG_4WHS flag set", ssn);
2220 SCLogDebug(
"ssn %p: 4WHS ssn->server.isn %" PRIu32
", "
2221 "ssn->server.next_seq %" PRIu32
", "
2222 "ssn->server.last_ack %"PRIu32
"", ssn,
2225 SCLogDebug(
"ssn %p: 4WHS ssn->client.isn %" PRIu32
", "
2226 "ssn->client.next_seq %" PRIu32
", "
2227 "ssn->client.last_ack %"PRIu32
"", ssn,
2236 TcpStateQueueInitFromPktSyn(p, &syn_pkt);
2237 TcpStateQueueInitFromSsnSyn(ssn, &syn_ssn);
2239 if (memcmp(&syn_pkt, &syn_ssn,
sizeof(
TcpStateQueue)) != 0) {
2241 StreamTcp3whsStoreSyn(ssn, p);
2242 SCLogDebug(
"ssn %p: Retransmitted SYN. Updating ssn from packet %" PRIu64
2243 ". Stored previous state",
2246 StreamTcp3whsStoreSynApplyToSsn(ssn, &syn_pkt);
2262 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
2263 "%" PRIu32
" from stream",
2270 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2271 StreamTcp3wsFreeQueue(ssn);
2284 SCLogDebug(
"ssn %p: synsent => Asynchronous stream, packet SEQ"
2285 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2286 "ssn->client.next_seq %" PRIu32
"",
2335 static int StreamTcpPacketStateSynRecv(
2339 const TCPHdr *tcph = PacketGetTCP(p);
2342 if (!StreamTcpValidateRst(ssn, p))
2359 SCLogDebug(
"Detection evasion has been attempted, so"
2360 " not resetting the connection !!");
2368 SCLogDebug(
"Detection evasion has been attempted, so"
2369 " not resetting the connection !!");
2375 StreamTcpCloseSsnWithReset(p, ssn);
2378 StreamTcpHandleTimestamp(ssn, p);
2385 if (!StreamTcpValidateTimestamp(ssn, p))
2389 if ((StreamTcpHandleFin(
tv, stt, ssn, p)) == -1)
2394 SCLogDebug(
"ssn %p: SYN/ACK packet on state SYN_RECV. resent", ssn);
2397 SCLogDebug(
"ssn %p: SYN/ACK-pkt to server in SYN_RECV state", ssn);
2406 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
2407 "%" PRIu32
" from stream",
2417 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
2418 "%" PRIu32
" from stream",
2421 if (StreamTcp3whsQueueSynAck(ssn, p) == -1)
2423 SCLogDebug(
"ssn %p: queued different SYN/ACK", ssn);
2427 SCLogDebug(
"ssn %p: SYN packet on state SYN_RECV... resent", ssn);
2430 SCLogDebug(
"ssn %p: SYN-pkt to client in SYN_RECV state", ssn);
2437 SCLogDebug(
"ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
2445 SCLogDebug(
"ssn %p: checking ACK against queued SYN/ACKs", ssn);
2448 SCLogDebug(
"ssn %p: here we update state against queued SYN/ACK", ssn);
2449 StreamTcp3whsSynAckUpdate(ssn, p, q);
2451 SCLogDebug(
"ssn %p: none found, now checking ACK against original SYN/ACK (state)", ssn);
2461 if (!(StreamTcpValidateTimestamp(ssn, p))) {
2467 SCLogDebug(
"ssn %p: ACK received on 4WHS session",ssn);
2470 SCLogDebug(
"ssn %p: 4WHS wrong seq nr on packet", ssn);
2475 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
2476 SCLogDebug(
"ssn %p: 4WHS invalid ack nr on packet", ssn);
2482 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
2483 "%" PRIu32
", ACK %" PRIu32
"",
2487 StreamTcpHandleTimestamp(ssn, p);
2496 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2500 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
", "
2501 "ssn->client.last_ack %"PRIu32
"", ssn,
2506 bool ack_indicates_missed_3whs_ack_packet =
false;
2516 SCLogDebug(
"ssn %p: ACK received on midstream SYN/ACK "
2517 "pickup session",ssn);
2520 SCLogDebug(
"ssn %p: ACK received on TFO session",ssn);
2537 SCLogDebug(
"ssn %p: possible data injection", ssn);
2542 SCLogDebug(
"ssn %p: ACK received in the wrong direction",
2547 ack_indicates_missed_3whs_ack_packet =
true;
2551 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ %" PRIu32
""
2552 ", ACK %" PRIu32
"",
2564 StreamTcpHandleTimestamp(ssn, p);
2588 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2614 StreamTcpHandleTimestamp(ssn, p);
2627 SCLogDebug(
"ssn %p: synrecv => Asynchronous stream, packet SEQ"
2628 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2629 "ssn->server.next_seq %" PRIu32,
2634 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2643 SCLogDebug(
"ssn %p: wrong ack nr on packet, possible evasion!!",
2653 SCLogDebug(
"ssn %p: ACK for missing data", ssn);
2656 StreamTcpHandleTimestamp(ssn, p);
2662 SCLogDebug(
"ssn %p: ACK for missing data: ssn->server.next_seq %u", ssn,
2672 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2681 SCLogDebug(
"ssn %p: ACK for missing data", ssn);
2684 StreamTcpHandleTimestamp(ssn, p);
2706 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2711 }
else if ((ack_indicates_missed_3whs_ack_packet ||
2715 if (ack_indicates_missed_3whs_ack_packet) {
2716 SCLogDebug(
"ssn %p: packet fits perfectly after a missed 3whs-ACK", ssn);
2718 SCLogDebug(
"ssn %p: (TFO) expected packet fits perfectly after SYN/ACK", ssn);
2727 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2732 SCLogDebug(
"ssn %p: wrong seq nr on packet", ssn);
2738 SCLogDebug(
"ssn %p: ssn->server.next_win %" PRIu32
", "
2739 "ssn->server.last_ack %"PRIu32
"", ssn,
2761 static int HandleEstablishedPacketToServer(
2764 const TCPHdr *tcph = PacketGetTCP(p);
2769 SCLogDebug(
"ssn %p: =+ pkt (%" PRIu32
") is to server: SEQ %" PRIu32
","
2770 "ACK %" PRIu32
", WIN %" PRIu16
"",
2776 SCLogDebug(
"ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
2779 }
else if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
2780 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
2788 SCLogDebug(
"ssn %p: pkt is keep alive", ssn);
2793 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ"
2794 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
2795 " ssn->client.last_ack %" PRIu32
", ssn->client.next_win"
2796 "%" PRIu32
"(%" PRIu32
")",
2806 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ."
2807 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2808 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2809 "%" PRIu32
"(%" PRIu32
")",
2821 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ"
2822 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2823 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2824 "%" PRIu32
"(%" PRIu32
")",
2839 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
2840 " before last_ack %" PRIu32
", after next_seq %" PRIu32
":"
2841 " acked data that we haven't seen before",
2844 SCLogDebug(
"ssn %p: server => SEQ before last_ack, packet SEQ"
2845 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2846 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2847 "%" PRIu32
"(%" PRIu32
")",
2851 SCLogDebug(
"ssn %p: rejecting because pkt before last_ack", ssn);
2857 int zerowindowprobe = 0;
2860 SCLogDebug(
"ssn %p: zero window probe", ssn);
2861 zerowindowprobe = 1;
2871 if (zerowindowprobe) {
2872 SCLogDebug(
"ssn %p: zero window probe, skipping oow check", ssn);
2875 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
2880 SCLogDebug(
"ssn %p: ssn->server.window %"PRIu32
"", ssn,
2897 StreamTcpHandleTimestamp(ssn, p);
2909 SCLogDebug(
"ssn %p: toserver => SEQ out of window, packet SEQ "
2910 "%" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
2911 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2912 "%" PRIu32
"(%" PRIu32
")",
2916 StreamTcpSackedSize(&ssn->
client));
2936 static int HandleEstablishedPacketToClient(
2939 const TCPHdr *tcph = PacketGetTCP(p);
2944 SCLogDebug(
"ssn %p: =+ pkt (%" PRIu32
") is to client: SEQ %" PRIu32
","
2945 " ACK %" PRIu32
", WIN %" PRIu16
"",
2951 SCLogDebug(
"ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
2954 }
else if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
2955 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
2969 SCLogDebug(
"ssn %p: adjusted midstream ssn->server.next_win to "
2975 SCLogDebug(
"ssn %p: pkt is keep alive", ssn);
2981 SCLogDebug(
"ssn %p: client => Asynchronous stream, packet SEQ"
2982 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
2983 " ssn->client.last_ack %" PRIu32
", ssn->client.next_win"
2984 " %" PRIu32
"(%" PRIu32
")",
2995 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
2996 " before last_ack %" PRIu32
", after next_seq %" PRIu32
":"
2997 " acked data that we haven't seen before",
3000 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
3001 " before last_ack %" PRIu32
". next_seq %" PRIu32,
3008 int zerowindowprobe = 0;
3011 SCLogDebug(
"ssn %p: zero window probe", ssn);
3012 zerowindowprobe = 1;
3023 if (zerowindowprobe) {
3024 SCLogDebug(
"ssn %p: zero window probe, skipping oow check", ssn);
3027 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
3031 SCLogDebug(
"ssn %p: ssn->client.window %"PRIu32
"", ssn,
3044 StreamTcpHandleTimestamp(ssn, p);
3053 SCLogDebug(
"ssn %p: client => SEQ out of window, packet SEQ"
3054 "%" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3055 " ssn->server.last_ack %" PRIu32
", ssn->server.next_win "
3056 "%" PRIu32
"(%" PRIu32
")",
3077 static inline uint32_t StreamTcpResetGetMaxAck(
TcpStream *stream, uint32_t
seq)
3083 if (
SEQ_GT(tail_seq, ack)) {
3091 static bool StreamTcpPacketIsZeroWindowProbeAck(
const TcpSession *ssn,
const Packet *p)
3093 const TCPHdr *tcph = PacketGetTCP(p);
3117 if (pkt_win != rcv->
window)
3124 SCLogDebug(
"ssn %p: packet %" PRIu64
" is a Zero Window Probe ACK", ssn, p->
pcap_cnt);
3131 static bool StreamTcpPacketIsDupAck(
const TcpSession *ssn,
const Packet *p)
3133 const TCPHdr *tcph = PacketGetTCP(p);
3151 if (pkt_win == 0 || rcv->
window == 0)
3153 if (pkt_win != rcv->
window)
3161 SCLogDebug(
"ssn %p: packet:%" PRIu64
" seq:%u ack:%u win:%u snd %u:%u:%u rcv %u:%u:%u", ssn,
3185 const TCPHdr *tcph = PacketGetTCP(p);
3236 static int StreamTcpPacketIsSpuriousRetransmission(
const TcpSession *ssn,
Packet *p)
3247 const TCPHdr *tcph = PacketGetTCP(p);
3253 "ssn %p: spurious retransmission; packet entirely before base_seq: SEQ %u(%u) "
3254 "last_ack %u base_seq %u",
3263 SCLogDebug(
"ssn %p: spurious retransmission; packet entirely before last_ack: SEQ %u(%u) "
3271 SCLogDebug(
"ssn %p: NOT spurious retransmission; packet NOT entirely before last_ack: SEQ "
3272 "%u(%u) last_ack %u, base_seq %u",
3289 static int StreamTcpPacketStateEstablished(
3293 const TCPHdr *tcph = PacketGetTCP(p);
3299 if (!StreamTcpValidateRst(ssn, p))
3303 StreamTcpCloseSsnWithReset(p, ssn);
3307 SCLogDebug(
"ssn %p: ssn->server.next_seq %" PRIu32
"", ssn,
3313 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, window));
3318 StreamTcpHandleTimestamp(ssn, p);
3322 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3330 StreamTcpCloseSsnWithReset(p, ssn);
3335 SCLogDebug(
"ssn %p: ssn->server.next_seq %" PRIu32
"", ssn,
3341 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
3346 StreamTcpHandleTimestamp(ssn, p);
3350 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3361 if (!StreamTcpValidateTimestamp(ssn, p))
3366 " %" PRIu32
", last ACK %" PRIu32
", next win %"PRIu32
","
3371 if ((StreamTcpHandleFin(
tv, stt, ssn, p)) == -1)
3376 SCLogDebug(
"ssn %p: SYN/ACK packet on state ESTABLISHED... resent",
3380 SCLogDebug(
"ssn %p: SYN/ACK-pkt to server in ESTABLISHED state", ssn);
3389 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
3390 "%" PRIu32
" from stream",
3400 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
3401 "%" PRIu32
" from stream",
3414 SCLogDebug(
"ssn %p: SYN/ACK packet on state ESTABLISHED... resent. "
3415 "Likely due server not receiving final ACK in 3whs", ssn);
3419 SCLogDebug(
"ssn %p: SYN packet on state ESTABLISHED... resent", ssn);
3421 SCLogDebug(
"ssn %p: SYN-pkt to client in EST state", ssn);
3428 SCLogDebug(
"ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
3449 if (!StreamTcpValidateTimestamp(ssn, p))
3455 HandleEstablishedPacketToServer(
tv, ssn, p, stt);
3457 SCLogDebug(
"ssn %p: next SEQ %" PRIu32
", last ACK %" PRIu32
","
3458 " next win %" PRIu32
", win %" PRIu32
"", ssn,
3465 SCLogDebug(
"3whs is now confirmed by server");
3469 HandleEstablishedPacketToClient(
tv, ssn, p, stt);
3471 SCLogDebug(
"ssn %p: next SEQ %" PRIu32
", last ACK %" PRIu32
","
3472 " next win %" PRIu32
", win %" PRIu32
"", ssn,
3497 const TCPHdr *tcph = PacketGetTCP(p);
3503 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ %" PRIu32
","
3507 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3508 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3514 SCLogDebug(
"ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn,
seq, pkt_re,
3519 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
" != "
3520 "%" PRIu32
" from stream",
3533 SCLogDebug(
"ssn %p: state changed to TCP_CLOSE_WAIT", ssn);
3538 SCLogDebug(
"ssn %p: ssn->client.next_seq %" PRIu32
"", ssn,
3543 StreamTcpHandleTimestamp(ssn, p);
3556 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK %" PRIu32
"",
3559 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ %" PRIu32
", "
3563 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3564 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3570 SCLogDebug(
"ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn,
seq, pkt_re,
3575 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
" != "
3576 "%" PRIu32
" from stream (last_ack %u win %u = %u)",
3585 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT1", ssn);
3594 StreamTcpHandleTimestamp(ssn, p);
3607 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK %" PRIu32
"",
3627 static int StreamTcpPacketStateFinWait1(
3631 const TCPHdr *tcph = PacketGetTCP(p);
3637 if (!StreamTcpValidateRst(ssn, p))
3640 StreamTcpCloseSsnWithReset(p, ssn);
3645 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, ack));
3650 StreamTcpHandleTimestamp(ssn, p);
3657 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
3662 StreamTcpHandleTimestamp(ssn, p);
3670 if (!StreamTcpValidateTimestamp(ssn, p))
3675 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3676 "%" PRIu32
", ACK %" PRIu32
"",
3678 int retransmission = 0;
3680 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
3681 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3687 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3688 " != %" PRIu32
" from stream",
3694 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3695 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3700 if (!retransmission) {
3702 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
3708 StreamTcpHandleTimestamp(ssn, p);
3724 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3728 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3729 "%" PRIu32
", ACK %" PRIu32
"",
3731 int retransmission = 0;
3733 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
3734 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3739 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3745 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3746 " != %" PRIu32
" from stream",
3752 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3753 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3759 StreamTcpHandleTimestamp(ssn, p);
3762 if (!retransmission) {
3764 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
3782 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3789 if (!StreamTcpValidateTimestamp(ssn, p))
3794 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3795 "%" PRIu32
", ACK %" PRIu32
"",
3797 int retransmission = 0;
3799 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
3800 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3806 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3807 " != %" PRIu32
" from stream",
3813 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3814 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3819 if (!retransmission) {
3821 SCLogDebug(
"ssn %p: state changed to TCP_CLOSING", ssn);
3827 StreamTcpHandleTimestamp(ssn, p);
3844 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3848 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3849 "%" PRIu32
", ACK %" PRIu32
"",
3852 int retransmission = 0;
3854 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
3855 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3861 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3862 " != %" PRIu32
" from stream",
3868 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3869 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3874 if (!retransmission) {
3876 SCLogDebug(
"ssn %p: state changed to TCP_CLOSING", ssn);
3882 StreamTcpHandleTimestamp(ssn, p);
3899 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3904 SCLogDebug(
"ssn (%p): SYN pkt on FinWait1", ssn);
3910 if (!StreamTcpValidateTimestamp(ssn, p))
3915 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3916 "%" PRIu32
", ACK %" PRIu32
"",
3918 int retransmission = 0;
3920 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
3921 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3926 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3927 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3934 "ssn %p: ACK's older segment as %u < %u", ssn, ack, ssn->
server.
next_seq);
3935 }
else if (!retransmission) {
3939 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
3945 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT2", ssn);
3948 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3949 " != %" PRIu32
" from stream",
3961 StreamTcpHandleTimestamp(ssn, p);
3982 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3988 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3989 "%" PRIu32
", ACK %" PRIu32
"",
3992 int retransmission = 0;
3994 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
3995 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4000 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4001 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4006 if (!retransmission) {
4009 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
4015 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT2", ssn);
4018 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4019 " != %" PRIu32
" from stream",
4029 StreamTcpHandleTimestamp(ssn, p);
4050 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4071 static int StreamTcpPacketStateFinWait2(
4075 const TCPHdr *tcph = PacketGetTCP(p);
4081 if (!StreamTcpValidateRst(ssn, p))
4084 StreamTcpCloseSsnWithReset(p, ssn);
4089 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, ack));
4094 StreamTcpHandleTimestamp(ssn, p);
4101 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
4106 StreamTcpHandleTimestamp(ssn, p);
4114 if (!StreamTcpValidateTimestamp(ssn, p))
4119 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4120 "%" PRIu32
", ACK %" PRIu32
"",
4122 int retransmission = 0;
4128 }
else if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4129 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4135 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ "
4136 "%" PRIu32
" != %" PRIu32
" from stream",
4142 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4143 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4148 if (!retransmission) {
4150 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4160 StreamTcpHandleTimestamp(ssn, p);
4173 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4177 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4178 "%" PRIu32
", ACK %" PRIu32
"",
4180 int retransmission = 0;
4186 }
else if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4187 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4193 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ "
4194 "%" PRIu32
" != %" PRIu32
" from stream",
4200 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4201 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4206 if (!retransmission) {
4208 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4214 StreamTcpHandleTimestamp(ssn, p);
4226 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4232 SCLogDebug(
"ssn (%p): SYN pkt on FinWait2", ssn);
4238 if (!StreamTcpValidateTimestamp(ssn, p))
4243 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4244 "%" PRIu32
", ACK %" PRIu32
"",
4246 int retransmission = 0;
4248 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4249 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4254 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4255 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4260 if (!retransmission) {
4263 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
4268 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4269 " != %" PRIu32
" from stream",
4279 StreamTcpHandleTimestamp(ssn, p);
4295 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4299 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4300 "%" PRIu32
", ACK %" PRIu32
"",
4302 int retransmission = 0;
4304 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4305 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4310 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4311 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4316 if (!retransmission) {
4319 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
4323 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4324 " != %" PRIu32
" from stream",
4334 StreamTcpHandleTimestamp(ssn, p);
4350 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4371 static int StreamTcpPacketStateClosing(
4375 const TCPHdr *tcph = PacketGetTCP(p);
4381 if (!StreamTcpValidateRst(ssn, p))
4384 StreamTcpCloseSsnWithReset(p, ssn);
4389 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, ack));
4394 StreamTcpHandleTimestamp(ssn, p);
4401 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
4406 StreamTcpHandleTimestamp(ssn, p);
4413 SCLogDebug(
"ssn (%p): SYN pkt on Closing", ssn);
4419 if (!StreamTcpValidateTimestamp(ssn, p))
4424 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4425 "%" PRIu32
", ACK %" PRIu32
"",
4427 int retransmission = 0;
4428 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4429 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4435 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4436 " != %" PRIu32
" from stream",
4442 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4443 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4448 if (!retransmission) {
4450 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4456 StreamTcpHandleTimestamp(ssn, p);
4466 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4470 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4471 "%" PRIu32
", ACK %" PRIu32
"",
4473 int retransmission = 0;
4474 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4475 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4481 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4482 " != %" PRIu32
" from stream",
4488 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4489 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4494 if (!retransmission) {
4496 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4502 StreamTcpHandleTimestamp(ssn, p);
4513 SCLogDebug(
"StreamTcpPacketStateClosing (%p): =+ next SEQ "
4514 "%" PRIu32
", last ACK %" PRIu32
"", ssn,
4534 static int StreamTcpPacketStateCloseWait(
4538 const TCPHdr *tcph = PacketGetTCP(p);
4546 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4547 "%" PRIu32
", ACK %" PRIu32
"",
4550 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4551 "%" PRIu32
", ACK %" PRIu32
"",
4556 if (!StreamTcpValidateRst(ssn, p))
4559 StreamTcpCloseSsnWithReset(p, ssn);
4564 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, ack));
4569 StreamTcpHandleTimestamp(ssn, p);
4576 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
4581 StreamTcpHandleTimestamp(ssn, p);
4589 if (!StreamTcpValidateTimestamp(ssn, p))
4594 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4595 "%" PRIu32
", ACK %" PRIu32
"",
4598 int retransmission = 0;
4599 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4600 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4605 if (!retransmission) {
4608 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4609 " != %" PRIu32
" from stream",
4616 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4617 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4624 if (!retransmission)
4628 StreamTcpHandleTimestamp(ssn, p);
4640 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4644 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4645 "%" PRIu32
", ACK %" PRIu32
"",
4648 int retransmission = 0;
4649 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4650 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4655 if (!retransmission) {
4658 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4659 " != %" PRIu32
" from stream",
4666 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4667 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4672 if (!retransmission) {
4674 SCLogDebug(
"ssn %p: state changed to TCP_LAST_ACK", ssn);
4680 StreamTcpHandleTimestamp(ssn, p);
4692 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4698 SCLogDebug(
"ssn (%p): SYN pkt on CloseWait", ssn);
4704 if (!StreamTcpValidateTimestamp(ssn, p))
4709 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4710 "%" PRIu32
", ACK %" PRIu32
"",
4713 int retransmission = 0;
4714 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4715 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4721 SCLogDebug(
"ssn %p: -> retransmission", ssn);
4726 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4727 " != %" PRIu32
" from stream",
4733 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4734 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4739 if (!retransmission) {
4744 StreamTcpHandleTimestamp(ssn, p);
4758 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4762 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4763 "%" PRIu32
", ACK %" PRIu32
"",
4765 int retransmission = 0;
4766 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4767 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4773 SCLogDebug(
"ssn %p: -> retransmission", ssn);
4778 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4779 " != %" PRIu32
" from stream",
4785 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4786 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4791 if (!retransmission) {
4796 StreamTcpHandleTimestamp(ssn, p);
4810 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4831 static int StreamTcpPacketStateLastAck(
4835 const TCPHdr *tcph = PacketGetTCP(p);
4841 if (!StreamTcpValidateRst(ssn, p))
4844 StreamTcpCloseSsnWithReset(p, ssn);
4849 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, ack));
4854 StreamTcpHandleTimestamp(ssn, p);
4861 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
4866 StreamTcpHandleTimestamp(ssn, p);
4874 SCLogDebug(
"ssn (%p): FIN pkt on LastAck", ssn);
4877 SCLogDebug(
"ssn (%p): SYN pkt on LastAck", ssn);
4883 if (!StreamTcpValidateTimestamp(ssn, p))
4888 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4889 "%" PRIu32
", ACK %" PRIu32
"",
4892 int retransmission = 0;
4893 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4894 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4899 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4900 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4905 if (!retransmission) {
4907 SCLogDebug(
"ssn %p: not updating state as packet is before next_seq", ssn);
4909 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4910 " != %" PRIu32
" from stream",
4916 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
4922 StreamTcpHandleTimestamp(ssn, p);
4933 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4954 static int StreamTcpPacketStateTimeWait(
4958 const TCPHdr *tcph = PacketGetTCP(p);
4964 if (!StreamTcpValidateRst(ssn, p))
4967 StreamTcpCloseSsnWithReset(p, ssn);
4972 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, ack));
4977 StreamTcpHandleTimestamp(ssn, p);
4984 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
4989 StreamTcpHandleTimestamp(ssn, p);
4999 SCLogDebug(
"ssn (%p): SYN pkt on TimeWait", ssn);
5005 if (!StreamTcpValidateTimestamp(ssn, p))
5010 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
5011 "%" PRIu32
", ACK %" PRIu32
"",
5013 int retransmission = 0;
5014 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
5015 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
5020 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5021 " != %" PRIu32
" from stream",
5027 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
5028 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5033 if (!retransmission) {
5035 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5041 StreamTcpHandleTimestamp(ssn, p);
5052 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5056 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
5057 "%" PRIu32
", ACK %" PRIu32
"",
5059 int retransmission = 0;
5060 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
5061 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
5066 SCLogDebug(
"ssn %p: -> retransmission", ssn);
5069 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5070 " != %" PRIu32
" from stream",
5077 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
5078 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5083 if (!retransmission) {
5085 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5091 StreamTcpHandleTimestamp(ssn, p);
5102 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5114 static int StreamTcpPacketStateClosed(
5119 const TCPHdr *tcph = PacketGetTCP(p);
5125 TcpStream *stream = NULL, *ostream = NULL;
5142 if (StreamTcpStateDispatch(
tv, p, stt, ssn, ssn->
pstate) < 0)
5157 const TCPHdr *tcph = PacketGetTCP(p);
5171 SCLogDebug(
"regular packet %"PRIu64
" from same sender as "
5172 "the previous RST. Looks like it injected!", p->
pcap_cnt);
5198 const TCPHdr *tcph = PacketGetTCP(p);
5203 TcpStream *stream = NULL, *ostream = NULL;
5214 if (ack == ostream->last_ack &&
seq == (stream->
next_seq - 1)) {
5230 TcpStream *stream = NULL, *ostream = NULL;
5241 const TCPHdr *tcph = PacketGetTCP(p);
5260 if (pkt_win != ostream->window)
5269 SCLogDebug(
"seq %u (%u), ack %u (%u) FLAG_KEEPALIVE: %s",
seq, stream->
next_seq, ack, ostream->last_ack,
5299 TcpStream *stream = NULL, *ostream = NULL;
5313 const TCPHdr *tcph = PacketGetTCP(p);
5332 if (pkt_win == ostream->window)
5335 if (ack == ostream->last_ack &&
seq == stream->
next_seq) {
5350 TcpStream *stream = NULL, *ostream = NULL;
5358 const TCPHdr *tcph = PacketGetTCP(p);
5375 SCLogDebug(
"%"PRIu64
", seq %u ack %u stream->next_seq %u ostream->next_seq %u",
5403 TcpStream *stream = NULL, *ostream = NULL;
5414 const TCPHdr *tcph = PacketGetTCP(p);
5430 if (pkt_win < ostream->window) {
5431 uint32_t diff = ostream->window - pkt_win;
5433 SEQ_GT(ack, ostream->next_seq) &&
5436 SCLogDebug(
"%"PRIu64
", pkt_win %u, stream win %u, diff %u, dsize %u",
5438 SCLogDebug(
"%"PRIu64
", pkt_win %u, stream win %u",
5439 p->
pcap_cnt, pkt_win, ostream->window);
5440 SCLogDebug(
"%"PRIu64
", seq %u ack %u ostream->next_seq %u ostream->last_ack %u, ostream->next_win %u, diff %u (%u)",
5441 p->
pcap_cnt,
seq, ack, ostream->next_seq, ostream->last_ack, ostream->next_win,
5442 ostream->next_seq - ostream->last_ack, stream->
next_seq - stream->
last_ack);
5449 uint32_t adiff = ack - ostream->last_ack;
5450 if (((pkt_win > 1024) && (diff > (adiff + 32))) ||
5451 ((pkt_win <= 1024) && (diff > adiff)))
5453 SCLogDebug(
"pkt ACK %u is %u bytes beyond last_ack %u, shrinks window by %u "
5454 "(allowing 32 bytes extra): pkt WIN %u", ack, adiff, ostream->last_ack, diff, pkt_win);
5455 SCLogDebug(
"%u - %u = %u (state %u)", diff, adiff, diff - adiff, ssn->
state);
5470 static inline int StreamTcpStateDispatch(
5478 SCLogDebug(
"packet received on TCP_SYN_SENT state");
5479 if (StreamTcpPacketStateSynSent(
tv, p, stt, ssn)) {
5484 SCLogDebug(
"packet received on TCP_SYN_RECV state");
5485 if (StreamTcpPacketStateSynRecv(
tv, p, stt, ssn)) {
5490 SCLogDebug(
"packet received on TCP_ESTABLISHED state");
5491 if (StreamTcpPacketStateEstablished(
tv, p, stt, ssn)) {
5496 SCLogDebug(
"packet received on TCP_FIN_WAIT1 state");
5497 if (StreamTcpPacketStateFinWait1(
tv, p, stt, ssn)) {
5502 SCLogDebug(
"packet received on TCP_FIN_WAIT2 state");
5503 if (StreamTcpPacketStateFinWait2(
tv, p, stt, ssn)) {
5508 SCLogDebug(
"packet received on TCP_CLOSING state");
5509 if (StreamTcpPacketStateClosing(
tv, p, stt, ssn)) {
5514 SCLogDebug(
"packet received on TCP_CLOSE_WAIT state");
5515 if (StreamTcpPacketStateCloseWait(
tv, p, stt, ssn)) {
5520 SCLogDebug(
"packet received on TCP_LAST_ACK state");
5521 if (StreamTcpPacketStateLastAck(
tv, p, stt, ssn)) {
5526 SCLogDebug(
"packet received on TCP_TIME_WAIT state");
5527 if (StreamTcpPacketStateTimeWait(
tv, p, stt, ssn)) {
5533 SCLogDebug(
"packet received on closed state");
5535 if (StreamTcpPacketStateClosed(
tv, p, stt, ssn)) {
5541 SCLogDebug(
"packet received on default state");
5577 const TCPHdr *tcph = PacketGetTCP(p);
5592 SCLogDebug(
"ssn %p: removing ASYNC flag as we have packets on both sides", ssn);
5612 if (StreamTcpCheckFlowDrops(p) == 1) {
5622 if (StreamTcpPacketStateNone(
tv, p, stt, ssn) == -1) {
5648 if (StreamTcpPacketIsKeepAlive(ssn, p) == 1) {
5651 if (StreamTcpPacketIsKeepAliveACK(ssn, p) == 1) {
5652 StreamTcpClearKeepAliveFlag(ssn, p);
5655 StreamTcpClearKeepAliveFlag(ssn, p);
5657 const bool is_zwp_ack = StreamTcpPacketIsZeroWindowProbeAck(ssn, p);
5668 if (StreamTcpPacketIsDupAck(ssn, p) ==
true) {
5675 if (StreamTcpPacketIsFinShutdownAck(ssn, p) == 0) {
5676 if (StreamTcpPacketIsWindowUpdate(ssn, p) == 0) {
5677 if (StreamTcpPacketIsBadWindowUpdate(ssn,p))
5679 if (StreamTcpPacketIsOutdatedAck(ssn, p))
5684 int ret = StreamTcpPacketIsSpuriousRetransmission(ssn, p);
5693 if (StreamTcpStateDispatch(
tv, p, stt, ssn, ssn->
state) < 0)
5697 StreamTcpPacketCheckPostRst(ssn, p);
5746 SCLogDebug(
"bypass as stream is dead and we have no rules");
5759 if (StreamTcpInlineDropInvalid()) {
5763 DecodeSetNoPayloadInspectionFlag(p);
5777 static inline int StreamTcpValidateChecksum(
Packet *p)
5785 const TCPHdr *tcph = PacketGetTCP(p);
5786 if (PacketIsIPv4(p)) {
5787 const IPV4Hdr *ip4h = PacketGetIPv4(p);
5788 p->
l4.
csum = TCPChecksum(ip4h->s_ip_addrs, (uint16_t *)tcph,
5791 }
else if (PacketIsIPv6(p)) {
5792 const IPV6Hdr *ip6h = PacketGetIPv6(p);
5793 p->
l4.
csum = TCPV6Checksum(ip6h->s_ip6_addrs, (uint16_t *)tcph,
5814 static int TcpSessionPacketIsStreamStarter(
const Packet *p)
5816 const TCPHdr *tcph = PacketGetTCP(p);
5839 static bool TcpSessionReuseDoneEnoughSyn(
const Packet *p,
const Flow *f,
const TcpSession *ssn)
5841 const TCPHdr *tcph = PacketGetTCP(p);
5846 SCLogDebug(
"steam starter packet %" PRIu64
", ssn %p null. Reuse.", p->
pcap_cnt, ssn);
5851 ", ssn %p. STREAMTCP_FLAG_TFO_DATA_IGNORED set. Reuse.",
5856 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.", p->
pcap_cnt, ssn);
5860 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5863 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5866 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
5876 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5879 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5882 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
5895 static bool TcpSessionReuseDoneEnoughSynAck(
const Packet *p,
const Flow *f,
const TcpSession *ssn)
5897 const TCPHdr *tcph = PacketGetTCP(p);
5900 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p null. No reuse.", p->
pcap_cnt, ssn);
5904 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.", p->
pcap_cnt, ssn);
5908 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5911 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5914 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
5924 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5927 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5930 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
5946 const TCPHdr *tcph = PacketGetTCP(p);
5948 return TcpSessionReuseDoneEnoughSyn(p, f, ssn);
5953 return TcpSessionReuseDoneEnoughSynAck(p, f, ssn);
5962 if (p->
proto == IPPROTO_TCP && PacketIsTCP(p)) {
5963 if (TcpSessionPacketIsStreamStarter(p) == 1) {
5964 if (TcpSessionReuseDoneEnough(p, f, tcp_ssn) == 1) {
5987 if (!(PacketIsTCP(p))) {
5991 HandleThreadId(
tv, p, stt);
5997 if (StreamTcpValidateChecksum(p) == 0) {
6023 *data = (
void *)stt;
6032 IsStreamTcpSessionMemcapExceptionPolicyStatsValid);
6041 "tcp.midstream_exception_policy.", IsMidstreamExceptionPolicyStatsValid);
6045 "tcp.midstream_exception_policy.", IsMidstreamExceptionPolicyStatsValid);
6060 "tcp.reassembly_exception_policy.", IsReassemblyMemcapExceptionPolicyStatsValid);
6074 SCLogDebug(
"StreamTcp thread specific ctx online at %p, reassembly ctx %p",
6083 StreamTcpSessionPoolAlloc,
6084 StreamTcpSessionPoolInit, NULL,
6085 StreamTcpSessionPoolCleanup, NULL);
6095 SCLogError(
"failed to setup/expand stream session pool. Expand stream.memcap?");
6140 const TCPHdr *tcph = PacketGetTCP(p);
6148 if (!StreamTcpValidateTimestamp(ssn, p)) {
6177 StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
6178 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
6190 StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
6191 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
6204 receiver_stream = &ssn->
server;
6206 receiver_stream = &ssn->
client;
6208 SCLogDebug(
"ssn %p: setting STREAMTCP_STREAM_FLAG_RST_RECV on receiver stream", ssn);
6228 switch (os_policy) {
6235 SCLogDebug(
"reset is not Valid! Packet SEQ: %" PRIu32
" "
6236 "and server SEQ: %" PRIu32
"",
6245 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" "
6246 "and client SEQ: %" PRIu32
"",
6263 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6264 " server SEQ: %" PRIu32
"",
6276 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6277 " client SEQ: %" PRIu32
"",
6298 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" "
6299 "and server SEQ: %" PRIu32
"",
6305 SCLogDebug(
"reset is valid! Packet SEQ: %" PRIu32
" Stream %u",
seq,
6309 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6310 " client SEQ: %" PRIu32
"",
6341 uint8_t check_ts = 1;
6342 const TCPHdr *tcph = PacketGetTCP(p);
6346 sender_stream = &ssn->
client;
6347 receiver_stream = &ssn->
server;
6349 sender_stream = &ssn->
server;
6350 receiver_stream = &ssn->
client;
6361 uint32_t last_pkt_ts = sender_stream->
last_pkt_ts;
6362 uint32_t last_ts = sender_stream->
last_ts;
6412 SCLogDebug(
"ts %"PRIu32
", last_ts %"PRIu32
"",
ts, last_ts);
6416 result = (int32_t) ((
ts - last_ts) + 1);
6418 result = (int32_t) (
ts - last_ts);
6421 SCLogDebug(
"result %" PRIi32
", p->ts(secs) %" PRIuMAX
"", result,
6424 if (last_pkt_ts == 0 &&
6432 "%" PRIu32
" p->tcpvars->ts %" PRIu32
" result "
6433 "%" PRId32
"", last_ts,
ts, result);
6436 }
else if ((sender_stream->
last_ts != 0) &&
6438 SCLogDebug(
"packet is not valid last_pkt_ts "
6439 "%" PRIu32
" p->ts(sec) %" PRIu32
"",
6451 SCLogDebug(
"timestamp considered valid anyway");
6483 uint8_t check_ts = 1;
6484 const TCPHdr *tcph = PacketGetTCP(p);
6488 sender_stream = &ssn->
client;
6489 receiver_stream = &ssn->
server;
6491 sender_stream = &ssn->
server;
6492 receiver_stream = &ssn->
client;
6560 result = (int32_t) ((
ts - sender_stream->
last_ts) + 1);
6562 result = (int32_t) (
ts - sender_stream->
last_ts);
6565 SCLogDebug(
"result %" PRIi32
", p->ts(sec) %" PRIuMAX
"", result,
6575 SCLogDebug(
"timestamp is not valid sender_stream->last_ts "
6576 "%" PRIu32
" p->tcpvars->ts %" PRIu32
" result "
6577 "%" PRId32
"", sender_stream->
last_ts,
ts, result);
6580 }
else if ((sender_stream->
last_ts != 0) &&
6583 SCLogDebug(
"packet is not valid sender_stream->last_pkt_ts "
6584 "%" PRIu32
" p->ts(sec) %" PRIu32
"",
6598 }
else if (ret == 0) {
6608 SCLogDebug(
"timestamp considered valid anyway");
6644 const TCPHdr *tcph = PacketGetTCP(p);
6659 SCLogDebug(
"ssn %p: pkt ACK %" PRIu32
" == stream last ACK %" PRIu32, ssn, ack,
6672 SCLogDebug(
"ACK %"PRIu32
" is before last_ack %"PRIu32
" - window "
6673 "%"PRIu32
" = %"PRIu32, ack, stream->
last_ack,
6696 SCLogDebug(
"default path leading to invalid: ACK %"PRIu32
", last_ack %"PRIu32
6709 const uint32_t progress)
6767 static void StreamTcpPseudoPacketCreateDetectLogFlush(
ThreadVars *
tv,
6790 np->
proto = IPPROTO_TCP;
6791 FlowReference(&np->
flow, f);
6801 DecodeSetNoPacketInspectionFlag(np);
6804 DecodeSetNoPayloadInspectionFlag(np);
6844 ip4h->
ip_len = htons(40);
6850 ip4h->s_ip_src.s_addr = f->
src.addr_data32[0];
6851 ip4h->s_ip_dst.s_addr = f->
dst.addr_data32[0];
6853 ip4h->s_ip_src.s_addr = f->
dst.addr_data32[0];
6854 ip4h->s_ip_dst.s_addr = f->
src.addr_data32[0];
6887 ip6h->s_ip6_vfc = 0x60;
6888 ip6h->s_ip6_flow = 0;
6889 ip6h->s_ip6_nxt = IPPROTO_TCP;
6890 ip6h->s_ip6_plen = htons(20);
6891 ip6h->s_ip6_hlim = 64;
6893 ip6h->s_ip6_src[0] = f->
src.addr_data32[0];
6894 ip6h->s_ip6_src[1] = f->
src.addr_data32[1];
6895 ip6h->s_ip6_src[2] = f->
src.addr_data32[2];
6896 ip6h->s_ip6_src[3] = f->
src.addr_data32[3];
6897 ip6h->s_ip6_dst[0] = f->
dst.addr_data32[0];
6898 ip6h->s_ip6_dst[1] = f->
dst.addr_data32[1];
6899 ip6h->s_ip6_dst[2] = f->
dst.addr_data32[2];
6900 ip6h->s_ip6_dst[3] = f->
dst.addr_data32[3];
6902 ip6h->s_ip6_src[0] = f->
dst.addr_data32[0];
6903 ip6h->s_ip6_src[1] = f->
dst.addr_data32[1];
6904 ip6h->s_ip6_src[2] = f->
dst.addr_data32[2];
6905 ip6h->s_ip6_src[3] = f->
dst.addr_data32[3];
6906 ip6h->s_ip6_dst[0] = f->
src.addr_data32[0];
6907 ip6h->s_ip6_dst[1] = f->
src.addr_data32[1];
6908 ip6h->s_ip6_dst[2] = f->
src.addr_data32[2];
6909 ip6h->s_ip6_dst[3] = f->
src.addr_data32[3];
6941 np->
ts = parent->
ts;
6949 FlowDeReference(&np->
flow);
6968 StreamTcpPseudoPacketCreateDetectLogFlush(
tv, stt, p, ssn, pq,
ts^0);
6969 StreamTcpPseudoPacketCreateDetectLogFlush(
tv, stt, p, ssn, pq,
ts^1);
6989 if (p->
flow == NULL)
7017 const uint8_t *seg_data;
7018 uint32_t seg_datalen;
7021 int ret = CallbackFunc(p, seg, data, seg_data, seg_datalen);
7049 if (p->
flow == NULL)
7063 if (server_node == NULL && client_node == NULL) {
7067 while (server_node != NULL || client_node != NULL) {
7068 const uint8_t *seg_data;
7069 uint32_t seg_datalen;
7070 if (server_node == NULL) {
7077 &client_stream->
sb, &client_node->
sbseg, &seg_data, &seg_datalen);
7078 ret = CallbackFunc(p, client_node, data, seg_data, seg_datalen);
7083 client_node = TCPSEG_RB_NEXT(client_node);
7084 }
else if (client_node == NULL) {
7091 &server_stream->
sb, &server_node->
sbseg, &seg_data, &seg_datalen);
7092 ret = CallbackFunc(p, server_node, data, seg_data, seg_datalen);
7097 server_node = TCPSEG_RB_NEXT(server_node);
7102 &client_stream->
sb, &client_node->
sbseg, &seg_data, &seg_datalen);
7103 ret = CallbackFunc(p, client_node, data, seg_data, seg_datalen);
7108 client_node = TCPSEG_RB_NEXT(client_node);
7111 &server_stream->
sb, &server_node->
sbseg, &seg_data, &seg_datalen);
7112 ret = CallbackFunc(p, server_node, data, seg_data, seg_datalen);
7117 server_node = TCPSEG_RB_NEXT(server_node);
7152 const char *tcp_state = NULL;
7158 tcp_state =
"syn_sent";
7161 tcp_state =
"syn_recv";
7164 tcp_state =
"established";
7167 tcp_state =
"fin_wait1";
7170 tcp_state =
"fin_wait2";
7173 tcp_state =
"time_wait";
7176 tcp_state =
"last_ack";
7179 tcp_state =
"close_wait";
7182 tcp_state =
"closing";
7185 tcp_state =
"closed";