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
93 #define STREAM_DEPTH_DEFAULT 1024 * 1024
109 .valid_settings_ips = {
137 .valid_settings_ips = {
165 .valid_settings_ips = {
193 .valid_settings_ips = {
217 static int StreamTcpStateDispatch(
224 #if defined(DEBUG) || defined(QA_SIMULATION)
225 static uint64_t ssn_pool_cnt = 0;
226 extern thread_local uint64_t t_pcapcnt;
246 #if defined(DEBUG_VALIDATION) && defined(UNITTESTS)
249 BUG_ON(presize > UINT_MAX);
255 #if defined(DEBUG_VALIDATION) && defined(UNITTESTS)
258 BUG_ON(postsize > presize);
279 if (memcapcopy == 0 || size +
SC_ATOMIC_GET(st_memuse) <= memcapcopy)
291 if (size == 0 || (uint64_t)
SC_ATOMIC_GET(st_memuse) < size) {
312 if (stream != NULL) {
319 static void StreamTcp3wsFreeQueue(
TcpSession *ssn)
346 StreamTcp3wsFreeQueue(ssn);
407 static void *StreamTcpSessionPoolAlloc(
void)
421 static int StreamTcpSessionPoolInit(
void *data,
void* initdata)
431 static void StreamTcpSessionPoolCleanup(
void *s)
445 static inline bool StreamTcpInlineDropInvalid(
void)
456 static inline bool StreamTcpInlineDropUrg(
void)
465 static int RandomGetWrap(
void)
471 }
while(r >= ULONG_MAX - (ULONG_MAX % RAND_MAX));
501 uint16_t rdrange = 10;
510 if ((
SCConfGetInt(
"stream.max-sessions", &value)) == 1) {
512 "Number of concurrent sessions is now only limited by Flow and "
513 "TCP stream engine memcaps.");
516 if ((
SCConfGetInt(
"stream.prealloc-sessions", &value)) == 1) {
531 SCLogConfig(
"stream \"prealloc-sessions\": %"PRIu32
" (per thread)",
535 const char *temp_stream_memcap_str;
536 if (
SCConfGet(
"stream.memcap", &temp_stream_memcap_str) == 1) {
537 uint64_t stream_memcap_copy;
540 "from conf file - %s. Killing engine",
541 temp_stream_memcap_str);
572 if ((
SCConfGetBool(
"stream.checksum-validation", &csum)) == 1) {
584 "enabled" :
"disabled");
587 const char *temp_stream_inline_str;
588 if (
SCConfGet(
"stream.inline", &temp_stream_inline_str) == 1) {
593 if (strcmp(temp_stream_inline_str,
"auto") == 0) {
616 ?
"enabled" :
"disabled");
629 ?
"enabled" :
"disabled");
632 int drop_invalid = 0;
633 if ((
SCConfGetBool(
"stream.drop-invalid", &drop_invalid)) == 1) {
634 if (drop_invalid == 1) {
641 const char *temp_urgpol = NULL;
642 if (
SCConfGet(
"stream.reassembly.urgent.policy", &temp_urgpol) == 1 && temp_urgpol != NULL) {
643 if (strcmp(temp_urgpol,
"inline") == 0) {
645 }
else if (strcmp(temp_urgpol,
"drop") == 0) {
647 }
else if (strcmp(temp_urgpol,
"oob") == 0) {
649 }
else if (strcmp(temp_urgpol,
"gap") == 0) {
652 FatalError(
"stream.reassembly.urgent.policy: invalid value '%s'", temp_urgpol);
661 const char *temp_urgoobpol = NULL;
662 if (
SCConfGet(
"stream.reassembly.urgent.oob-limit-policy", &temp_urgoobpol) == 1 &&
663 temp_urgoobpol != NULL) {
664 if (strcmp(temp_urgoobpol,
"inline") == 0) {
666 }
else if (strcmp(temp_urgoobpol,
"drop") == 0) {
668 }
else if (strcmp(temp_urgoobpol,
"gap") == 0) {
671 FatalError(
"stream.reassembly.urgent.oob-limit-policy: invalid value '%s'", temp_urgoobpol);
681 if ((
SCConfGetInt(
"stream.max-syn-queued", &value)) == 1) {
682 if (value >= 0 && value <= 255) {
694 if ((
SCConfGetInt(
"stream.max-synack-queued", &value)) == 1) {
695 if (value >= 0 && value <= 255) {
707 const char *temp_stream_reassembly_memcap_str;
708 if (
SCConfGet(
"stream.reassembly.memcap", &temp_stream_reassembly_memcap_str) == 1) {
709 uint64_t stream_reassembly_memcap_copy;
711 &stream_reassembly_memcap_copy) < 0) {
713 "stream.reassembly.memcap "
714 "from conf file - %s. Killing engine",
715 temp_stream_reassembly_memcap_str);
725 SCLogConfig(
"stream.reassembly \"memcap\": %"PRIu64
"",
729 const char *temp_stream_reassembly_depth_str;
730 if (
SCConfGet(
"stream.reassembly.depth", &temp_stream_reassembly_depth_str) == 1) {
734 "stream.reassembly.depth "
735 "from conf file - %s. Killing engine",
736 temp_stream_reassembly_depth_str);
748 if ((
SCConfGetBool(
"stream.reassembly.randomize-chunk-size", &randomize)) == 0) {
756 const char *temp_rdrange;
757 if (
SCConfGet(
"stream.reassembly.randomize-chunk-range", &temp_rdrange) == 1) {
760 "stream.reassembly.randomize-chunk-range "
761 "from conf file - %s. Killing engine",
764 }
else if (rdrange >= 100) {
765 FatalError(
"stream.reassembly.randomize-chunk-range "
766 "must be lower than 100");
771 const char *temp_stream_reassembly_toserver_chunk_size_str;
772 if (
SCConfGet(
"stream.reassembly.toserver-chunk-size",
773 &temp_stream_reassembly_toserver_chunk_size_str) == 1) {
777 "stream.reassembly.toserver-chunk-size "
778 "from conf file - %s. Killing engine",
779 temp_stream_reassembly_toserver_chunk_size_str);
788 long int r = RandomGetWrap();
793 const char *temp_stream_reassembly_toclient_chunk_size_str;
794 if (
SCConfGet(
"stream.reassembly.toclient-chunk-size",
795 &temp_stream_reassembly_toclient_chunk_size_str) == 1) {
799 "stream.reassembly.toclient-chunk-size "
800 "from conf file - %s. Killing engine",
801 temp_stream_reassembly_toclient_chunk_size_str);
810 long int r = RandomGetWrap();
816 SCLogConfig(
"stream.reassembly \"toserver-chunk-size\": %"PRIu16,
818 SCLogConfig(
"stream.reassembly \"toclient-chunk-size\": %"PRIu16,
823 if (
SCConfGetBool(
"stream.reassembly.raw", &enable_raw) == 1) {
831 SCLogConfig(
"stream.reassembly.raw: %s", enable_raw ?
"enabled" :
"disabled");
835 int liberal_timestamps = 0;
836 if (
SCConfGetBool(
"stream.liberal-timestamps", &liberal_timestamps) == 1) {
840 SCLogConfig(
"stream.liberal-timestamps: %s", liberal_timestamps ?
"enabled" :
"disabled");
860 StreamTcpSessionPoolAlloc,
861 StreamTcpSessionPoolInit, NULL,
862 StreamTcpSessionPoolCleanup, NULL);
881 SCLogDebug(
"ssn_pool_cnt %"PRIu64
"", ssn_pool_cnt);
884 static bool IsReassemblyMemcapExceptionPolicyStatsValid(
enum ExceptionPolicy exception_policy)
892 static bool IsStreamTcpSessionMemcapExceptionPolicyStatsValid(
enum ExceptionPolicy policy)
900 static void StreamTcpSsnMemcapExceptionPolicyStatsIncr(
953 #if defined(DEBUG) || defined(QA_SIMULATION)
959 if (
unlikely((g_eps_stream_ssn_memcap != UINT64_MAX &&
960 g_eps_stream_ssn_memcap == t_pcapcnt))) {
961 SCLogNotice(
"simulating memcap reached condition for packet %" PRIu64, t_pcapcnt);
976 const TCPHdr *tcph = PacketGetTCP(p);
1010 switch(ssn->
state) {
1035 if (PacketIsIPv4(p)) {
1045 }
else if (PacketIsIPv6(p)) {
1071 #define StreamTcpUpdateLastAck(ssn, stream, ack) \
1073 if (SEQ_GT((ack), (stream)->last_ack) && SEQ_GT(ack, (stream)->base_seq)) { \
1074 SCLogDebug("ssn %p: last_ack set to %" PRIu32 ", moved %u forward", (ssn), (ack), \
1075 (ack) - (stream)->last_ack); \
1076 if ((SEQ_LEQ((stream)->last_ack, (stream)->next_seq) && \
1077 SEQ_GT((ack), (stream)->next_seq))) { \
1078 SCLogDebug("last_ack just passed next_seq: %u (was %u) > %u", (ack), \
1079 (stream)->last_ack, (stream)->next_seq); \
1081 SCLogDebug("next_seq (%u) <> last_ack now %d", (stream)->next_seq, \
1082 (int)(stream)->next_seq - (ack)); \
1084 (stream)->last_ack = (ack); \
1085 StreamTcpSackPruneList((stream)); \
1087 SCLogDebug("ssn %p: no update: ack %u, last_ack %" PRIu32 ", next_seq %u (state %u)", \
1088 (ssn), (ack), (stream)->last_ack, (stream)->next_seq, (ssn)->state); \
1092 #define StreamTcpAsyncLastAckUpdate(ssn, stream) { \
1093 if ((ssn)->flags & STREAMTCP_FLAG_ASYNC) { \
1094 if (SEQ_GT((stream)->next_seq, (stream)->last_ack)) { \
1095 uint32_t ack_diff = (stream)->next_seq - (stream)->last_ack; \
1096 (stream)->last_ack += ack_diff; \
1097 SCLogDebug("ssn %p: ASYNC last_ack set to %"PRIu32", moved %u forward", \
1098 (ssn), (stream)->next_seq, ack_diff); \
1103 #define StreamTcpUpdateNextSeq(ssn, stream, seq) { \
1104 (stream)->next_seq = seq; \
1105 SCLogDebug("ssn %p: next_seq %" PRIu32, (ssn), (stream)->next_seq); \
1106 StreamTcpAsyncLastAckUpdate((ssn), (stream)); \
1116 #define StreamTcpUpdateNextWin(ssn, stream, win) { \
1117 uint32_t sacked_size__ = StreamTcpSackedSize((stream)); \
1118 if (SEQ_GT(((win) + sacked_size__), (stream)->next_win)) { \
1119 (stream)->next_win = ((win) + sacked_size__); \
1120 SCLogDebug("ssn %p: next_win set to %"PRIu32, (ssn), (stream)->next_win); \
1128 SCLogDebug(
"ssn %p: (state: %s) Reset received and state changed to "
1132 static bool IsMidstreamExceptionPolicyStatsValid(
enum ExceptionPolicy policy)
1146 static void StreamTcpMidstreamExceptionPolicyStatsIncr(
1155 static int StreamTcpPacketIsRetransmission(
TcpStream *stream,
Packet *p)
1160 const TCPHdr *tcph = PacketGetTCP(p);
1198 static int StreamTcpPacketStateNone(
1201 const TCPHdr *tcph = PacketGetTCP(p);
1204 SCLogDebug(
"RST packet received, no session setup");
1214 SCLogDebug(
"FIN packet received, no session setup");
1220 SCLogDebug(
"FIN packet received, no session setup");
1237 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1269 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
", "
1270 "ssn->server.next_win %" PRIu32
"",
1272 SCLogDebug(
"ssn %p: ssn->client.last_ack %" PRIu32
", "
1273 "ssn->server.last_ack %" PRIu32
"",
1281 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1282 "ssn->client.last_ts %" PRIu32
"",
1301 SCLogDebug(
"ssn %p: assuming SACK permitted for both sides", ssn);
1310 SCLogDebug(
"Midstream not enabled, so won't pick up a session");
1315 SCLogDebug(
"Midstream policy not permissive, so won't pick up a session");
1338 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1339 "TCP_SYN_RECV", ssn);
1370 SCLogDebug(
"ssn %p: wscale enabled. client %u server %u",
1374 SCLogDebug(
"ssn %p: ssn->client.isn %"PRIu32
", ssn->client.next_seq"
1375 " %"PRIu32
", ssn->client.last_ack %"PRIu32
"", ssn,
1378 SCLogDebug(
"ssn %p: ssn->server.isn %"PRIu32
", ssn->server.next_seq"
1379 " %"PRIu32
", ssn->server.last_ack %"PRIu32
"", ssn,
1388 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1389 "ssn->client.last_ts %" PRIu32
"", ssn,
1407 SCLogDebug(
"ssn %p: SYN/ACK with SACK permitted, assuming "
1408 "SACK permitted for both sides", ssn);
1426 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_SYN_SENT", ssn);
1459 SCLogDebug(
"ssn %p: SACK permitted on SYN packet", ssn);
1466 SCLogDebug(
"ssn: %p (TFO) isn %u base_seq %u next_seq %u payload len %u", ssn,
1474 SCLogDebug(
"ssn %p: ssn->client.isn %" PRIu32
", "
1475 "ssn->client.next_seq %" PRIu32
", ssn->client.last_ack "
1485 SCLogDebug(
"Midstream not enabled, so won't pick up a session");
1490 SCLogDebug(
"Midstream policy not permissive, so won't pick up a session");
1507 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1508 "TCP_ESTABLISHED", ssn);
1529 SCLogDebug(
"ssn %p: ssn->client.isn %u, ssn->client.next_seq %u",
1538 SCLogDebug(
"ssn %p: ssn->client.next_win %"PRIu32
", "
1539 "ssn->server.next_win %"PRIu32
"", ssn,
1541 SCLogDebug(
"ssn %p: ssn->client.last_ack %"PRIu32
", "
1542 "ssn->server.last_ack %"PRIu32
"", ssn,
1550 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1551 "ssn->client.last_ts %" PRIu32
"", ssn,
1570 SCLogDebug(
"ssn %p: assuming SACK permitted for both sides", ssn);
1584 const TCPHdr *tcph = PacketGetTCP(p);
1614 StreamTcp3whsSynAckToStateQueue(p, &search);
1622 search.
ts == q->
ts) {
1635 if (StreamTcp3whsFindSynAckBySynAck(ssn, p) != NULL)
1639 SCLogDebug(
"ssn %p: =~ SYN/ACK queue limit reached", ssn);
1645 SCLogDebug(
"ssn %p: =~ SYN/ACK queue failed: stream memcap reached", ssn);
1651 SCLogDebug(
"ssn %p: =~ SYN/ACK queue failed: alloc failed", ssn);
1656 StreamTcp3whsSynAckToStateQueue(p, q);
1670 const TCPHdr *tcph = PacketGetTCP(p);
1705 StreamTcp3whsSynAckToStateQueue(p, &update);
1712 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_SYN_RECV", ssn);
1728 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1729 "ssn->client.last_ts %" PRIu32
"", ssn,
1757 SCLogDebug(
"ssn %p: SACK permitted for session", ssn);
1764 SCLogDebug(
"ssn %p: ssn->server.next_win %" PRIu32
"", ssn,
1766 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
"", ssn,
1768 SCLogDebug(
"ssn %p: ssn->server.isn %" PRIu32
", "
1769 "ssn->server.next_seq %" PRIu32
", "
1770 "ssn->server.last_ack %" PRIu32
" "
1771 "(ssn->client.last_ack %" PRIu32
")", ssn,
1778 SCLogDebug(
"ssn %p: STREAMTCP_FLAG_4WHS unset, normal SYN/ACK"
1779 " so considering 3WHS", ssn);
1790 static inline bool StateSynSentValidateTimestamp(
TcpSession *ssn,
Packet *p)
1800 if (receiver_stream->
last_ts != 0 && ts_echo != 0 &&
1801 ts_echo != receiver_stream->
last_ts)
1804 ts_echo, receiver_stream->
last_ts);
1808 if (receiver_stream->
last_ts == 0 && ts_echo != 0) {
1810 ts_echo, receiver_stream->
last_ts);
1820 memset(q, 0,
sizeof(*q));
1841 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1847 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1851 memset(q, 0,
sizeof(*q));
1852 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,
1878 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1882 memset(q, 0,
sizeof(*q));
1884 const TCPHdr *tcph = PacketGetTCP(p);
1902 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1918 SCLogDebug(
"ssn %p: search state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, s, s->
seq, s->
win,
1923 SCLogDebug(
"ssn %p: queue state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u (last:%s)", ssn, q,
1931 }
else if (ignore_ts) {
1951 ssn->
queue = new_head;
1954 tail->next = old_head;
1956 *old_head = *search;
1957 old_head->
next = NULL;
1963 TcpStateQueueInitFromSsnSyn(ssn, &search);
1967 if (ssn->
queue != NULL && StreamTcp3whsFindSyn(ssn, &search, &
tail,
false) != NULL)
1977 AddAndRotate(ssn,
tail, &search);
1982 SCLogDebug(
"ssn %p: =~ SYN queue failed: stream memcap reached", ssn);
1988 SCLogDebug(
"ssn %p: =~ SYN queue failed: alloc failed", ssn);
2042 static inline bool StateSynSentCheckSynAck3Whs(
TcpSession *ssn,
Packet *p,
const bool ts_mismatch)
2044 const TCPHdr *tcph = PacketGetTCP(p);
2046 if (seq_match && !ts_mismatch) {
2051 if (ssn->
queue == NULL) {
2056 TcpStateQueueInitFromPktSynAck(p, &search);
2067 SCLogDebug(
"ssn %p: found queued SYN state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q,
2069 StreamTcp3whsStoreSynApplyToSsn(ssn, q);
2074 }
else if (ts_mismatch) {
2088 static inline bool StateSynSentCheckSynAckTFO(
TcpSession *ssn,
Packet *p,
const bool ts_mismatch)
2090 const TCPHdr *tcph = PacketGetTCP(p);
2093 if (seq_match_tfo && !ts_mismatch) {
2095 }
else if (seq_match_nodata && !ts_mismatch) {
2102 if (ssn->
queue == NULL) {
2107 TcpStateQueueInitFromPktSynAck(p, &search);
2118 SCLogDebug(
"ssn %p: found queued SYN state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q,
2120 StreamTcp3whsStoreSynApplyToSsn(ssn, q);
2125 if (!seq_match_tfo && !seq_match_nodata) {
2127 }
else if (ts_mismatch) {
2143 static int StreamTcpPacketStateSynSent(
2147 const TCPHdr *tcph = PacketGetTCP(p);
2153 SCLogDebug(
"%" PRIu64
": ssn %p: SYN/ACK on SYN_SENT state for packet %" PRIu64,
2157 const bool ts_mismatch =
2162 if (StateSynSentCheckSynAck3Whs(ssn, p, ts_mismatch)) {
2163 SCLogDebug(
"ssn %p: ACK match, packet ACK %" PRIu32
" == "
2164 "%" PRIu32
" from stream",
2167 SCLogDebug(
"ssn %p: (3WHS) ACK mismatch, packet ACK %" PRIu32
" != "
2168 "%" PRIu32
" from stream",
2173 if (StateSynSentCheckSynAckTFO(ssn, p, ts_mismatch)) {
2174 SCLogDebug(
"ssn %p: (TFO) ACK matches next_seq, packet ACK %" PRIu32
" == "
2175 "%" PRIu32
" from stream",
2178 SCLogDebug(
"ssn %p: (TFO) ACK mismatch, packet ACK %" PRIu32
" != "
2179 "%" PRIu32
" from stream",
2185 StreamTcp3wsFreeQueue(ssn);
2187 StreamTcp3whsSynAckUpdate(ssn, p, NULL);
2196 SCLogDebug(
"ssn %p: SYN/ACK received in the wrong direction", ssn);
2200 SCLogDebug(
"ssn %p: SYN/ACK received on 4WHS session", ssn);
2207 SCLogDebug(
"ssn %p: 4WHS ACK mismatch, packet ACK %" PRIu32
""
2208 " != %" PRIu32
" from stream",
2218 SCLogDebug(
"ssn %p: 4WHS SEQ mismatch, packet SEQ %" PRIu32
""
2219 " != %" PRIu32
" from *first* SYN pkt",
2226 SCLogDebug(
"ssn %p: =~ 4WHS ssn state is now TCP_SYN_RECV", ssn);
2240 SCLogDebug(
"ssn %p: 4WHS ssn->client.last_ts %" PRIu32
" "
2241 "ssn->server.last_ts %" PRIu32
"",
2266 SCLogDebug(
"ssn %p: SACK permitted for 4WHS session", ssn);
2273 SCLogDebug(
"ssn %p: 4WHS ssn->client.isn %" PRIu32
", "
2274 "ssn->client.next_seq %" PRIu32
", "
2275 "ssn->client.last_ack %" PRIu32
" "
2276 "(ssn->server.last_ack %" PRIu32
")",
2285 if (!StateSynSentValidateTimestamp(ssn, p)) {
2293 if (!StreamTcpValidateRst(ssn, p))
2300 SCLogDebug(
"ssn->server.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2302 StreamTcpCloseSsnWithReset(p, ssn);
2303 StreamTcp3wsFreeQueue(ssn);
2307 SCLogDebug(
"ssn->client.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2308 StreamTcpCloseSsnWithReset(p, ssn);
2309 StreamTcp3wsFreeQueue(ssn);
2317 SCLogDebug(
"ssn %p: SYN packet on state SYN_SENT... resent", ssn);
2319 SCLogDebug(
"ssn %p: SYN packet on state SYN_SENT... resent of "
2332 SCLogDebug(
"ssn %p: STREAMTCP_FLAG_4WHS flag set", ssn);
2369 SCLogDebug(
"ssn %p: 4WHS ssn->server.isn %" PRIu32
", "
2370 "ssn->server.next_seq %" PRIu32
", "
2371 "ssn->server.last_ack %"PRIu32
"", ssn,
2374 SCLogDebug(
"ssn %p: 4WHS ssn->client.isn %" PRIu32
", "
2375 "ssn->client.next_seq %" PRIu32
", "
2376 "ssn->client.last_ack %"PRIu32
"", ssn,
2385 TcpStateQueueInitFromPktSyn(p, &syn_pkt);
2386 TcpStateQueueInitFromSsnSyn(ssn, &syn_ssn);
2388 if (memcmp(&syn_pkt, &syn_ssn,
sizeof(
TcpStateQueue)) != 0) {
2390 StreamTcp3whsStoreSyn(ssn, p);
2391 SCLogDebug(
"ssn %p: Retransmitted SYN. Updating ssn from packet %" PRIu64
2392 ". Stored previous state",
2395 StreamTcp3whsStoreSynApplyToSsn(ssn, &syn_pkt);
2411 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
2412 "%" PRIu32
" from stream",
2419 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2420 StreamTcp3wsFreeQueue(ssn);
2433 SCLogDebug(
"ssn %p: synsent => Asynchronous stream, packet SEQ"
2434 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2435 "ssn->client.next_seq %" PRIu32
"",
2484 static int StreamTcpPacketStateSynRecv(
2488 const TCPHdr *tcph = PacketGetTCP(p);
2491 if (!StreamTcpValidateRst(ssn, p))
2508 SCLogDebug(
"Detection evasion has been attempted, so"
2509 " not resetting the connection !!");
2517 SCLogDebug(
"Detection evasion has been attempted, so"
2518 " not resetting the connection !!");
2524 StreamTcpCloseSsnWithReset(p, ssn);
2527 StreamTcpHandleTimestamp(ssn, p);
2534 if (!StreamTcpValidateTimestamp(ssn, p))
2538 if ((StreamTcpHandleFin(
tv, stt, ssn, p)) == -1)
2543 SCLogDebug(
"ssn %p: SYN/ACK packet on state SYN_RECV. resent", ssn);
2546 SCLogDebug(
"ssn %p: SYN/ACK-pkt to server in SYN_RECV state", ssn);
2555 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
2556 "%" PRIu32
" from stream",
2566 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
2567 "%" PRIu32
" from stream",
2570 if (StreamTcp3whsQueueSynAck(ssn, p) == -1)
2572 SCLogDebug(
"ssn %p: queued different SYN/ACK", ssn);
2576 SCLogDebug(
"ssn %p: SYN packet on state SYN_RECV... resent", ssn);
2579 SCLogDebug(
"ssn %p: SYN-pkt to client in SYN_RECV state", ssn);
2586 SCLogDebug(
"ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
2594 SCLogDebug(
"ssn %p: checking ACK against queued SYN/ACKs", ssn);
2597 SCLogDebug(
"ssn %p: here we update state against queued SYN/ACK", ssn);
2598 StreamTcp3whsSynAckUpdate(ssn, p, q);
2600 SCLogDebug(
"ssn %p: none found, now checking ACK against original SYN/ACK (state)", ssn);
2610 if (!(StreamTcpValidateTimestamp(ssn, p))) {
2616 SCLogDebug(
"ssn %p: ACK received on 4WHS session",ssn);
2619 SCLogDebug(
"ssn %p: 4WHS wrong seq nr on packet", ssn);
2624 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
2625 SCLogDebug(
"ssn %p: 4WHS invalid ack nr on packet", ssn);
2631 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
2632 "%" PRIu32
", ACK %" PRIu32
"",
2636 StreamTcpHandleTimestamp(ssn, p);
2645 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2649 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
", "
2650 "ssn->client.last_ack %"PRIu32
"", ssn,
2655 bool ack_indicates_missed_3whs_ack_packet =
false;
2665 SCLogDebug(
"ssn %p: ACK received on midstream SYN/ACK "
2666 "pickup session",ssn);
2669 SCLogDebug(
"ssn %p: ACK received on TFO session",ssn);
2686 SCLogDebug(
"ssn %p: possible data injection", ssn);
2691 SCLogDebug(
"ssn %p: ACK received in the wrong direction",
2696 ack_indicates_missed_3whs_ack_packet =
true;
2700 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ %" PRIu32
""
2701 ", ACK %" PRIu32
"",
2713 StreamTcpHandleTimestamp(ssn, p);
2737 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2763 StreamTcpHandleTimestamp(ssn, p);
2776 SCLogDebug(
"ssn %p: synrecv => Asynchronous stream, packet SEQ"
2777 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2778 "ssn->server.next_seq %" PRIu32,
2783 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2792 SCLogDebug(
"ssn %p: wrong ack nr on packet, possible evasion!!",
2802 SCLogDebug(
"ssn %p: ACK for missing data", ssn);
2805 StreamTcpHandleTimestamp(ssn, p);
2811 SCLogDebug(
"ssn %p: ACK for missing data: ssn->server.next_seq %u", ssn,
2821 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2830 SCLogDebug(
"ssn %p: ACK for missing data", ssn);
2833 StreamTcpHandleTimestamp(ssn, p);
2855 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2860 }
else if ((ack_indicates_missed_3whs_ack_packet ||
2864 if (ack_indicates_missed_3whs_ack_packet) {
2865 SCLogDebug(
"ssn %p: packet fits perfectly after a missed 3whs-ACK", ssn);
2867 SCLogDebug(
"ssn %p: (TFO) expected packet fits perfectly after SYN/ACK", ssn);
2876 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2881 SCLogDebug(
"ssn %p: wrong seq nr on packet", ssn);
2887 SCLogDebug(
"ssn %p: ssn->server.next_win %" PRIu32
", "
2888 "ssn->server.last_ack %"PRIu32
"", ssn,
2910 static int HandleEstablishedPacketToServer(
2913 const TCPHdr *tcph = PacketGetTCP(p);
2918 SCLogDebug(
"ssn %p: =+ pkt (%" PRIu32
") is to server: SEQ %" PRIu32
","
2919 "ACK %" PRIu32
", WIN %" PRIu16
"",
2925 SCLogDebug(
"ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
2928 }
else if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
2929 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
2937 SCLogDebug(
"ssn %p: pkt is keep alive", ssn);
2942 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ"
2943 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
2944 " ssn->client.last_ack %" PRIu32
", ssn->client.next_win"
2945 "%" PRIu32
"(%" PRIu32
")",
2955 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ."
2956 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2957 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2958 "%" PRIu32
"(%" PRIu32
")",
2970 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ"
2971 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2972 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2973 "%" PRIu32
"(%" PRIu32
")",
2988 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
2989 " before last_ack %" PRIu32
", after next_seq %" PRIu32
":"
2990 " acked data that we haven't seen before",
2993 SCLogDebug(
"ssn %p: server => SEQ before last_ack, packet SEQ"
2994 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2995 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2996 "%" PRIu32
"(%" PRIu32
")",
3000 SCLogDebug(
"ssn %p: rejecting because pkt before last_ack", ssn);
3006 int zerowindowprobe = 0;
3009 SCLogDebug(
"ssn %p: zero window probe", ssn);
3010 zerowindowprobe = 1;
3020 if (zerowindowprobe) {
3021 SCLogDebug(
"ssn %p: zero window probe, skipping oow check", ssn);
3024 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
3029 SCLogDebug(
"ssn %p: ssn->server.window %"PRIu32
"", ssn,
3046 StreamTcpHandleTimestamp(ssn, p);
3058 SCLogDebug(
"ssn %p: toserver => SEQ out of window, packet SEQ "
3059 "%" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3060 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
3061 "%" PRIu32
"(%" PRIu32
")",
3065 StreamTcpSackedSize(&ssn->
client));
3085 static int HandleEstablishedPacketToClient(
3088 const TCPHdr *tcph = PacketGetTCP(p);
3093 SCLogDebug(
"ssn %p: =+ pkt (%" PRIu32
") is to client: SEQ %" PRIu32
","
3094 " ACK %" PRIu32
", WIN %" PRIu16
"",
3100 SCLogDebug(
"ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
3103 }
else if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3104 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3118 SCLogDebug(
"ssn %p: adjusted midstream ssn->server.next_win to "
3124 SCLogDebug(
"ssn %p: pkt is keep alive", ssn);
3130 SCLogDebug(
"ssn %p: client => Asynchronous stream, packet SEQ"
3131 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3132 " ssn->client.last_ack %" PRIu32
", ssn->client.next_win"
3133 " %" PRIu32
"(%" PRIu32
")",
3144 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
3145 " before last_ack %" PRIu32
", after next_seq %" PRIu32
":"
3146 " acked data that we haven't seen before",
3149 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
3150 " before last_ack %" PRIu32
". next_seq %" PRIu32,
3157 int zerowindowprobe = 0;
3160 SCLogDebug(
"ssn %p: zero window probe", ssn);
3161 zerowindowprobe = 1;
3172 if (zerowindowprobe) {
3173 SCLogDebug(
"ssn %p: zero window probe, skipping oow check", ssn);
3176 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
3180 SCLogDebug(
"ssn %p: ssn->client.window %"PRIu32
"", ssn,
3193 StreamTcpHandleTimestamp(ssn, p);
3202 SCLogDebug(
"ssn %p: client => SEQ out of window, packet SEQ"
3203 "%" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3204 " ssn->server.last_ack %" PRIu32
", ssn->server.next_win "
3205 "%" PRIu32
"(%" PRIu32
")",
3214 static bool StreamTcpPacketIsZeroWindowProbeAck(
const TcpSession *ssn,
const Packet *p)
3216 const TCPHdr *tcph = PacketGetTCP(p);
3240 if (pkt_win != rcv->
window)
3254 static bool StreamTcpPacketIsDupAck(
const TcpSession *ssn,
const Packet *p)
3256 const TCPHdr *tcph = PacketGetTCP(p);
3274 if (pkt_win == 0 || rcv->
window == 0)
3276 if (pkt_win != rcv->
window)
3284 SCLogDebug(
"ssn %p: packet:%" PRIu64
" seq:%u ack:%u win:%u snd %u:%u:%u rcv %u:%u:%u", ssn,
3308 const TCPHdr *tcph = PacketGetTCP(p);
3359 static int StreamTcpPacketIsSpuriousRetransmission(
const TcpSession *ssn,
Packet *p)
3370 const TCPHdr *tcph = PacketGetTCP(p);
3376 "ssn %p: spurious retransmission; packet entirely before base_seq: SEQ %u(%u) "
3377 "last_ack %u base_seq %u",
3386 SCLogDebug(
"ssn %p: spurious retransmission; packet entirely before last_ack: SEQ %u(%u) "
3394 SCLogDebug(
"ssn %p: NOT spurious retransmission; packet NOT entirely before last_ack: SEQ "
3395 "%u(%u) last_ack %u, base_seq %u",
3412 static int StreamTcpPacketStateEstablished(
3416 const TCPHdr *tcph = PacketGetTCP(p);
3422 if (!StreamTcpValidateRst(ssn, p))
3426 StreamTcpCloseSsnWithReset(p, ssn);
3430 SCLogDebug(
"ssn %p: ssn->server.next_seq %" PRIu32
"", ssn,
3440 StreamTcpHandleTimestamp(ssn, p);
3444 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3452 StreamTcpCloseSsnWithReset(p, ssn);
3457 SCLogDebug(
"ssn %p: ssn->server.next_seq %" PRIu32
"", ssn,
3467 StreamTcpHandleTimestamp(ssn, p);
3471 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3482 if (!StreamTcpValidateTimestamp(ssn, p))
3487 " %" PRIu32
", last ACK %" PRIu32
", next win %"PRIu32
","
3492 if ((StreamTcpHandleFin(
tv, stt, ssn, p)) == -1)
3497 SCLogDebug(
"ssn %p: SYN/ACK packet on state ESTABLISHED... resent",
3501 SCLogDebug(
"ssn %p: SYN/ACK-pkt to server in ESTABLISHED state", ssn);
3510 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
3511 "%" PRIu32
" from stream",
3521 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
3522 "%" PRIu32
" from stream",
3535 SCLogDebug(
"ssn %p: SYN/ACK packet on state ESTABLISHED... resent. "
3536 "Likely due server not receiving final ACK in 3whs", ssn);
3540 SCLogDebug(
"ssn %p: SYN packet on state ESTABLISHED... resent", ssn);
3542 SCLogDebug(
"ssn %p: SYN-pkt to client in EST state", ssn);
3549 SCLogDebug(
"ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
3570 if (!StreamTcpValidateTimestamp(ssn, p))
3576 HandleEstablishedPacketToServer(
tv, ssn, p, stt);
3578 SCLogDebug(
"ssn %p: next SEQ %" PRIu32
", last ACK %" PRIu32
","
3579 " next win %" PRIu32
", win %" PRIu32
"", ssn,
3586 SCLogDebug(
"3whs is now confirmed by server");
3590 HandleEstablishedPacketToClient(
tv, ssn, p, stt);
3592 SCLogDebug(
"ssn %p: next SEQ %" PRIu32
", last ACK %" PRIu32
","
3593 " next win %" PRIu32
", win %" PRIu32
"", ssn,
3618 const TCPHdr *tcph = PacketGetTCP(p);
3624 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ %" PRIu32
","
3628 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3629 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3635 SCLogDebug(
"ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn,
seq, pkt_re,
3640 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
" != "
3641 "%" PRIu32
" from stream",
3654 SCLogDebug(
"ssn %p: state changed to TCP_CLOSE_WAIT", ssn);
3659 SCLogDebug(
"ssn %p: ssn->client.next_seq %" PRIu32
"", ssn,
3664 StreamTcpHandleTimestamp(ssn, p);
3677 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK %" PRIu32
"",
3680 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ %" PRIu32
", "
3684 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3685 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3691 SCLogDebug(
"ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn,
seq, pkt_re,
3696 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
" != "
3697 "%" PRIu32
" from stream (last_ack %u win %u = %u)",
3706 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT1", ssn);
3715 StreamTcpHandleTimestamp(ssn, p);
3728 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK %" PRIu32
"",
3748 static int StreamTcpPacketStateFinWait1(
3752 const TCPHdr *tcph = PacketGetTCP(p);
3758 if (!StreamTcpValidateRst(ssn, p))
3761 StreamTcpCloseSsnWithReset(p, ssn);
3770 StreamTcpHandleTimestamp(ssn, p);
3781 StreamTcpHandleTimestamp(ssn, p);
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_TIME_WAIT", ssn);
3827 StreamTcpHandleTimestamp(ssn, p);
3843 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3847 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3848 "%" PRIu32
", ACK %" PRIu32
"",
3850 int retransmission = 0;
3852 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
3853 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3858 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3864 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3865 " != %" PRIu32
" from stream",
3871 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3872 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3878 StreamTcpHandleTimestamp(ssn, p);
3881 if (!retransmission) {
3883 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
3901 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3908 if (!StreamTcpValidateTimestamp(ssn, p))
3913 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3914 "%" PRIu32
", ACK %" PRIu32
"",
3916 int retransmission = 0;
3918 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
3919 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3925 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3926 " != %" PRIu32
" from stream",
3932 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3933 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3938 if (!retransmission) {
3940 SCLogDebug(
"ssn %p: state changed to TCP_CLOSING", ssn);
3946 StreamTcpHandleTimestamp(ssn, p);
3963 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3967 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3968 "%" PRIu32
", ACK %" PRIu32
"",
3971 int retransmission = 0;
3973 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
3974 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3980 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3981 " != %" PRIu32
" from stream",
3987 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3988 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3993 if (!retransmission) {
3995 SCLogDebug(
"ssn %p: state changed to TCP_CLOSING", ssn);
4001 StreamTcpHandleTimestamp(ssn, p);
4018 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4023 SCLogDebug(
"ssn (%p): SYN pkt on FinWait1", ssn);
4029 if (!StreamTcpValidateTimestamp(ssn, p))
4034 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4035 "%" PRIu32
", ACK %" PRIu32
"",
4037 int retransmission = 0;
4039 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4040 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4045 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4046 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4053 "ssn %p: ACK's older segment as %u < %u", ssn, ack, ssn->
server.
next_seq);
4054 }
else if (!retransmission) {
4058 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
4064 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT2", ssn);
4067 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4068 " != %" PRIu32
" from stream",
4080 StreamTcpHandleTimestamp(ssn, p);
4101 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4107 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4108 "%" PRIu32
", ACK %" PRIu32
"",
4111 int retransmission = 0;
4113 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4114 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4119 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4120 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4125 if (!retransmission) {
4128 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
4134 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT2", ssn);
4137 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4138 " != %" PRIu32
" from stream",
4148 StreamTcpHandleTimestamp(ssn, p);
4169 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4190 static int StreamTcpPacketStateFinWait2(
4194 const TCPHdr *tcph = PacketGetTCP(p);
4200 if (!StreamTcpValidateRst(ssn, p))
4203 StreamTcpCloseSsnWithReset(p, ssn);
4212 StreamTcpHandleTimestamp(ssn, p);
4223 StreamTcpHandleTimestamp(ssn, p);
4231 if (!StreamTcpValidateTimestamp(ssn, p))
4236 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4237 "%" PRIu32
", ACK %" PRIu32
"",
4239 int retransmission = 0;
4245 }
else if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4246 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4252 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ "
4253 "%" PRIu32
" != %" PRIu32
" from stream",
4259 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4260 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4265 if (!retransmission) {
4267 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4277 StreamTcpHandleTimestamp(ssn, p);
4290 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4294 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4295 "%" PRIu32
", ACK %" PRIu32
"",
4297 int retransmission = 0;
4303 }
else if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4304 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4310 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ "
4311 "%" PRIu32
" != %" PRIu32
" from stream",
4317 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4318 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4323 if (!retransmission) {
4325 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4331 StreamTcpHandleTimestamp(ssn, p);
4343 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4349 SCLogDebug(
"ssn (%p): SYN pkt on FinWait2", ssn);
4355 if (!StreamTcpValidateTimestamp(ssn, p))
4360 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4361 "%" PRIu32
", ACK %" PRIu32
"",
4363 int retransmission = 0;
4365 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4366 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4371 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4372 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4377 if (!retransmission) {
4380 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
4385 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4386 " != %" PRIu32
" from stream",
4396 StreamTcpHandleTimestamp(ssn, p);
4412 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4416 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4417 "%" PRIu32
", ACK %" PRIu32
"",
4419 int retransmission = 0;
4421 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4422 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4427 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4428 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4433 if (!retransmission) {
4436 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
4440 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4441 " != %" PRIu32
" from stream",
4451 StreamTcpHandleTimestamp(ssn, p);
4467 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4488 static int StreamTcpPacketStateClosing(
4492 const TCPHdr *tcph = PacketGetTCP(p);
4498 if (!StreamTcpValidateRst(ssn, p))
4501 StreamTcpCloseSsnWithReset(p, ssn);
4510 StreamTcpHandleTimestamp(ssn, p);
4521 StreamTcpHandleTimestamp(ssn, p);
4528 SCLogDebug(
"ssn (%p): SYN pkt on Closing", ssn);
4534 if (!StreamTcpValidateTimestamp(ssn, p))
4539 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4540 "%" PRIu32
", ACK %" PRIu32
"",
4542 int retransmission = 0;
4543 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4544 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4550 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4551 " != %" PRIu32
" from stream",
4557 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4558 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4563 if (!retransmission) {
4565 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4571 StreamTcpHandleTimestamp(ssn, p);
4581 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4585 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4586 "%" PRIu32
", ACK %" PRIu32
"",
4588 int retransmission = 0;
4589 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4590 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4596 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4597 " != %" PRIu32
" from stream",
4603 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4604 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4609 if (!retransmission) {
4611 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4617 StreamTcpHandleTimestamp(ssn, p);
4628 SCLogDebug(
"StreamTcpPacketStateClosing (%p): =+ next SEQ "
4629 "%" PRIu32
", last ACK %" PRIu32
"", ssn,
4649 static int StreamTcpPacketStateCloseWait(
4653 const TCPHdr *tcph = PacketGetTCP(p);
4661 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4662 "%" PRIu32
", ACK %" PRIu32
"",
4665 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4666 "%" PRIu32
", ACK %" PRIu32
"",
4671 if (!StreamTcpValidateRst(ssn, p))
4674 StreamTcpCloseSsnWithReset(p, ssn);
4683 StreamTcpHandleTimestamp(ssn, p);
4694 StreamTcpHandleTimestamp(ssn, p);
4702 if (!StreamTcpValidateTimestamp(ssn, p))
4707 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4708 "%" PRIu32
", ACK %" PRIu32
"",
4711 int retransmission = 0;
4712 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4713 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4718 if (!retransmission) {
4721 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4722 " != %" PRIu32
" from stream",
4729 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4730 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4737 if (!retransmission)
4741 StreamTcpHandleTimestamp(ssn, p);
4753 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4757 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4758 "%" PRIu32
", ACK %" PRIu32
"",
4761 int retransmission = 0;
4762 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4763 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4768 if (!retransmission) {
4771 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4772 " != %" PRIu32
" from stream",
4779 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4780 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4785 if (!retransmission) {
4787 SCLogDebug(
"ssn %p: state changed to TCP_LAST_ACK", ssn);
4793 StreamTcpHandleTimestamp(ssn, p);
4805 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4811 SCLogDebug(
"ssn (%p): SYN pkt on CloseWait", ssn);
4817 if (!StreamTcpValidateTimestamp(ssn, p))
4822 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4823 "%" PRIu32
", ACK %" PRIu32
"",
4826 int retransmission = 0;
4827 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4828 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4834 SCLogDebug(
"ssn %p: -> retransmission", ssn);
4839 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4840 " != %" PRIu32
" from stream",
4846 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4847 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4852 if (!retransmission) {
4857 StreamTcpHandleTimestamp(ssn, p);
4871 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4875 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4876 "%" PRIu32
", ACK %" PRIu32
"",
4878 int retransmission = 0;
4879 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4880 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4886 SCLogDebug(
"ssn %p: -> retransmission", ssn);
4891 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4892 " != %" PRIu32
" from stream",
4898 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4899 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4904 if (!retransmission) {
4909 StreamTcpHandleTimestamp(ssn, p);
4923 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4944 static int StreamTcpPacketStateLastAck(
4948 const TCPHdr *tcph = PacketGetTCP(p);
4954 if (!StreamTcpValidateRst(ssn, p))
4957 StreamTcpCloseSsnWithReset(p, ssn);
4966 StreamTcpHandleTimestamp(ssn, p);
4977 StreamTcpHandleTimestamp(ssn, p);
4985 SCLogDebug(
"ssn (%p): FIN pkt on LastAck", ssn);
4988 SCLogDebug(
"ssn (%p): SYN pkt on LastAck", ssn);
4994 if (!StreamTcpValidateTimestamp(ssn, p))
4999 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
5000 "%" PRIu32
", ACK %" PRIu32
"",
5003 int retransmission = 0;
5004 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
5005 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
5010 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
5011 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5016 if (!retransmission) {
5018 SCLogDebug(
"ssn %p: not updating state as packet is before next_seq", ssn);
5020 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5021 " != %" PRIu32
" from stream",
5027 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5033 StreamTcpHandleTimestamp(ssn, p);
5044 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5065 static int StreamTcpPacketStateTimeWait(
5069 const TCPHdr *tcph = PacketGetTCP(p);
5075 if (!StreamTcpValidateRst(ssn, p))
5078 StreamTcpCloseSsnWithReset(p, ssn);
5087 StreamTcpHandleTimestamp(ssn, p);
5098 StreamTcpHandleTimestamp(ssn, p);
5108 SCLogDebug(
"ssn (%p): SYN pkt on TimeWait", ssn);
5114 if (!StreamTcpValidateTimestamp(ssn, p))
5119 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
5120 "%" PRIu32
", ACK %" PRIu32
"",
5122 int retransmission = 0;
5123 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
5124 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
5129 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5130 " != %" PRIu32
" from stream",
5136 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
5137 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5142 if (!retransmission) {
5144 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5150 StreamTcpHandleTimestamp(ssn, p);
5161 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5165 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
5166 "%" PRIu32
", ACK %" PRIu32
"",
5168 int retransmission = 0;
5169 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
5170 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
5175 SCLogDebug(
"ssn %p: -> retransmission", ssn);
5178 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5179 " != %" PRIu32
" from stream",
5186 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
5187 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5192 if (!retransmission) {
5194 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5200 StreamTcpHandleTimestamp(ssn, p);
5211 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5223 static int StreamTcpPacketStateClosed(
5228 const TCPHdr *tcph = PacketGetTCP(p);
5234 TcpStream *stream = NULL, *ostream = NULL;
5251 if (StreamTcpStateDispatch(
tv, p, stt, ssn, ssn->
pstate) < 0)
5266 const TCPHdr *tcph = PacketGetTCP(p);
5280 SCLogDebug(
"regular packet %" PRIu64
" from same sender as "
5281 "the previous RST. Looks like it injected!",
5308 const TCPHdr *tcph = PacketGetTCP(p);
5313 TcpStream *stream = NULL, *ostream = NULL;
5324 if (ack == ostream->last_ack &&
seq == (stream->
next_seq - 1)) {
5340 TcpStream *stream = NULL, *ostream = NULL;
5351 const TCPHdr *tcph = PacketGetTCP(p);
5370 if (pkt_win != ostream->window)
5379 SCLogDebug(
"seq %u (%u), ack %u (%u) FLAG_KEEPALIVE: %s",
seq, stream->
next_seq, ack, ostream->last_ack,
5409 TcpStream *stream = NULL, *ostream = NULL;
5423 const TCPHdr *tcph = PacketGetTCP(p);
5442 if (pkt_win == ostream->window)
5445 if (ack == ostream->last_ack &&
seq == stream->
next_seq) {
5460 TcpStream *stream = NULL, *ostream = NULL;
5468 const TCPHdr *tcph = PacketGetTCP(p);
5485 SCLogDebug(
"%" PRIu64
", seq %u ack %u stream->next_seq %u ostream->next_seq %u",
5513 TcpStream *stream = NULL, *ostream = NULL;
5524 const TCPHdr *tcph = PacketGetTCP(p);
5540 if (pkt_win < ostream->window) {
5541 uint32_t diff = ostream->window - pkt_win;
5543 SEQ_GT(ack, ostream->next_seq) &&
5546 SCLogDebug(
"%" PRIu64
", pkt_win %u, stream win %u, diff %u, dsize %u",
5550 SCLogDebug(
"%" PRIu64
", seq %u ack %u ostream->next_seq %u ostream->last_ack %u, "
5551 "ostream->next_win %u, diff %u (%u)",
5553 ostream->next_win, ostream->next_seq - ostream->last_ack,
5561 uint32_t adiff = ack - ostream->last_ack;
5562 if (((pkt_win > 1024) && (diff > (adiff + 32))) ||
5563 ((pkt_win <= 1024) && (diff > adiff)))
5565 SCLogDebug(
"pkt ACK %u is %u bytes beyond last_ack %u, shrinks window by %u "
5566 "(allowing 32 bytes extra): pkt WIN %u", ack, adiff, ostream->last_ack, diff, pkt_win);
5567 SCLogDebug(
"%u - %u = %u (state %u)", diff, adiff, diff - adiff, ssn->
state);
5582 static inline int StreamTcpStateDispatch(
5590 SCLogDebug(
"packet received on TCP_SYN_SENT state");
5591 if (StreamTcpPacketStateSynSent(
tv, p, stt, ssn)) {
5596 SCLogDebug(
"packet received on TCP_SYN_RECV state");
5597 if (StreamTcpPacketStateSynRecv(
tv, p, stt, ssn)) {
5602 SCLogDebug(
"packet received on TCP_ESTABLISHED state");
5603 if (StreamTcpPacketStateEstablished(
tv, p, stt, ssn)) {
5608 SCLogDebug(
"packet received on TCP_FIN_WAIT1 state");
5609 if (StreamTcpPacketStateFinWait1(
tv, p, stt, ssn)) {
5614 SCLogDebug(
"packet received on TCP_FIN_WAIT2 state");
5615 if (StreamTcpPacketStateFinWait2(
tv, p, stt, ssn)) {
5620 SCLogDebug(
"packet received on TCP_CLOSING state");
5621 if (StreamTcpPacketStateClosing(
tv, p, stt, ssn)) {
5626 SCLogDebug(
"packet received on TCP_CLOSE_WAIT state");
5627 if (StreamTcpPacketStateCloseWait(
tv, p, stt, ssn)) {
5632 SCLogDebug(
"packet received on TCP_LAST_ACK state");
5633 if (StreamTcpPacketStateLastAck(
tv, p, stt, ssn)) {
5638 SCLogDebug(
"packet received on TCP_TIME_WAIT state");
5639 if (StreamTcpPacketStateTimeWait(
tv, p, stt, ssn)) {
5645 SCLogDebug(
"packet received on closed state");
5647 if (StreamTcpPacketStateClosed(
tv, p, stt, ssn)) {
5653 SCLogDebug(
"packet received on default state");
5689 const TCPHdr *tcph = PacketGetTCP(p);
5704 SCLogDebug(
"ssn %p: removing ASYNC flag as we have packets on both sides", ssn);
5724 if (StreamTcpCheckFlowDrops(p) == 1) {
5734 if (StreamTcpPacketStateNone(
tv, p, stt, ssn) == -1) {
5761 if (StreamTcpPacketIsKeepAlive(ssn, p) == 1) {
5764 if (StreamTcpPacketIsKeepAliveACK(ssn, p) == 1) {
5765 StreamTcpClearKeepAliveFlag(ssn, p);
5768 StreamTcpClearKeepAliveFlag(ssn, p);
5770 const bool is_zwp_ack = StreamTcpPacketIsZeroWindowProbeAck(ssn, p);
5781 if (StreamTcpPacketIsDupAck(ssn, p)) {
5788 if (StreamTcpPacketIsFinShutdownAck(ssn, p) == 0) {
5789 if (StreamTcpPacketIsWindowUpdate(ssn, p) == 0) {
5790 if (StreamTcpPacketIsBadWindowUpdate(ssn,p))
5792 if (StreamTcpPacketIsOutdatedAck(ssn, p))
5797 int ret = StreamTcpPacketIsSpuriousRetransmission(ssn, p);
5806 if (StreamTcpStateDispatch(
tv, p, stt, ssn, ssn->
state) < 0)
5810 StreamTcpPacketCheckPostRst(ssn, p);
5857 SCLogDebug(
"bypass as stream is dead and we have no rules");
5870 if (StreamTcpInlineDropInvalid()) {
5874 DecodeSetNoPayloadInspectionFlag(p);
5888 static inline int StreamTcpValidateChecksum(
Packet *p)
5896 const TCPHdr *tcph = PacketGetTCP(p);
5897 if (PacketIsIPv4(p)) {
5898 const IPV4Hdr *ip4h = PacketGetIPv4(p);
5899 p->
l4.
csum = TCPChecksum(ip4h->s_ip_addrs, (uint16_t *)tcph,
5902 }
else if (PacketIsIPv6(p)) {
5903 const IPV6Hdr *ip6h = PacketGetIPv6(p);
5904 p->
l4.
csum = TCPV6Checksum(ip6h->s_ip6_addrs, (uint16_t *)tcph,
5925 static int TcpSessionPacketIsStreamStarter(
const Packet *p)
5927 const TCPHdr *tcph = PacketGetTCP(p);
5940 SCLogDebug(
"packet %" PRIu64
" is a midstream stream starter: %02x",
5951 static bool TcpSessionReuseDoneEnoughSyn(
const Packet *p,
const Flow *f,
const TcpSession *ssn)
5953 const TCPHdr *tcph = PacketGetTCP(p);
5958 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p null. Reuse.",
5964 ", ssn %p. STREAMTCP_FLAG_TFO_DATA_IGNORED set. Reuse.",
5970 ", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.",
5976 ", ssn %p state >= TCP_LAST_ACK (%u). Reuse.",
5980 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.",
5985 ", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.",
5992 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p null. Reuse.",
5998 ", ssn %p state >= TCP_LAST_ACK (%u). Reuse.",
6002 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.",
6007 ", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.",
6021 static bool TcpSessionReuseDoneEnoughSynAck(
const Packet *p,
const Flow *f,
const TcpSession *ssn)
6023 const TCPHdr *tcph = PacketGetTCP(p);
6026 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p null. No reuse.",
6032 ", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.",
6038 ", ssn %p state >= TCP_LAST_ACK (%u). Reuse.",
6042 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.",
6047 ", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.",
6054 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p null. Reuse.",
6060 ", ssn %p state >= TCP_LAST_ACK (%u). Reuse.",
6064 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.",
6069 ", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.",
6086 const TCPHdr *tcph = PacketGetTCP(p);
6088 return TcpSessionReuseDoneEnoughSyn(p, f, ssn);
6093 return TcpSessionReuseDoneEnoughSynAck(p, f, ssn);
6102 if (p->
proto == IPPROTO_TCP && PacketIsTCP(p)) {
6103 if (TcpSessionPacketIsStreamStarter(p) == 1) {
6104 if (TcpSessionReuseDoneEnough(p, f, tcp_ssn) == 1) {
6126 #ifdef QA_SIMULATION
6130 if (!(PacketIsTCP(p))) {
6134 CheckThreadId(
tv, p, stt);
6140 if (StreamTcpValidateChecksum(p) == 0) {
6162 *data = (
void *)stt;
6171 IsStreamTcpSessionMemcapExceptionPolicyStatsValid);
6179 "exception_policy.tcp.midstream.", IsMidstreamExceptionPolicyStatsValid);
6183 "exception_policy.tcp.midstream.", IsMidstreamExceptionPolicyStatsValid);
6199 "exception_policy.tcp.reassembly.", IsReassemblyMemcapExceptionPolicyStatsValid);
6218 SCLogDebug(
"StreamTcp thread specific ctx online at %p, reassembly ctx %p",
6227 StreamTcpSessionPoolAlloc,
6228 StreamTcpSessionPoolInit, NULL,
6229 StreamTcpSessionPoolCleanup, NULL);
6239 SCLogError(
"failed to setup/expand stream session pool. Expand stream.memcap?");
6284 const TCPHdr *tcph = PacketGetTCP(p);
6292 if (!StreamTcpValidateTimestamp(ssn, p)) {
6321 StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
6322 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
6334 StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
6335 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
6348 receiver_stream = &ssn->
server;
6350 receiver_stream = &ssn->
client;
6352 SCLogDebug(
"ssn %p: setting STREAMTCP_STREAM_FLAG_RST_RECV on receiver stream", ssn);
6372 switch (os_policy) {
6379 SCLogDebug(
"reset is not Valid! Packet SEQ: %" PRIu32
" "
6380 "and server SEQ: %" PRIu32
"",
6389 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" "
6390 "and client SEQ: %" PRIu32
"",
6407 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6408 " server SEQ: %" PRIu32
"",
6420 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6421 " client SEQ: %" PRIu32
"",
6442 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" "
6443 "and server SEQ: %" PRIu32
"",
6449 SCLogDebug(
"reset is valid! Packet SEQ: %" PRIu32
" Stream %u",
seq,
6453 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6454 " client SEQ: %" PRIu32
"",
6485 uint8_t check_ts = 1;
6486 const TCPHdr *tcph = PacketGetTCP(p);
6490 sender_stream = &ssn->
client;
6491 receiver_stream = &ssn->
server;
6493 sender_stream = &ssn->
server;
6494 receiver_stream = &ssn->
client;
6505 uint32_t last_pkt_ts = sender_stream->
last_pkt_ts;
6506 uint32_t last_ts = sender_stream->
last_ts;
6556 SCLogDebug(
"ts %"PRIu32
", last_ts %"PRIu32
"",
ts, last_ts);
6560 result = (int32_t) ((
ts - last_ts) + 1);
6562 result = (int32_t) (
ts - last_ts);
6565 SCLogDebug(
"result %" PRIi32
", p->ts(secs) %" PRIuMAX
"", result,
6568 if (last_pkt_ts == 0 &&
6576 "%" PRIu32
" p->tcpvars->ts %" PRIu32
" result "
6577 "%" PRId32
"", last_ts,
ts, result);
6580 }
else if ((sender_stream->
last_ts != 0) &&
6582 SCLogDebug(
"packet is not valid last_pkt_ts "
6583 "%" PRIu32
" p->ts(sec) %" PRIu32
"",
6595 SCLogDebug(
"timestamp considered valid anyway");
6627 uint8_t check_ts = 1;
6628 const TCPHdr *tcph = PacketGetTCP(p);
6632 sender_stream = &ssn->
client;
6633 receiver_stream = &ssn->
server;
6635 sender_stream = &ssn->
server;
6636 receiver_stream = &ssn->
client;
6704 result = (int32_t) ((
ts - sender_stream->
last_ts) + 1);
6706 result = (int32_t) (
ts - sender_stream->
last_ts);
6709 SCLogDebug(
"result %" PRIi32
", p->ts(sec) %" PRIuMAX
"", result,
6719 SCLogDebug(
"timestamp is not valid sender_stream->last_ts "
6720 "%" PRIu32
" p->tcpvars->ts %" PRIu32
" result "
6721 "%" PRId32
"", sender_stream->
last_ts,
ts, result);
6724 }
else if ((sender_stream->
last_ts != 0) &&
6727 SCLogDebug(
"packet is not valid sender_stream->last_pkt_ts "
6728 "%" PRIu32
" p->ts(sec) %" PRIu32
"",
6742 }
else if (ret == 0) {
6752 SCLogDebug(
"timestamp considered valid anyway");
6788 const TCPHdr *tcph = PacketGetTCP(p);
6803 SCLogDebug(
"ssn %p: pkt ACK %" PRIu32
" == stream last ACK %" PRIu32, ssn, ack,
6816 SCLogDebug(
"ACK %"PRIu32
" is before last_ack %"PRIu32
" - window "
6817 "%"PRIu32
" = %"PRIu32, ack, stream->
last_ack,
6840 SCLogDebug(
"default path leading to invalid: ACK %"PRIu32
", last_ack %"PRIu32
6853 const uint32_t progress)
6907 static void StreamTcpPseudoPacketCreateDetectLogFlush(
ThreadVars *
tv,
6930 np->
proto = IPPROTO_TCP;
6931 FlowReference(&np->
flow, f);
6941 DecodeSetNoPacketInspectionFlag(np);
6944 DecodeSetNoPayloadInspectionFlag(np);
6984 ip4h->
ip_len = htons(40);
6990 ip4h->s_ip_src.s_addr = f->
src.addr_data32[0];
6991 ip4h->s_ip_dst.s_addr = f->
dst.addr_data32[0];
6993 ip4h->s_ip_src.s_addr = f->
dst.addr_data32[0];
6994 ip4h->s_ip_dst.s_addr = f->
src.addr_data32[0];
7027 ip6h->s_ip6_vfc = 0x60;
7028 ip6h->s_ip6_flow = 0;
7029 ip6h->s_ip6_nxt = IPPROTO_TCP;
7030 ip6h->s_ip6_plen = htons(20);
7031 ip6h->s_ip6_hlim = 64;
7033 ip6h->s_ip6_src[0] = f->
src.addr_data32[0];
7034 ip6h->s_ip6_src[1] = f->
src.addr_data32[1];
7035 ip6h->s_ip6_src[2] = f->
src.addr_data32[2];
7036 ip6h->s_ip6_src[3] = f->
src.addr_data32[3];
7037 ip6h->s_ip6_dst[0] = f->
dst.addr_data32[0];
7038 ip6h->s_ip6_dst[1] = f->
dst.addr_data32[1];
7039 ip6h->s_ip6_dst[2] = f->
dst.addr_data32[2];
7040 ip6h->s_ip6_dst[3] = f->
dst.addr_data32[3];
7042 ip6h->s_ip6_src[0] = f->
dst.addr_data32[0];
7043 ip6h->s_ip6_src[1] = f->
dst.addr_data32[1];
7044 ip6h->s_ip6_src[2] = f->
dst.addr_data32[2];
7045 ip6h->s_ip6_src[3] = f->
dst.addr_data32[3];
7046 ip6h->s_ip6_dst[0] = f->
src.addr_data32[0];
7047 ip6h->s_ip6_dst[1] = f->
src.addr_data32[1];
7048 ip6h->s_ip6_dst[2] = f->
src.addr_data32[2];
7049 ip6h->s_ip6_dst[3] = f->
src.addr_data32[3];
7081 np->
ts = parent->
ts;
7089 FlowDeReference(&np->
flow);
7108 StreamTcpPseudoPacketCreateDetectLogFlush(
tv, stt, p, ssn, pq,
ts^0);
7109 StreamTcpPseudoPacketCreateDetectLogFlush(
tv, stt, p, ssn, pq,
ts^1);
7129 if (p->
flow == NULL)
7157 const uint8_t *seg_data;
7158 uint32_t seg_datalen;
7161 int ret = CallbackFunc(p, seg, data, seg_data, seg_datalen);
7189 if (p->
flow == NULL)
7203 if (server_node == NULL && client_node == NULL) {
7207 while (server_node != NULL || client_node != NULL) {
7208 const uint8_t *seg_data;
7209 uint32_t seg_datalen;
7210 if (server_node == NULL) {
7217 &client_stream->
sb, &client_node->
sbseg, &seg_data, &seg_datalen);
7218 ret = CallbackFunc(p, client_node, data, seg_data, seg_datalen);
7223 client_node = TCPSEG_RB_NEXT(client_node);
7224 }
else if (client_node == NULL) {
7231 &server_stream->
sb, &server_node->
sbseg, &seg_data, &seg_datalen);
7232 ret = CallbackFunc(p, server_node, data, seg_data, seg_datalen);
7237 server_node = TCPSEG_RB_NEXT(server_node);
7242 &client_stream->
sb, &client_node->
sbseg, &seg_data, &seg_datalen);
7243 ret = CallbackFunc(p, client_node, data, seg_data, seg_datalen);
7248 client_node = TCPSEG_RB_NEXT(client_node);
7251 &server_stream->
sb, &server_node->
sbseg, &seg_data, &seg_datalen);
7252 ret = CallbackFunc(p, server_node, data, seg_data, seg_datalen);
7257 server_node = TCPSEG_RB_NEXT(server_node);
7292 const char *tcp_state = NULL;
7298 tcp_state =
"syn_sent";
7301 tcp_state =
"syn_recv";
7304 tcp_state =
"established";
7307 tcp_state =
"fin_wait1";
7310 tcp_state =
"fin_wait2";
7313 tcp_state =
"time_wait";
7316 tcp_state =
"last_ack";
7319 tcp_state =
"close_wait";
7322 tcp_state =
"closing";
7325 tcp_state =
"closed";