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)
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;
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;
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 (
SCConfGetNonNull(
"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 (
SCConfGetNonNull(
"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 (
SCConfGetNonNull(
"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;
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;
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");
859 StreamTcpSessionPoolInit, StreamTcpSessionPoolCleanup);
878 SCLogDebug(
"ssn_pool_cnt %"PRIu64
"", ssn_pool_cnt);
881 static bool IsReassemblyMemcapExceptionPolicyStatsValid(
enum ExceptionPolicy exception_policy)
889 static bool IsStreamTcpSessionMemcapExceptionPolicyStatsValid(
enum ExceptionPolicy policy)
897 static void StreamTcpSsnMemcapExceptionPolicyStatsIncr(
950 #if defined(DEBUG) || defined(QA_SIMULATION)
956 if (
unlikely((g_eps_stream_ssn_memcap != UINT64_MAX &&
957 g_eps_stream_ssn_memcap == t_pcapcnt))) {
958 SCLogNotice(
"simulating memcap reached condition for packet %" PRIu64, t_pcapcnt);
973 const TCPHdr *tcph = PacketGetTCP(
p);
1007 switch(ssn->
state) {
1032 if (PacketIsIPv4(
p)) {
1042 }
else if (PacketIsIPv6(
p)) {
1068 #define StreamTcpUpdateLastAck(ssn, stream, ack) \
1070 if (SEQ_GT((ack), (stream)->last_ack) && SEQ_GT(ack, (stream)->base_seq)) { \
1071 SCLogDebug("ssn %p: last_ack set to %" PRIu32 ", moved %u forward", (ssn), (ack), \
1072 (ack) - (stream)->last_ack); \
1073 if ((SEQ_LEQ((stream)->last_ack, (stream)->next_seq) && \
1074 SEQ_GT((ack), (stream)->next_seq))) { \
1075 SCLogDebug("last_ack just passed next_seq: %u (was %u) > %u", (ack), \
1076 (stream)->last_ack, (stream)->next_seq); \
1078 SCLogDebug("next_seq (%u) <> last_ack now %d", (stream)->next_seq, \
1079 (int)(stream)->next_seq - (ack)); \
1081 (stream)->last_ack = (ack); \
1082 StreamTcpSackPruneList((stream)); \
1084 SCLogDebug("ssn %p: no update: ack %u, last_ack %" PRIu32 ", next_seq %u (state %u)", \
1085 (ssn), (ack), (stream)->last_ack, (stream)->next_seq, (ssn)->state); \
1089 #define StreamTcpAsyncLastAckUpdate(ssn, stream) { \
1090 if ((ssn)->flags & STREAMTCP_FLAG_ASYNC) { \
1091 if (SEQ_GT((stream)->next_seq, (stream)->last_ack)) { \
1092 uint32_t ack_diff = (stream)->next_seq - (stream)->last_ack; \
1093 (stream)->last_ack += ack_diff; \
1094 SCLogDebug("ssn %p: ASYNC last_ack set to %"PRIu32", moved %u forward", \
1095 (ssn), (stream)->next_seq, ack_diff); \
1100 #define StreamTcpUpdateNextSeq(ssn, stream, seq) { \
1101 (stream)->next_seq = seq; \
1102 SCLogDebug("ssn %p: next_seq %" PRIu32, (ssn), (stream)->next_seq); \
1103 StreamTcpAsyncLastAckUpdate((ssn), (stream)); \
1113 #define StreamTcpUpdateNextWin(ssn, stream, win) { \
1114 uint32_t sacked_size__ = StreamTcpSackedSize((stream)); \
1115 if (SEQ_GT(((win) + sacked_size__), (stream)->next_win)) { \
1116 (stream)->next_win = ((win) + sacked_size__); \
1117 SCLogDebug("ssn %p: next_win set to %"PRIu32, (ssn), (stream)->next_win); \
1125 SCLogDebug(
"ssn %p: (state: %s) Reset received and state changed to "
1129 static bool IsMidstreamExceptionPolicyStatsValid(
enum ExceptionPolicy policy)
1143 static void StreamTcpMidstreamExceptionPolicyStatsIncr(
1157 const TCPHdr *tcph = PacketGetTCP(
p);
1195 static int StreamTcpPacketStateNone(
1198 const TCPHdr *tcph = PacketGetTCP(
p);
1201 SCLogDebug(
"RST packet received, no session setup");
1211 SCLogDebug(
"FIN packet received, no session setup");
1217 SCLogDebug(
"FIN packet received, no session setup");
1234 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1266 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
", "
1267 "ssn->server.next_win %" PRIu32
"",
1269 SCLogDebug(
"ssn %p: ssn->client.last_ack %" PRIu32
", "
1270 "ssn->server.last_ack %" PRIu32
"",
1278 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1279 "ssn->client.last_ts %" PRIu32
"",
1298 SCLogDebug(
"ssn %p: assuming SACK permitted for both sides", ssn);
1307 SCLogDebug(
"Midstream not enabled, so won't pick up a session");
1312 SCLogDebug(
"Midstream policy not permissive, so won't pick up a session");
1335 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1336 "TCP_SYN_RECV", ssn);
1367 SCLogDebug(
"ssn %p: wscale enabled. client %u server %u",
1371 SCLogDebug(
"ssn %p: ssn->client.isn %"PRIu32
", ssn->client.next_seq"
1372 " %"PRIu32
", ssn->client.last_ack %"PRIu32
"", ssn,
1375 SCLogDebug(
"ssn %p: ssn->server.isn %"PRIu32
", ssn->server.next_seq"
1376 " %"PRIu32
", ssn->server.last_ack %"PRIu32
"", ssn,
1385 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1386 "ssn->client.last_ts %" PRIu32
"", ssn,
1404 SCLogDebug(
"ssn %p: SYN/ACK with SACK permitted, assuming "
1405 "SACK permitted for both sides", ssn);
1423 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_SYN_SENT", ssn);
1456 SCLogDebug(
"ssn %p: SACK permitted on SYN packet", ssn);
1463 SCLogDebug(
"ssn: %p (TFO) isn %u base_seq %u next_seq %u payload len %u", ssn,
1471 SCLogDebug(
"ssn %p: ssn->client.isn %" PRIu32
", "
1472 "ssn->client.next_seq %" PRIu32
", ssn->client.last_ack "
1482 SCLogDebug(
"Midstream not enabled, so won't pick up a session");
1487 SCLogDebug(
"Midstream policy not permissive, so won't pick up a session");
1504 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1505 "TCP_ESTABLISHED", ssn);
1526 SCLogDebug(
"ssn %p: ssn->client.isn %u, ssn->client.next_seq %u",
1535 SCLogDebug(
"ssn %p: ssn->client.next_win %"PRIu32
", "
1536 "ssn->server.next_win %"PRIu32
"", ssn,
1538 SCLogDebug(
"ssn %p: ssn->client.last_ack %"PRIu32
", "
1539 "ssn->server.last_ack %"PRIu32
"", ssn,
1547 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1548 "ssn->client.last_ts %" PRIu32
"", ssn,
1567 SCLogDebug(
"ssn %p: assuming SACK permitted for both sides", ssn);
1581 const TCPHdr *tcph = PacketGetTCP(
p);
1611 StreamTcp3whsSynAckToStateQueue(
p, &search);
1619 search.
ts == q->
ts) {
1632 if (StreamTcp3whsFindSynAckBySynAck(ssn,
p) != NULL)
1636 SCLogDebug(
"ssn %p: =~ SYN/ACK queue limit reached", ssn);
1642 SCLogDebug(
"ssn %p: =~ SYN/ACK queue failed: stream memcap reached", ssn);
1648 SCLogDebug(
"ssn %p: =~ SYN/ACK queue failed: alloc failed", ssn);
1653 StreamTcp3whsSynAckToStateQueue(
p, q);
1667 const TCPHdr *tcph = PacketGetTCP(
p);
1702 StreamTcp3whsSynAckToStateQueue(
p, &update);
1709 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_SYN_RECV", ssn);
1725 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1726 "ssn->client.last_ts %" PRIu32
"", ssn,
1754 SCLogDebug(
"ssn %p: SACK permitted for session", ssn);
1761 SCLogDebug(
"ssn %p: ssn->server.next_win %" PRIu32
"", ssn,
1763 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
"", ssn,
1765 SCLogDebug(
"ssn %p: ssn->server.isn %" PRIu32
", "
1766 "ssn->server.next_seq %" PRIu32
", "
1767 "ssn->server.last_ack %" PRIu32
" "
1768 "(ssn->client.last_ack %" PRIu32
")", ssn,
1775 SCLogDebug(
"ssn %p: STREAMTCP_FLAG_4WHS unset, normal SYN/ACK"
1776 " so considering 3WHS", ssn);
1797 if (receiver_stream->
last_ts != 0 && ts_echo != 0 &&
1798 ts_echo != receiver_stream->
last_ts)
1801 ts_echo, receiver_stream->
last_ts);
1805 if (receiver_stream->
last_ts == 0 && ts_echo != 0) {
1807 ts_echo, receiver_stream->
last_ts);
1817 memset(q, 0,
sizeof(*q));
1838 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1844 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1848 memset(q, 0,
sizeof(*q));
1849 const TCPHdr *tcph = PacketGetTCP(
p);
1868 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1875 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1879 memset(q, 0,
sizeof(*q));
1881 const TCPHdr *tcph = PacketGetTCP(
p);
1899 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1915 SCLogDebug(
"ssn %p: search state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, s, s->
seq, s->
win,
1920 SCLogDebug(
"ssn %p: queue state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u (last:%s)", ssn, q,
1928 }
else if (ignore_ts) {
1947 if (
tail == old_head) {
1949 *old_head = *search;
1950 old_head->
next = NULL;
1956 tail->next = old_head;
1958 *old_head = *search;
1959 old_head->
next = NULL;
1965 TcpStateQueueInitFromSsnSyn(ssn, &search);
1969 if (ssn->
queue != NULL && StreamTcp3whsFindSyn(ssn, &search, &
tail,
false) != NULL)
1978 AddAndRotate(ssn,
tail, &search);
1983 SCLogDebug(
"ssn %p: =~ SYN queue failed: stream memcap reached", ssn);
1989 SCLogDebug(
"ssn %p: =~ SYN queue failed: alloc failed", ssn);
2043 static inline bool StateSynSentCheckSynAck3Whs(
TcpSession *ssn,
Packet *
p,
const bool ts_mismatch)
2045 const TCPHdr *tcph = PacketGetTCP(
p);
2047 if (seq_match && !ts_mismatch) {
2052 if (ssn->
queue == NULL) {
2057 TcpStateQueueInitFromPktSynAck(
p, &search);
2068 SCLogDebug(
"ssn %p: found queued SYN state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q,
2070 StreamTcp3whsStoreSynApplyToSsn(ssn, q);
2075 }
else if (ts_mismatch) {
2089 static inline bool StateSynSentCheckSynAckTFO(
TcpSession *ssn,
Packet *
p,
const bool ts_mismatch)
2091 const TCPHdr *tcph = PacketGetTCP(
p);
2094 if (seq_match_tfo && !ts_mismatch) {
2096 }
else if (seq_match_nodata && !ts_mismatch) {
2103 if (ssn->
queue == NULL) {
2108 TcpStateQueueInitFromPktSynAck(
p, &search);
2119 SCLogDebug(
"ssn %p: found queued SYN state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q,
2121 StreamTcp3whsStoreSynApplyToSsn(ssn, q);
2126 if (!seq_match_tfo && !seq_match_nodata) {
2128 }
else if (ts_mismatch) {
2144 static int StreamTcpPacketStateSynSent(
2148 const TCPHdr *tcph = PacketGetTCP(
p);
2154 SCLogDebug(
"%" PRIu64
": ssn %p: SYN/ACK on SYN_SENT state for packet %" PRIu64,
2158 const bool ts_mismatch =
2163 if (StateSynSentCheckSynAck3Whs(ssn,
p, ts_mismatch)) {
2164 SCLogDebug(
"ssn %p: ACK match, packet ACK %" PRIu32
" == "
2165 "%" PRIu32
" from stream",
2168 SCLogDebug(
"ssn %p: (3WHS) ACK mismatch, packet ACK %" PRIu32
" != "
2169 "%" PRIu32
" from stream",
2174 if (StateSynSentCheckSynAckTFO(ssn,
p, ts_mismatch)) {
2175 SCLogDebug(
"ssn %p: (TFO) ACK matches next_seq, packet ACK %" PRIu32
" == "
2176 "%" PRIu32
" from stream",
2179 SCLogDebug(
"ssn %p: (TFO) ACK mismatch, packet ACK %" PRIu32
" != "
2180 "%" PRIu32
" from stream",
2186 StreamTcp3wsFreeQueue(ssn);
2188 StreamTcp3whsSynAckUpdate(ssn,
p, NULL);
2197 SCLogDebug(
"ssn %p: SYN/ACK received in the wrong direction", ssn);
2201 SCLogDebug(
"ssn %p: SYN/ACK received on 4WHS session", ssn);
2208 SCLogDebug(
"ssn %p: 4WHS ACK mismatch, packet ACK %" PRIu32
""
2209 " != %" PRIu32
" from stream",
2219 SCLogDebug(
"ssn %p: 4WHS SEQ mismatch, packet SEQ %" PRIu32
""
2220 " != %" PRIu32
" from *first* SYN pkt",
2227 SCLogDebug(
"ssn %p: =~ 4WHS ssn state is now TCP_SYN_RECV", ssn);
2241 SCLogDebug(
"ssn %p: 4WHS ssn->client.last_ts %" PRIu32
" "
2242 "ssn->server.last_ts %" PRIu32
"",
2267 SCLogDebug(
"ssn %p: SACK permitted for 4WHS session", ssn);
2274 SCLogDebug(
"ssn %p: 4WHS ssn->client.isn %" PRIu32
", "
2275 "ssn->client.next_seq %" PRIu32
", "
2276 "ssn->client.last_ack %" PRIu32
" "
2277 "(ssn->server.last_ack %" PRIu32
")",
2286 if (!StateSynSentValidateTimestamp(ssn,
p)) {
2294 if (!StreamTcpValidateRst(ssn,
p))
2301 SCLogDebug(
"ssn->server.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2303 StreamTcpCloseSsnWithReset(
p, ssn);
2304 StreamTcp3wsFreeQueue(ssn);
2308 SCLogDebug(
"ssn->client.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2309 StreamTcpCloseSsnWithReset(
p, ssn);
2310 StreamTcp3wsFreeQueue(ssn);
2318 SCLogDebug(
"ssn %p: SYN packet on state SYN_SENT... resent", ssn);
2320 SCLogDebug(
"ssn %p: SYN packet on state SYN_SENT... resent of "
2333 SCLogDebug(
"ssn %p: STREAMTCP_FLAG_4WHS flag set", ssn);
2370 SCLogDebug(
"ssn %p: 4WHS ssn->server.isn %" PRIu32
", "
2371 "ssn->server.next_seq %" PRIu32
", "
2372 "ssn->server.last_ack %"PRIu32
"", ssn,
2375 SCLogDebug(
"ssn %p: 4WHS ssn->client.isn %" PRIu32
", "
2376 "ssn->client.next_seq %" PRIu32
", "
2377 "ssn->client.last_ack %"PRIu32
"", ssn,
2386 TcpStateQueueInitFromPktSyn(
p, &syn_pkt);
2387 TcpStateQueueInitFromSsnSyn(ssn, &syn_ssn);
2389 if (memcmp(&syn_pkt, &syn_ssn,
sizeof(
TcpStateQueue)) != 0) {
2391 StreamTcp3whsStoreSyn(ssn,
p);
2392 SCLogDebug(
"ssn %p: Retransmitted SYN. Updating ssn from packet %" PRIu64
2393 ". Stored previous state",
2396 StreamTcp3whsStoreSynApplyToSsn(ssn, &syn_pkt);
2412 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
2413 "%" PRIu32
" from stream",
2420 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2421 StreamTcp3wsFreeQueue(ssn);
2434 SCLogDebug(
"ssn %p: synsent => Asynchronous stream, packet SEQ"
2435 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2436 "ssn->client.next_seq %" PRIu32
"",
2485 static int StreamTcpPacketStateSynRecv(
2489 const TCPHdr *tcph = PacketGetTCP(
p);
2492 if (!StreamTcpValidateRst(ssn,
p))
2509 SCLogDebug(
"Detection evasion has been attempted, so"
2510 " not resetting the connection !!");
2518 SCLogDebug(
"Detection evasion has been attempted, so"
2519 " not resetting the connection !!");
2525 StreamTcpCloseSsnWithReset(
p, ssn);
2528 StreamTcpHandleTimestamp(ssn,
p);
2535 if (!StreamTcpValidateTimestamp(ssn,
p))
2539 if ((StreamTcpHandleFin(
tv, stt, ssn,
p)) == -1)
2544 SCLogDebug(
"ssn %p: SYN/ACK packet on state SYN_RECV. resent", ssn);
2547 SCLogDebug(
"ssn %p: SYN/ACK-pkt to server in SYN_RECV state", ssn);
2556 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
2557 "%" PRIu32
" from stream",
2567 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
2568 "%" PRIu32
" from stream",
2571 if (StreamTcp3whsQueueSynAck(ssn,
p) == -1)
2573 SCLogDebug(
"ssn %p: queued different SYN/ACK", ssn);
2577 SCLogDebug(
"ssn %p: SYN packet on state SYN_RECV... resent", ssn);
2580 SCLogDebug(
"ssn %p: SYN-pkt to client in SYN_RECV state", ssn);
2587 SCLogDebug(
"ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
2595 SCLogDebug(
"ssn %p: checking ACK against queued SYN/ACKs", ssn);
2598 SCLogDebug(
"ssn %p: here we update state against queued SYN/ACK", ssn);
2599 StreamTcp3whsSynAckUpdate(ssn,
p, q);
2601 SCLogDebug(
"ssn %p: none found, now checking ACK against original SYN/ACK (state)", ssn);
2611 if (!(StreamTcpValidateTimestamp(ssn,
p))) {
2617 SCLogDebug(
"ssn %p: ACK received on 4WHS session",ssn);
2620 SCLogDebug(
"ssn %p: 4WHS wrong seq nr on packet", ssn);
2625 if (StreamTcpValidateAck(ssn, &ssn->
client,
p) == -1) {
2626 SCLogDebug(
"ssn %p: 4WHS invalid ack nr on packet", ssn);
2632 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
2633 "%" PRIu32
", ACK %" PRIu32
"",
2637 StreamTcpHandleTimestamp(ssn,
p);
2646 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2650 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
", "
2651 "ssn->client.last_ack %"PRIu32
"", ssn,
2656 bool ack_indicates_missed_3whs_ack_packet =
false;
2666 SCLogDebug(
"ssn %p: ACK received on midstream SYN/ACK "
2667 "pickup session",ssn);
2670 SCLogDebug(
"ssn %p: ACK received on TFO session",ssn);
2687 SCLogDebug(
"ssn %p: possible data injection", ssn);
2692 SCLogDebug(
"ssn %p: ACK received in the wrong direction",
2697 ack_indicates_missed_3whs_ack_packet =
true;
2701 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ %" PRIu32
""
2702 ", ACK %" PRIu32
"",
2714 StreamTcpHandleTimestamp(ssn,
p);
2738 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2764 StreamTcpHandleTimestamp(ssn,
p);
2777 SCLogDebug(
"ssn %p: synrecv => Asynchronous stream, packet SEQ"
2778 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2779 "ssn->server.next_seq %" PRIu32,
2784 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2793 SCLogDebug(
"ssn %p: wrong ack nr on packet, possible evasion!!",
2803 SCLogDebug(
"ssn %p: ACK for missing data", ssn);
2806 StreamTcpHandleTimestamp(ssn,
p);
2812 SCLogDebug(
"ssn %p: ACK for missing data: ssn->server.next_seq %u", ssn,
2822 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2831 SCLogDebug(
"ssn %p: ACK for missing data", ssn);
2834 StreamTcpHandleTimestamp(ssn,
p);
2856 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2861 }
else if ((ack_indicates_missed_3whs_ack_packet ||
2865 if (ack_indicates_missed_3whs_ack_packet) {
2866 SCLogDebug(
"ssn %p: packet fits perfectly after a missed 3whs-ACK", ssn);
2868 SCLogDebug(
"ssn %p: (TFO) expected packet fits perfectly after SYN/ACK", ssn);
2877 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2882 SCLogDebug(
"ssn %p: wrong seq nr on packet", ssn);
2888 SCLogDebug(
"ssn %p: ssn->server.next_win %" PRIu32
", "
2889 "ssn->server.last_ack %"PRIu32
"", ssn,
2911 static int HandleEstablishedPacketToServer(
2914 const TCPHdr *tcph = PacketGetTCP(
p);
2919 SCLogDebug(
"ssn %p: =+ pkt (%" PRIu32
") is to server: SEQ %" PRIu32
","
2920 "ACK %" PRIu32
", WIN %" PRIu16
"",
2926 SCLogDebug(
"ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
2929 }
else if (StreamTcpValidateAck(ssn, &ssn->
server,
p) == -1) {
2930 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
2938 SCLogDebug(
"ssn %p: pkt is keep alive", ssn);
2943 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ"
2944 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
2945 " ssn->client.last_ack %" PRIu32
", ssn->client.next_win"
2946 "%" PRIu32
"(%" PRIu32
")",
2956 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ."
2957 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2958 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2959 "%" PRIu32
"(%" PRIu32
")",
2971 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ"
2972 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2973 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2974 "%" PRIu32
"(%" PRIu32
")",
2989 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
2990 " before last_ack %" PRIu32
", after next_seq %" PRIu32
":"
2991 " acked data that we haven't seen before",
2994 SCLogDebug(
"ssn %p: server => SEQ before last_ack, packet SEQ"
2995 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2996 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2997 "%" PRIu32
"(%" PRIu32
")",
3001 SCLogDebug(
"ssn %p: rejecting because pkt before last_ack", ssn);
3007 int zerowindowprobe = 0;
3010 SCLogDebug(
"ssn %p: zero window probe", ssn);
3011 zerowindowprobe = 1;
3021 if (zerowindowprobe) {
3022 SCLogDebug(
"ssn %p: zero window probe, skipping oow check", ssn);
3025 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
3030 SCLogDebug(
"ssn %p: ssn->server.window %"PRIu32
"", ssn,
3047 StreamTcpHandleTimestamp(ssn,
p);
3059 SCLogDebug(
"ssn %p: toserver => SEQ out of window, packet SEQ "
3060 "%" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3061 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
3062 "%" PRIu32
"(%" PRIu32
")",
3066 StreamTcpSackedSize(&ssn->
client));
3086 static int HandleEstablishedPacketToClient(
3089 const TCPHdr *tcph = PacketGetTCP(
p);
3094 SCLogDebug(
"ssn %p: =+ pkt (%" PRIu32
") is to client: SEQ %" PRIu32
","
3095 " ACK %" PRIu32
", WIN %" PRIu16
"",
3101 SCLogDebug(
"ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
3104 }
else if (StreamTcpValidateAck(ssn, &ssn->
client,
p) == -1) {
3105 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3119 SCLogDebug(
"ssn %p: adjusted midstream ssn->server.next_win to "
3125 SCLogDebug(
"ssn %p: pkt is keep alive", ssn);
3131 SCLogDebug(
"ssn %p: client => Asynchronous stream, packet SEQ"
3132 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3133 " ssn->client.last_ack %" PRIu32
", ssn->client.next_win"
3134 " %" PRIu32
"(%" PRIu32
")",
3145 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
3146 " before last_ack %" PRIu32
", after next_seq %" PRIu32
":"
3147 " acked data that we haven't seen before",
3150 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
3151 " before last_ack %" PRIu32
". next_seq %" PRIu32,
3158 int zerowindowprobe = 0;
3161 SCLogDebug(
"ssn %p: zero window probe", ssn);
3162 zerowindowprobe = 1;
3173 if (zerowindowprobe) {
3174 SCLogDebug(
"ssn %p: zero window probe, skipping oow check", ssn);
3177 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
3181 SCLogDebug(
"ssn %p: ssn->client.window %"PRIu32
"", ssn,
3194 StreamTcpHandleTimestamp(ssn,
p);
3203 SCLogDebug(
"ssn %p: client => SEQ out of window, packet SEQ"
3204 "%" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3205 " ssn->server.last_ack %" PRIu32
", ssn->server.next_win "
3206 "%" PRIu32
"(%" PRIu32
")",
3215 static bool StreamTcpPacketIsZeroWindowProbeAck(
const TcpSession *ssn,
const Packet *
p)
3217 const TCPHdr *tcph = PacketGetTCP(
p);
3241 if (pkt_win != rcv->
window)
3257 const TCPHdr *tcph = PacketGetTCP(
p);
3275 if (pkt_win == 0 || rcv->
window == 0)
3277 if (pkt_win != rcv->
window)
3285 SCLogDebug(
"ssn %p: packet:%" PRIu64
" seq:%u ack:%u win:%u snd %u:%u:%u rcv %u:%u:%u", ssn,
3309 const TCPHdr *tcph = PacketGetTCP(
p);
3360 static int StreamTcpPacketIsSpuriousRetransmission(
const TcpSession *ssn,
Packet *
p)
3371 const TCPHdr *tcph = PacketGetTCP(
p);
3377 "ssn %p: spurious retransmission; packet entirely before base_seq: SEQ %u(%u) "
3378 "last_ack %u base_seq %u",
3387 SCLogDebug(
"ssn %p: spurious retransmission; packet entirely before last_ack: SEQ %u(%u) "
3395 SCLogDebug(
"ssn %p: NOT spurious retransmission; packet NOT entirely before last_ack: SEQ "
3396 "%u(%u) last_ack %u, base_seq %u",
3413 static int StreamTcpPacketStateEstablished(
3417 const TCPHdr *tcph = PacketGetTCP(
p);
3423 if (!StreamTcpValidateRst(ssn,
p))
3427 StreamTcpCloseSsnWithReset(
p, ssn);
3431 SCLogDebug(
"ssn %p: ssn->server.next_seq %" PRIu32
"", ssn,
3441 StreamTcpHandleTimestamp(ssn,
p);
3445 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3453 StreamTcpCloseSsnWithReset(
p, ssn);
3458 SCLogDebug(
"ssn %p: ssn->server.next_seq %" PRIu32
"", ssn,
3468 StreamTcpHandleTimestamp(ssn,
p);
3472 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3483 if (!StreamTcpValidateTimestamp(ssn,
p))
3488 " %" PRIu32
", last ACK %" PRIu32
", next win %"PRIu32
","
3493 if ((StreamTcpHandleFin(
tv, stt, ssn,
p)) == -1)
3498 SCLogDebug(
"ssn %p: SYN/ACK packet on state ESTABLISHED... resent",
3502 SCLogDebug(
"ssn %p: SYN/ACK-pkt to server in ESTABLISHED state", ssn);
3511 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
3512 "%" PRIu32
" from stream",
3522 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
3523 "%" PRIu32
" from stream",
3536 SCLogDebug(
"ssn %p: SYN/ACK packet on state ESTABLISHED... resent. "
3537 "Likely due server not receiving final ACK in 3whs", ssn);
3541 SCLogDebug(
"ssn %p: SYN packet on state ESTABLISHED... resent", ssn);
3543 SCLogDebug(
"ssn %p: SYN-pkt to client in EST state", ssn);
3550 SCLogDebug(
"ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
3571 if (!StreamTcpValidateTimestamp(ssn,
p))
3577 HandleEstablishedPacketToServer(
tv, ssn,
p, stt);
3579 SCLogDebug(
"ssn %p: next SEQ %" PRIu32
", last ACK %" PRIu32
","
3580 " next win %" PRIu32
", win %" PRIu32
"", ssn,
3587 SCLogDebug(
"3whs is now confirmed by server");
3591 HandleEstablishedPacketToClient(
tv, ssn,
p, stt);
3593 SCLogDebug(
"ssn %p: next SEQ %" PRIu32
", last ACK %" PRIu32
","
3594 " next win %" PRIu32
", win %" PRIu32
"", ssn,
3619 const TCPHdr *tcph = PacketGetTCP(
p);
3625 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ %" PRIu32
","
3629 if (StreamTcpValidateAck(ssn, &ssn->
server,
p) == -1) {
3630 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3636 SCLogDebug(
"ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn,
seq, pkt_re,
3641 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
" != "
3642 "%" PRIu32
" from stream",
3655 SCLogDebug(
"ssn %p: state changed to TCP_CLOSE_WAIT", ssn);
3660 SCLogDebug(
"ssn %p: ssn->client.next_seq %" PRIu32
"", ssn,
3665 StreamTcpHandleTimestamp(ssn,
p);
3678 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK %" PRIu32
"",
3681 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ %" PRIu32
", "
3685 if (StreamTcpValidateAck(ssn, &ssn->
client,
p) == -1) {
3686 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3692 SCLogDebug(
"ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn,
seq, pkt_re,
3697 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
" != "
3698 "%" PRIu32
" from stream (last_ack %u win %u = %u)",
3707 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT1", ssn);
3716 StreamTcpHandleTimestamp(ssn,
p);
3729 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK %" PRIu32
"",
3749 static int StreamTcpPacketStateFinWait1(
3753 const TCPHdr *tcph = PacketGetTCP(
p);
3759 if (!StreamTcpValidateRst(ssn,
p))
3762 StreamTcpCloseSsnWithReset(
p, ssn);
3771 StreamTcpHandleTimestamp(ssn,
p);
3782 StreamTcpHandleTimestamp(ssn,
p);
3790 if (!StreamTcpValidateTimestamp(ssn,
p))
3795 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3796 "%" PRIu32
", ACK %" PRIu32
"",
3798 int retransmission = 0;
3800 if (StreamTcpPacketIsRetransmission(&ssn->
client,
p)) {
3801 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3807 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3808 " != %" PRIu32
" from stream",
3814 if (StreamTcpValidateAck(ssn, &ssn->
server,
p) == -1) {
3815 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3820 if (!retransmission) {
3822 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
3828 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
"",
3851 int retransmission = 0;
3853 if (StreamTcpPacketIsRetransmission(&ssn->
server,
p)) {
3854 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3859 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3865 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3866 " != %" PRIu32
" from stream",
3872 if (StreamTcpValidateAck(ssn, &ssn->
client,
p) == -1) {
3873 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3879 StreamTcpHandleTimestamp(ssn,
p);
3882 if (!retransmission) {
3884 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
3902 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3909 if (!StreamTcpValidateTimestamp(ssn,
p))
3914 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3915 "%" PRIu32
", ACK %" PRIu32
"",
3917 int retransmission = 0;
3919 if (StreamTcpPacketIsRetransmission(&ssn->
client,
p)) {
3920 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3926 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3927 " != %" PRIu32
" from stream",
3933 if (StreamTcpValidateAck(ssn, &ssn->
server,
p) == -1) {
3934 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3939 if (!retransmission) {
3941 SCLogDebug(
"ssn %p: state changed to TCP_CLOSING", ssn);
3947 StreamTcpHandleTimestamp(ssn,
p);
3964 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3968 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3969 "%" PRIu32
", ACK %" PRIu32
"",
3972 int retransmission = 0;
3974 if (StreamTcpPacketIsRetransmission(&ssn->
server,
p)) {
3975 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3981 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3982 " != %" PRIu32
" from stream",
3988 if (StreamTcpValidateAck(ssn, &ssn->
client,
p) == -1) {
3989 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3994 if (!retransmission) {
3996 SCLogDebug(
"ssn %p: state changed to TCP_CLOSING", ssn);
4002 StreamTcpHandleTimestamp(ssn,
p);
4019 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4024 SCLogDebug(
"ssn (%p): SYN pkt on FinWait1", ssn);
4030 if (!StreamTcpValidateTimestamp(ssn,
p))
4035 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4036 "%" PRIu32
", ACK %" PRIu32
"",
4038 int retransmission = 0;
4040 if (StreamTcpPacketIsRetransmission(&ssn->
client,
p)) {
4041 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4046 if (StreamTcpValidateAck(ssn, &ssn->
server,
p) == -1) {
4047 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4054 "ssn %p: ACK's older segment as %u < %u", ssn, ack, ssn->
server.
next_seq);
4055 }
else if (!retransmission) {
4059 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
4065 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT2", ssn);
4068 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4069 " != %" PRIu32
" from stream",
4081 StreamTcpHandleTimestamp(ssn,
p);
4102 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4108 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4109 "%" PRIu32
", ACK %" PRIu32
"",
4112 int retransmission = 0;
4114 if (StreamTcpPacketIsRetransmission(&ssn->
server,
p)) {
4115 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4120 if (StreamTcpValidateAck(ssn, &ssn->
client,
p) == -1) {
4121 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4126 if (!retransmission) {
4129 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
4135 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT2", ssn);
4138 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4139 " != %" PRIu32
" from stream",
4149 StreamTcpHandleTimestamp(ssn,
p);
4170 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4191 static int StreamTcpPacketStateFinWait2(
4195 const TCPHdr *tcph = PacketGetTCP(
p);
4201 if (!StreamTcpValidateRst(ssn,
p))
4204 StreamTcpCloseSsnWithReset(
p, ssn);
4213 StreamTcpHandleTimestamp(ssn,
p);
4224 StreamTcpHandleTimestamp(ssn,
p);
4232 if (!StreamTcpValidateTimestamp(ssn,
p))
4237 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4238 "%" PRIu32
", ACK %" PRIu32
"",
4240 int retransmission = 0;
4246 }
else if (StreamTcpPacketIsRetransmission(&ssn->
client,
p)) {
4247 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4253 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ "
4254 "%" PRIu32
" != %" PRIu32
" from stream",
4260 if (StreamTcpValidateAck(ssn, &ssn->
server,
p) == -1) {
4261 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4266 if (!retransmission) {
4268 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4278 StreamTcpHandleTimestamp(ssn,
p);
4291 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4295 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4296 "%" PRIu32
", ACK %" PRIu32
"",
4298 int retransmission = 0;
4304 }
else if (StreamTcpPacketIsRetransmission(&ssn->
server,
p)) {
4305 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4311 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ "
4312 "%" PRIu32
" != %" PRIu32
" from stream",
4318 if (StreamTcpValidateAck(ssn, &ssn->
client,
p) == -1) {
4319 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4324 if (!retransmission) {
4326 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4332 StreamTcpHandleTimestamp(ssn,
p);
4344 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4350 SCLogDebug(
"ssn (%p): SYN pkt on FinWait2", ssn);
4356 if (!StreamTcpValidateTimestamp(ssn,
p))
4361 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4362 "%" PRIu32
", ACK %" PRIu32
"",
4364 int retransmission = 0;
4366 if (StreamTcpPacketIsRetransmission(&ssn->
client,
p)) {
4367 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4372 if (StreamTcpValidateAck(ssn, &ssn->
server,
p) == -1) {
4373 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4378 if (!retransmission) {
4381 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
4386 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4387 " != %" PRIu32
" from stream",
4397 StreamTcpHandleTimestamp(ssn,
p);
4413 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4417 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4418 "%" PRIu32
", ACK %" PRIu32
"",
4420 int retransmission = 0;
4422 if (StreamTcpPacketIsRetransmission(&ssn->
server,
p)) {
4423 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4428 if (StreamTcpValidateAck(ssn, &ssn->
client,
p) == -1) {
4429 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4434 if (!retransmission) {
4437 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
4441 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4442 " != %" PRIu32
" from stream",
4452 StreamTcpHandleTimestamp(ssn,
p);
4468 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4489 static int StreamTcpPacketStateClosing(
4493 const TCPHdr *tcph = PacketGetTCP(
p);
4499 if (!StreamTcpValidateRst(ssn,
p))
4502 StreamTcpCloseSsnWithReset(
p, ssn);
4511 StreamTcpHandleTimestamp(ssn,
p);
4522 StreamTcpHandleTimestamp(ssn,
p);
4529 SCLogDebug(
"ssn (%p): SYN pkt on Closing", ssn);
4535 if (!StreamTcpValidateTimestamp(ssn,
p))
4540 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4541 "%" PRIu32
", ACK %" PRIu32
"",
4543 int retransmission = 0;
4544 if (StreamTcpPacketIsRetransmission(&ssn->
client,
p)) {
4545 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4551 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4552 " != %" PRIu32
" from stream",
4558 if (StreamTcpValidateAck(ssn, &ssn->
server,
p) == -1) {
4559 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4564 if (!retransmission) {
4566 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4572 StreamTcpHandleTimestamp(ssn,
p);
4582 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4586 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4587 "%" PRIu32
", ACK %" PRIu32
"",
4589 int retransmission = 0;
4590 if (StreamTcpPacketIsRetransmission(&ssn->
server,
p)) {
4591 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4597 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4598 " != %" PRIu32
" from stream",
4604 if (StreamTcpValidateAck(ssn, &ssn->
client,
p) == -1) {
4605 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4610 if (!retransmission) {
4612 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4618 StreamTcpHandleTimestamp(ssn,
p);
4629 SCLogDebug(
"StreamTcpPacketStateClosing (%p): =+ next SEQ "
4630 "%" PRIu32
", last ACK %" PRIu32
"", ssn,
4650 static int StreamTcpPacketStateCloseWait(
4654 const TCPHdr *tcph = PacketGetTCP(
p);
4662 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4663 "%" PRIu32
", ACK %" PRIu32
"",
4666 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4667 "%" PRIu32
", ACK %" PRIu32
"",
4672 if (!StreamTcpValidateRst(ssn,
p))
4675 StreamTcpCloseSsnWithReset(
p, ssn);
4684 StreamTcpHandleTimestamp(ssn,
p);
4695 StreamTcpHandleTimestamp(ssn,
p);
4703 if (!StreamTcpValidateTimestamp(ssn,
p))
4708 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4709 "%" PRIu32
", ACK %" PRIu32
"",
4712 int retransmission = 0;
4713 if (StreamTcpPacketIsRetransmission(&ssn->
client,
p)) {
4714 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4719 if (!retransmission) {
4722 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4723 " != %" PRIu32
" from stream",
4730 if (StreamTcpValidateAck(ssn, &ssn->
server,
p) == -1) {
4731 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4738 if (!retransmission)
4742 StreamTcpHandleTimestamp(ssn,
p);
4754 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4758 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4759 "%" PRIu32
", ACK %" PRIu32
"",
4762 int retransmission = 0;
4763 if (StreamTcpPacketIsRetransmission(&ssn->
server,
p)) {
4764 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4769 if (!retransmission) {
4772 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4773 " != %" PRIu32
" from stream",
4780 if (StreamTcpValidateAck(ssn, &ssn->
client,
p) == -1) {
4781 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4786 if (!retransmission) {
4788 SCLogDebug(
"ssn %p: state changed to TCP_LAST_ACK", ssn);
4794 StreamTcpHandleTimestamp(ssn,
p);
4806 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4812 SCLogDebug(
"ssn (%p): SYN pkt on CloseWait", ssn);
4818 if (!StreamTcpValidateTimestamp(ssn,
p))
4823 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4824 "%" PRIu32
", ACK %" PRIu32
"",
4827 int retransmission = 0;
4828 if (StreamTcpPacketIsRetransmission(&ssn->
client,
p)) {
4829 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4835 SCLogDebug(
"ssn %p: -> retransmission", ssn);
4840 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4841 " != %" PRIu32
" from stream",
4847 if (StreamTcpValidateAck(ssn, &ssn->
server,
p) == -1) {
4848 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4853 if (!retransmission) {
4858 StreamTcpHandleTimestamp(ssn,
p);
4872 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4876 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4877 "%" PRIu32
", ACK %" PRIu32
"",
4879 int retransmission = 0;
4880 if (StreamTcpPacketIsRetransmission(&ssn->
server,
p)) {
4881 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4887 SCLogDebug(
"ssn %p: -> retransmission", ssn);
4892 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4893 " != %" PRIu32
" from stream",
4899 if (StreamTcpValidateAck(ssn, &ssn->
client,
p) == -1) {
4900 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4905 if (!retransmission) {
4910 StreamTcpHandleTimestamp(ssn,
p);
4924 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4945 static int StreamTcpPacketStateLastAck(
4949 const TCPHdr *tcph = PacketGetTCP(
p);
4955 if (!StreamTcpValidateRst(ssn,
p))
4958 StreamTcpCloseSsnWithReset(
p, ssn);
4967 StreamTcpHandleTimestamp(ssn,
p);
4978 StreamTcpHandleTimestamp(ssn,
p);
4986 SCLogDebug(
"ssn (%p): FIN pkt on LastAck", ssn);
4989 SCLogDebug(
"ssn (%p): SYN pkt on LastAck", ssn);
4995 if (!StreamTcpValidateTimestamp(ssn,
p))
5000 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
5001 "%" PRIu32
", ACK %" PRIu32
"",
5004 int retransmission = 0;
5005 if (StreamTcpPacketIsRetransmission(&ssn->
client,
p)) {
5006 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
5011 if (StreamTcpValidateAck(ssn, &ssn->
server,
p) == -1) {
5012 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5017 if (!retransmission) {
5019 SCLogDebug(
"ssn %p: not updating state as packet is before next_seq", ssn);
5021 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5022 " != %" PRIu32
" from stream",
5028 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5034 StreamTcpHandleTimestamp(ssn,
p);
5045 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5066 static int StreamTcpPacketStateTimeWait(
5070 const TCPHdr *tcph = PacketGetTCP(
p);
5076 if (!StreamTcpValidateRst(ssn,
p))
5079 StreamTcpCloseSsnWithReset(
p, ssn);
5088 StreamTcpHandleTimestamp(ssn,
p);
5099 StreamTcpHandleTimestamp(ssn,
p);
5109 SCLogDebug(
"ssn (%p): SYN pkt on TimeWait", ssn);
5115 if (!StreamTcpValidateTimestamp(ssn,
p))
5120 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
5121 "%" PRIu32
", ACK %" PRIu32
"",
5123 int retransmission = 0;
5124 if (StreamTcpPacketIsRetransmission(&ssn->
client,
p)) {
5125 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
5130 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5131 " != %" PRIu32
" from stream",
5137 if (StreamTcpValidateAck(ssn, &ssn->
server,
p) == -1) {
5138 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5143 if (!retransmission) {
5145 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5151 StreamTcpHandleTimestamp(ssn,
p);
5162 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5166 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
5167 "%" PRIu32
", ACK %" PRIu32
"",
5169 int retransmission = 0;
5170 if (StreamTcpPacketIsRetransmission(&ssn->
server,
p)) {
5171 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
5176 SCLogDebug(
"ssn %p: -> retransmission", ssn);
5179 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5180 " != %" PRIu32
" from stream",
5187 if (StreamTcpValidateAck(ssn, &ssn->
client,
p) == -1) {
5188 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5193 if (!retransmission) {
5195 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5201 StreamTcpHandleTimestamp(ssn,
p);
5212 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5224 static int StreamTcpPacketStateClosed(
5229 const TCPHdr *tcph = PacketGetTCP(
p);
5235 TcpStream *stream = NULL, *ostream = NULL;
5252 if (StreamTcpStateDispatch(
tv,
p, stt, ssn, ssn->
pstate) < 0)
5267 const TCPHdr *tcph = PacketGetTCP(
p);
5281 SCLogDebug(
"regular packet %" PRIu64
" from same sender as "
5282 "the previous RST. Looks like it injected!",
5309 const TCPHdr *tcph = PacketGetTCP(
p);
5314 TcpStream *stream = NULL, *ostream = NULL;
5325 if (ack == ostream->last_ack &&
seq == (stream->
next_seq - 1)) {
5341 TcpStream *stream = NULL, *ostream = NULL;
5352 const TCPHdr *tcph = PacketGetTCP(
p);
5371 if (pkt_win != ostream->window)
5380 SCLogDebug(
"seq %u (%u), ack %u (%u) FLAG_KEEPALIVE: %s",
seq, stream->
next_seq, ack, ostream->last_ack,
5410 TcpStream *stream = NULL, *ostream = NULL;
5424 const TCPHdr *tcph = PacketGetTCP(
p);
5443 if (pkt_win == ostream->window)
5446 if (ack == ostream->last_ack &&
seq == stream->
next_seq) {
5461 TcpStream *stream = NULL, *ostream = NULL;
5469 const TCPHdr *tcph = PacketGetTCP(
p);
5486 SCLogDebug(
"%" PRIu64
", seq %u ack %u stream->next_seq %u ostream->next_seq %u",
5514 TcpStream *stream = NULL, *ostream = NULL;
5525 const TCPHdr *tcph = PacketGetTCP(
p);
5541 if (pkt_win < ostream->window) {
5542 uint32_t diff = ostream->window - pkt_win;
5544 SEQ_GT(ack, ostream->next_seq) &&
5547 SCLogDebug(
"%" PRIu64
", pkt_win %u, stream win %u, diff %u, dsize %u",
5551 SCLogDebug(
"%" PRIu64
", seq %u ack %u ostream->next_seq %u ostream->last_ack %u, "
5552 "ostream->next_win %u, diff %u (%u)",
5554 ostream->next_win, ostream->next_seq - ostream->last_ack,
5562 uint32_t adiff = ack - ostream->last_ack;
5563 if (((pkt_win > 1024) && (diff > (adiff + 32))) ||
5564 ((pkt_win <= 1024) && (diff > adiff)))
5566 SCLogDebug(
"pkt ACK %u is %u bytes beyond last_ack %u, shrinks window by %u "
5567 "(allowing 32 bytes extra): pkt WIN %u", ack, adiff, ostream->last_ack, diff, pkt_win);
5568 SCLogDebug(
"%u - %u = %u (state %u)", diff, adiff, diff - adiff, ssn->
state);
5583 static inline int StreamTcpStateDispatch(
5591 SCLogDebug(
"packet received on TCP_SYN_SENT state");
5592 if (StreamTcpPacketStateSynSent(
tv,
p, stt, ssn)) {
5597 SCLogDebug(
"packet received on TCP_SYN_RECV state");
5598 if (StreamTcpPacketStateSynRecv(
tv,
p, stt, ssn)) {
5603 SCLogDebug(
"packet received on TCP_ESTABLISHED state");
5604 if (StreamTcpPacketStateEstablished(
tv,
p, stt, ssn)) {
5609 SCLogDebug(
"packet received on TCP_FIN_WAIT1 state");
5610 if (StreamTcpPacketStateFinWait1(
tv,
p, stt, ssn)) {
5615 SCLogDebug(
"packet received on TCP_FIN_WAIT2 state");
5616 if (StreamTcpPacketStateFinWait2(
tv,
p, stt, ssn)) {
5621 SCLogDebug(
"packet received on TCP_CLOSING state");
5622 if (StreamTcpPacketStateClosing(
tv,
p, stt, ssn)) {
5627 SCLogDebug(
"packet received on TCP_CLOSE_WAIT state");
5628 if (StreamTcpPacketStateCloseWait(
tv,
p, stt, ssn)) {
5633 SCLogDebug(
"packet received on TCP_LAST_ACK state");
5634 if (StreamTcpPacketStateLastAck(
tv,
p, stt, ssn)) {
5639 SCLogDebug(
"packet received on TCP_TIME_WAIT state");
5640 if (StreamTcpPacketStateTimeWait(
tv,
p, stt, ssn)) {
5646 SCLogDebug(
"packet received on closed state");
5648 if (StreamTcpPacketStateClosed(
tv,
p, stt, ssn)) {
5654 SCLogDebug(
"packet received on default state");
5690 const TCPHdr *tcph = PacketGetTCP(
p);
5705 SCLogDebug(
"ssn %p: removing ASYNC flag as we have packets on both sides", ssn);
5725 if (StreamTcpCheckFlowDrops(
p) == 1) {
5735 if (StreamTcpPacketStateNone(
tv,
p, stt, ssn) == -1) {
5762 if (StreamTcpPacketIsKeepAlive(ssn,
p) == 1) {
5765 if (StreamTcpPacketIsKeepAliveACK(ssn,
p) == 1) {
5766 StreamTcpClearKeepAliveFlag(ssn,
p);
5769 StreamTcpClearKeepAliveFlag(ssn,
p);
5771 const bool is_zwp_ack = StreamTcpPacketIsZeroWindowProbeAck(ssn,
p);
5782 if (StreamTcpPacketIsDupAck(ssn,
p)) {
5789 if (StreamTcpPacketIsFinShutdownAck(ssn,
p) == 0) {
5790 if (StreamTcpPacketIsWindowUpdate(ssn,
p) == 0) {
5791 if (StreamTcpPacketIsBadWindowUpdate(ssn,
p))
5793 if (StreamTcpPacketIsOutdatedAck(ssn,
p))
5798 int ret = StreamTcpPacketIsSpuriousRetransmission(ssn,
p);
5807 if (StreamTcpStateDispatch(
tv,
p, stt, ssn, ssn->
state) < 0)
5811 StreamTcpPacketCheckPostRst(ssn,
p);
5858 SCLogDebug(
"bypass as stream is dead and we have no rules");
5871 if (StreamTcpInlineDropInvalid()) {
5875 DecodeSetNoPayloadInspectionFlag(
p);
5889 static inline int StreamTcpValidateChecksum(
Packet *
p)
5897 const TCPHdr *tcph = PacketGetTCP(
p);
5898 if (PacketIsIPv4(
p)) {
5899 const IPV4Hdr *ip4h = PacketGetIPv4(
p);
5900 p->
l4.
csum = TCPChecksum(ip4h->s_ip_addrs, (uint16_t *)tcph,
5903 }
else if (PacketIsIPv6(
p)) {
5904 const IPV6Hdr *ip6h = PacketGetIPv6(
p);
5905 p->
l4.
csum = TCPV6Checksum(ip6h->s_ip6_addrs, (uint16_t *)tcph,
5927 static int TcpSessionPacketIsStreamStarter(
const Packet *
p)
5929 const TCPHdr *tcph = PacketGetTCP(
p);
5942 SCLogDebug(
"packet %" PRIu64
" is a midstream stream starter: %02x",
5955 const TCPHdr *tcph = PacketGetTCP(
p);
5960 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p null. Reuse.",
5966 ", ssn %p. STREAMTCP_FLAG_TFO_DATA_IGNORED set. Reuse.",
5972 ", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.",
5978 ", ssn %p state >= TCP_LAST_ACK (%u). Reuse.",
5982 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.",
5987 ", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.",
5994 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p null. Reuse.",
6000 ", ssn %p state >= TCP_LAST_ACK (%u). Reuse.",
6004 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.",
6009 ", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.",
6025 const TCPHdr *tcph = PacketGetTCP(
p);
6028 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p null. No reuse.",
6034 ", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.",
6040 ", ssn %p state >= TCP_LAST_ACK (%u). Reuse.",
6044 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.",
6049 ", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.",
6056 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p null. Reuse.",
6062 ", ssn %p state >= TCP_LAST_ACK (%u). Reuse.",
6066 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.",
6071 ", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.",
6088 const TCPHdr *tcph = PacketGetTCP(
p);
6090 return TcpSessionReuseDoneEnoughSyn(
p, f, ssn);
6095 return TcpSessionReuseDoneEnoughSynAck(
p, f, ssn);
6104 if (
p->
proto == IPPROTO_TCP && PacketIsTCP(
p)) {
6105 if (TcpSessionPacketIsStreamStarter(
p) == 1) {
6106 if (TcpSessionReuseDoneEnough(
p, f, tcp_ssn) == 1) {
6128 #ifdef QA_SIMULATION
6132 if (!(PacketIsTCP(
p))) {
6136 CheckThreadId(
tv,
p, stt);
6142 if (StreamTcpValidateChecksum(
p) == 0) {
6164 *data = (
void *)stt;
6173 IsStreamTcpSessionMemcapExceptionPolicyStatsValid);
6181 "exception_policy.tcp.midstream.", IsMidstreamExceptionPolicyStatsValid);
6185 "exception_policy.tcp.midstream.", IsMidstreamExceptionPolicyStatsValid);
6201 "exception_policy.tcp.reassembly.", IsReassemblyMemcapExceptionPolicyStatsValid);
6220 SCLogDebug(
"StreamTcp thread specific ctx online at %p, reassembly ctx %p",
6228 StreamTcpSessionPoolInit, StreamTcpSessionPoolCleanup);
6238 SCLogError(
"failed to setup/expand stream session pool. Expand stream.memcap?");
6283 const TCPHdr *tcph = PacketGetTCP(
p);
6291 if (!StreamTcpValidateTimestamp(ssn,
p)) {
6320 StreamTcpValidateAck(ssn, &ssn->
server,
p) == -1) {
6321 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
6333 StreamTcpValidateAck(ssn, &ssn->
client,
p) == -1) {
6334 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
6347 receiver_stream = &ssn->
server;
6349 receiver_stream = &ssn->
client;
6351 SCLogDebug(
"ssn %p: setting STREAMTCP_STREAM_FLAG_RST_RECV on receiver stream", ssn);
6371 switch (os_policy) {
6378 SCLogDebug(
"reset is not Valid! Packet SEQ: %" PRIu32
" "
6379 "and server SEQ: %" PRIu32
"",
6388 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" "
6389 "and client SEQ: %" PRIu32
"",
6406 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6407 " server SEQ: %" PRIu32
"",
6419 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6420 " client SEQ: %" PRIu32
"",
6441 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" "
6442 "and server SEQ: %" PRIu32
"",
6448 SCLogDebug(
"reset is valid! Packet SEQ: %" PRIu32
" Stream %u",
seq,
6452 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6453 " client SEQ: %" PRIu32
"",
6484 uint8_t check_ts = 1;
6485 const TCPHdr *tcph = PacketGetTCP(
p);
6489 sender_stream = &ssn->
client;
6490 receiver_stream = &ssn->
server;
6492 sender_stream = &ssn->
server;
6493 receiver_stream = &ssn->
client;
6504 uint32_t last_pkt_ts = sender_stream->
last_pkt_ts;
6505 uint32_t last_ts = sender_stream->
last_ts;
6555 SCLogDebug(
"ts %"PRIu32
", last_ts %"PRIu32
"",
ts, last_ts);
6559 result = (int32_t) ((
ts - last_ts) + 1);
6561 result = (int32_t) (
ts - last_ts);
6564 SCLogDebug(
"result %" PRIi32
", p->ts(secs) %" PRIuMAX
"", result,
6567 if (last_pkt_ts == 0 &&
6575 "%" PRIu32
" p->tcpvars->ts %" PRIu32
" result "
6576 "%" PRId32
"", last_ts,
ts, result);
6579 }
else if ((sender_stream->
last_ts != 0) &&
6581 SCLogDebug(
"packet is not valid last_pkt_ts "
6582 "%" PRIu32
" p->ts(sec) %" PRIu32
"",
6594 SCLogDebug(
"timestamp considered valid anyway");
6626 uint8_t check_ts = 1;
6627 const TCPHdr *tcph = PacketGetTCP(
p);
6631 sender_stream = &ssn->
client;
6632 receiver_stream = &ssn->
server;
6634 sender_stream = &ssn->
server;
6635 receiver_stream = &ssn->
client;
6703 result = (int32_t) ((
ts - sender_stream->
last_ts) + 1);
6705 result = (int32_t) (
ts - sender_stream->
last_ts);
6708 SCLogDebug(
"result %" PRIi32
", p->ts(sec) %" PRIuMAX
"", result,
6718 SCLogDebug(
"timestamp is not valid sender_stream->last_ts "
6719 "%" PRIu32
" p->tcpvars->ts %" PRIu32
" result "
6720 "%" PRId32
"", sender_stream->
last_ts,
ts, result);
6723 }
else if ((sender_stream->
last_ts != 0) &&
6726 SCLogDebug(
"packet is not valid sender_stream->last_pkt_ts "
6727 "%" PRIu32
" p->ts(sec) %" PRIu32
"",
6741 }
else if (ret == 0) {
6751 SCLogDebug(
"timestamp considered valid anyway");
6787 const TCPHdr *tcph = PacketGetTCP(
p);
6802 SCLogDebug(
"ssn %p: pkt ACK %" PRIu32
" == stream last ACK %" PRIu32, ssn, ack,
6815 SCLogDebug(
"ACK %"PRIu32
" is before last_ack %"PRIu32
" - window "
6816 "%"PRIu32
" = %"PRIu32, ack, stream->
last_ack,
6839 SCLogDebug(
"default path leading to invalid: ACK %"PRIu32
", last_ack %"PRIu32
6852 const uint32_t progress)
6906 static void StreamTcpPseudoPacketCreateDetectLogFlush(
ThreadVars *
tv,
6929 np->
proto = IPPROTO_TCP;
6930 FlowReference(&np->
flow, f);
6940 DecodeSetNoPacketInspectionFlag(np);
6943 DecodeSetNoPayloadInspectionFlag(np);
6983 ip4h->
ip_len = htons(40);
6989 ip4h->s_ip_src.s_addr = f->
src.addr_data32[0];
6990 ip4h->s_ip_dst.s_addr = f->
dst.addr_data32[0];
6992 ip4h->s_ip_src.s_addr = f->
dst.addr_data32[0];
6993 ip4h->s_ip_dst.s_addr = f->
src.addr_data32[0];
7026 ip6h->s_ip6_vfc = 0x60;
7027 ip6h->s_ip6_flow = 0;
7028 ip6h->s_ip6_nxt = IPPROTO_TCP;
7029 ip6h->s_ip6_plen = htons(20);
7030 ip6h->s_ip6_hlim = 64;
7032 ip6h->s_ip6_src[0] = f->
src.addr_data32[0];
7033 ip6h->s_ip6_src[1] = f->
src.addr_data32[1];
7034 ip6h->s_ip6_src[2] = f->
src.addr_data32[2];
7035 ip6h->s_ip6_src[3] = f->
src.addr_data32[3];
7036 ip6h->s_ip6_dst[0] = f->
dst.addr_data32[0];
7037 ip6h->s_ip6_dst[1] = f->
dst.addr_data32[1];
7038 ip6h->s_ip6_dst[2] = f->
dst.addr_data32[2];
7039 ip6h->s_ip6_dst[3] = f->
dst.addr_data32[3];
7041 ip6h->s_ip6_src[0] = f->
dst.addr_data32[0];
7042 ip6h->s_ip6_src[1] = f->
dst.addr_data32[1];
7043 ip6h->s_ip6_src[2] = f->
dst.addr_data32[2];
7044 ip6h->s_ip6_src[3] = f->
dst.addr_data32[3];
7045 ip6h->s_ip6_dst[0] = f->
src.addr_data32[0];
7046 ip6h->s_ip6_dst[1] = f->
src.addr_data32[1];
7047 ip6h->s_ip6_dst[2] = f->
src.addr_data32[2];
7048 ip6h->s_ip6_dst[3] = f->
src.addr_data32[3];
7080 np->
ts = parent->
ts;
7088 FlowDeReference(&np->
flow);
7107 StreamTcpPseudoPacketCreateDetectLogFlush(
tv, stt,
p, ssn, pq,
ts^1);
7108 StreamTcpPseudoPacketCreateDetectLogFlush(
tv, stt,
p, ssn, pq,
ts ^ 0);
7128 if (
p->
flow == NULL)
7156 const uint8_t *seg_data;
7157 uint32_t seg_datalen;
7160 int ret = CallbackFunc(
p, seg, data, seg_data, seg_datalen);
7188 if (
p->
flow == NULL)
7202 if (server_node == NULL && client_node == NULL) {
7206 while (server_node != NULL || client_node != NULL) {
7207 const uint8_t *seg_data;
7208 uint32_t seg_datalen;
7209 if (server_node == NULL) {
7216 &client_stream->
sb, &client_node->
sbseg, &seg_data, &seg_datalen);
7217 ret = CallbackFunc(
p, client_node, data, seg_data, seg_datalen);
7222 client_node = TCPSEG_RB_NEXT(client_node);
7223 }
else if (client_node == NULL) {
7230 &server_stream->
sb, &server_node->
sbseg, &seg_data, &seg_datalen);
7231 ret = CallbackFunc(
p, server_node, data, seg_data, seg_datalen);
7236 server_node = TCPSEG_RB_NEXT(server_node);
7241 &client_stream->
sb, &client_node->
sbseg, &seg_data, &seg_datalen);
7242 ret = CallbackFunc(
p, client_node, data, seg_data, seg_datalen);
7247 client_node = TCPSEG_RB_NEXT(client_node);
7250 &server_stream->
sb, &server_node->
sbseg, &seg_data, &seg_datalen);
7251 ret = CallbackFunc(
p, server_node, data, seg_data, seg_datalen);
7256 server_node = TCPSEG_RB_NEXT(server_node);
7291 const char *tcp_state = NULL;
7297 tcp_state =
"syn_sent";
7300 tcp_state =
"syn_recv";
7303 tcp_state =
"established";
7306 tcp_state =
"fin_wait1";
7309 tcp_state =
"fin_wait2";
7312 tcp_state =
"time_wait";
7315 tcp_state =
"last_ack";
7318 tcp_state =
"close_wait";
7321 tcp_state =
"closing";
7324 tcp_state =
"closed";