85 #define STREAMTCP_DEFAULT_PREALLOC 2048
86 #define STREAMTCP_DEFAULT_MEMCAP (64 * 1024 * 1024)
87 #define STREAMTCP_DEFAULT_REASSEMBLY_MEMCAP (256 * 1024 * 1024)
88 #define STREAMTCP_DEFAULT_TOSERVER_CHUNK_SIZE 2560
89 #define STREAMTCP_DEFAULT_TOCLIENT_CHUNK_SIZE 2560
90 #define STREAMTCP_DEFAULT_MAX_SYN_QUEUED 10
91 #define STREAMTCP_DEFAULT_MAX_SYNACK_QUEUED 5
106 .valid_settings_ips = {
132 .valid_settings_ips = {
158 .valid_settings_ips = {
184 .valid_settings_ips = {
207 static int StreamTcpStateDispatch(
216 static uint64_t ssn_pool_cnt = 0;
236 #if defined(DEBUG_VALIDATION) && defined(UNITTESTS)
239 BUG_ON(presize > UINT_MAX);
245 #if defined(DEBUG_VALIDATION) && defined(UNITTESTS)
248 BUG_ON(postsize > presize);
269 if (memcapcopy == 0 || size +
SC_ATOMIC_GET(st_memuse) <= memcapcopy)
281 if (size == 0 || (uint64_t)
SC_ATOMIC_GET(st_memuse) < size) {
302 if (stream != NULL) {
309 static void StreamTcp3wsFreeQueue(
TcpSession *ssn)
336 StreamTcp3wsFreeQueue(ssn);
397 static void *StreamTcpSessionPoolAlloc(
void)
411 static int StreamTcpSessionPoolInit(
void *data,
void* initdata)
421 static void StreamTcpSessionPoolCleanup(
void *s)
435 static inline bool StreamTcpInlineDropInvalid(
void)
446 static inline bool StreamTcpInlineDropUrg(
void)
455 static int RandomGetWrap(
void)
461 }
while(r >= ULONG_MAX - (ULONG_MAX % RAND_MAX));
491 uint16_t rdrange = 10;
500 if ((
SCConfGetInt(
"stream.max-sessions", &value)) == 1) {
502 "Number of concurrent sessions is now only limited by Flow and "
503 "TCP stream engine memcaps.");
506 if ((
SCConfGetInt(
"stream.prealloc-sessions", &value)) == 1) {
521 SCLogConfig(
"stream \"prealloc-sessions\": %"PRIu32
" (per thread)",
525 const char *temp_stream_memcap_str;
526 if (
SCConfGet(
"stream.memcap", &temp_stream_memcap_str) == 1) {
527 uint64_t stream_memcap_copy;
530 "from conf file - %s. Killing engine",
531 temp_stream_memcap_str);
562 if ((
SCConfGetBool(
"stream.checksum-validation", &csum)) == 1) {
574 "enabled" :
"disabled");
577 const char *temp_stream_inline_str;
578 if (
SCConfGet(
"stream.inline", &temp_stream_inline_str) == 1) {
583 if (strcmp(temp_stream_inline_str,
"auto") == 0) {
606 ?
"enabled" :
"disabled");
619 ?
"enabled" :
"disabled");
622 int drop_invalid = 0;
623 if ((
SCConfGetBool(
"stream.drop-invalid", &drop_invalid)) == 1) {
624 if (drop_invalid == 1) {
631 const char *temp_urgpol = NULL;
632 if (
SCConfGet(
"stream.reassembly.urgent.policy", &temp_urgpol) == 1 && temp_urgpol != NULL) {
633 if (strcmp(temp_urgpol,
"inline") == 0) {
635 }
else if (strcmp(temp_urgpol,
"drop") == 0) {
637 }
else if (strcmp(temp_urgpol,
"oob") == 0) {
639 }
else if (strcmp(temp_urgpol,
"gap") == 0) {
642 FatalError(
"stream.reassembly.urgent.policy: invalid value '%s'", temp_urgpol);
651 const char *temp_urgoobpol = NULL;
652 if (
SCConfGet(
"stream.reassembly.urgent.oob-limit-policy", &temp_urgoobpol) == 1 &&
653 temp_urgoobpol != NULL) {
654 if (strcmp(temp_urgoobpol,
"inline") == 0) {
656 }
else if (strcmp(temp_urgoobpol,
"drop") == 0) {
658 }
else if (strcmp(temp_urgoobpol,
"gap") == 0) {
661 FatalError(
"stream.reassembly.urgent.oob-limit-policy: invalid value '%s'", temp_urgoobpol);
671 if ((
SCConfGetInt(
"stream.max-syn-queued", &value)) == 1) {
672 if (value >= 0 && value <= 255) {
684 if ((
SCConfGetInt(
"stream.max-synack-queued", &value)) == 1) {
685 if (value >= 0 && value <= 255) {
697 const char *temp_stream_reassembly_memcap_str;
698 if (
SCConfGet(
"stream.reassembly.memcap", &temp_stream_reassembly_memcap_str) == 1) {
699 uint64_t stream_reassembly_memcap_copy;
701 &stream_reassembly_memcap_copy) < 0) {
703 "stream.reassembly.memcap "
704 "from conf file - %s. Killing engine",
705 temp_stream_reassembly_memcap_str);
715 SCLogConfig(
"stream.reassembly \"memcap\": %"PRIu64
"",
719 const char *temp_stream_reassembly_depth_str;
720 if (
SCConfGet(
"stream.reassembly.depth", &temp_stream_reassembly_depth_str) == 1) {
724 "stream.reassembly.depth "
725 "from conf file - %s. Killing engine",
726 temp_stream_reassembly_depth_str);
738 if ((
SCConfGetBool(
"stream.reassembly.randomize-chunk-size", &randomize)) == 0) {
746 const char *temp_rdrange;
747 if (
SCConfGet(
"stream.reassembly.randomize-chunk-range", &temp_rdrange) == 1) {
750 "stream.reassembly.randomize-chunk-range "
751 "from conf file - %s. Killing engine",
754 }
else if (rdrange >= 100) {
755 FatalError(
"stream.reassembly.randomize-chunk-range "
756 "must be lower than 100");
761 const char *temp_stream_reassembly_toserver_chunk_size_str;
762 if (
SCConfGet(
"stream.reassembly.toserver-chunk-size",
763 &temp_stream_reassembly_toserver_chunk_size_str) == 1) {
767 "stream.reassembly.toserver-chunk-size "
768 "from conf file - %s. Killing engine",
769 temp_stream_reassembly_toserver_chunk_size_str);
778 long int r = RandomGetWrap();
783 const char *temp_stream_reassembly_toclient_chunk_size_str;
784 if (
SCConfGet(
"stream.reassembly.toclient-chunk-size",
785 &temp_stream_reassembly_toclient_chunk_size_str) == 1) {
789 "stream.reassembly.toclient-chunk-size "
790 "from conf file - %s. Killing engine",
791 temp_stream_reassembly_toclient_chunk_size_str);
800 long int r = RandomGetWrap();
806 SCLogConfig(
"stream.reassembly \"toserver-chunk-size\": %"PRIu16,
808 SCLogConfig(
"stream.reassembly \"toclient-chunk-size\": %"PRIu16,
813 if (
SCConfGetBool(
"stream.reassembly.raw", &enable_raw) == 1) {
821 SCLogConfig(
"stream.reassembly.raw: %s", enable_raw ?
"enabled" :
"disabled");
825 int liberal_timestamps = 0;
826 if (
SCConfGetBool(
"stream.liberal-timestamps", &liberal_timestamps) == 1) {
830 SCLogConfig(
"stream.liberal-timestamps: %s", liberal_timestamps ?
"enabled" :
"disabled");
850 StreamTcpSessionPoolAlloc,
851 StreamTcpSessionPoolInit, NULL,
852 StreamTcpSessionPoolCleanup, NULL);
871 SCLogDebug(
"ssn_pool_cnt %"PRIu64
"", ssn_pool_cnt);
874 static bool IsReassemblyMemcapExceptionPolicyStatsValid(
enum ExceptionPolicy exception_policy)
882 static bool IsStreamTcpSessionMemcapExceptionPolicyStatsValid(
enum ExceptionPolicy policy)
890 static void StreamTcpSsnMemcapExceptionPolicyStatsIncr(
949 if (
unlikely((g_eps_stream_ssn_memcap != UINT64_MAX &&
950 g_eps_stream_ssn_memcap ==
t_pcapcnt))) {
965 const TCPHdr *tcph = PacketGetTCP(p);
1024 if (PacketIsIPv4(p)) {
1034 }
else if (PacketIsIPv6(p)) {
1060 #define StreamTcpUpdateLastAck(ssn, stream, ack) { \
1061 if (SEQ_GT((ack), (stream)->last_ack)) \
1063 SCLogDebug("ssn %p: last_ack set to %"PRIu32", moved %u forward", (ssn), (ack), (ack) - (stream)->last_ack); \
1064 if ((SEQ_LEQ((stream)->last_ack, (stream)->next_seq) && SEQ_GT((ack),(stream)->next_seq))) { \
1065 SCLogDebug("last_ack just passed next_seq: %u (was %u) > %u", (ack), (stream)->last_ack, (stream)->next_seq); \
1067 SCLogDebug("next_seq (%u) <> last_ack now %d", (stream)->next_seq, (int)(stream)->next_seq - (ack)); \
1069 (stream)->last_ack = (ack); \
1070 StreamTcpSackPruneList((stream)); \
1072 SCLogDebug("ssn %p: no update: ack %u, last_ack %"PRIu32", next_seq %u (state %u)", \
1073 (ssn), (ack), (stream)->last_ack, (stream)->next_seq, (ssn)->state); \
1077 #define StreamTcpAsyncLastAckUpdate(ssn, stream) { \
1078 if ((ssn)->flags & STREAMTCP_FLAG_ASYNC) { \
1079 if (SEQ_GT((stream)->next_seq, (stream)->last_ack)) { \
1080 uint32_t ack_diff = (stream)->next_seq - (stream)->last_ack; \
1081 (stream)->last_ack += ack_diff; \
1082 SCLogDebug("ssn %p: ASYNC last_ack set to %"PRIu32", moved %u forward", \
1083 (ssn), (stream)->next_seq, ack_diff); \
1088 #define StreamTcpUpdateNextSeq(ssn, stream, seq) { \
1089 (stream)->next_seq = seq; \
1090 SCLogDebug("ssn %p: next_seq %" PRIu32, (ssn), (stream)->next_seq); \
1091 StreamTcpAsyncLastAckUpdate((ssn), (stream)); \
1101 #define StreamTcpUpdateNextWin(ssn, stream, win) { \
1102 uint32_t sacked_size__ = StreamTcpSackedSize((stream)); \
1103 if (SEQ_GT(((win) + sacked_size__), (stream)->next_win)) { \
1104 (stream)->next_win = ((win) + sacked_size__); \
1105 SCLogDebug("ssn %p: next_win set to %"PRIu32, (ssn), (stream)->next_win); \
1113 SCLogDebug(
"ssn %p: (state: %s) Reset received and state changed to "
1117 static bool IsMidstreamExceptionPolicyStatsValid(
enum ExceptionPolicy policy)
1131 static void StreamTcpMidstreamExceptionPolicyStatsIncr(
1140 static int StreamTcpPacketIsRetransmission(
TcpStream *stream,
Packet *p)
1145 const TCPHdr *tcph = PacketGetTCP(p);
1183 static int StreamTcpPacketStateNone(
1186 const TCPHdr *tcph = PacketGetTCP(p);
1189 SCLogDebug(
"RST packet received, no session setup");
1199 SCLogDebug(
"FIN packet received, no session setup");
1205 SCLogDebug(
"FIN packet received, no session setup");
1222 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1254 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
", "
1255 "ssn->server.next_win %" PRIu32
"",
1257 SCLogDebug(
"ssn %p: ssn->client.last_ack %" PRIu32
", "
1258 "ssn->server.last_ack %" PRIu32
"",
1266 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1267 "ssn->client.last_ts %" PRIu32
"",
1286 SCLogDebug(
"ssn %p: assuming SACK permitted for both sides", ssn);
1295 SCLogDebug(
"Midstream not enabled, so won't pick up a session");
1300 SCLogDebug(
"Midstream policy not permissive, so won't pick up a session");
1323 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1324 "TCP_SYN_RECV", ssn);
1355 SCLogDebug(
"ssn %p: wscale enabled. client %u server %u",
1359 SCLogDebug(
"ssn %p: ssn->client.isn %"PRIu32
", ssn->client.next_seq"
1360 " %"PRIu32
", ssn->client.last_ack %"PRIu32
"", ssn,
1363 SCLogDebug(
"ssn %p: ssn->server.isn %"PRIu32
", ssn->server.next_seq"
1364 " %"PRIu32
", ssn->server.last_ack %"PRIu32
"", ssn,
1373 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1374 "ssn->client.last_ts %" PRIu32
"", ssn,
1392 SCLogDebug(
"ssn %p: SYN/ACK with SACK permitted, assuming "
1393 "SACK permitted for both sides", ssn);
1411 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_SYN_SENT", ssn);
1444 SCLogDebug(
"ssn %p: SACK permitted on SYN packet", ssn);
1451 SCLogDebug(
"ssn: %p (TFO) isn %u base_seq %u next_seq %u payload len %u", ssn,
1458 SCLogDebug(
"ssn %p: ssn->client.isn %" PRIu32
", "
1459 "ssn->client.next_seq %" PRIu32
", ssn->client.last_ack "
1469 SCLogDebug(
"Midstream not enabled, so won't pick up a session");
1474 SCLogDebug(
"Midstream policy not permissive, so won't pick up a session");
1491 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1492 "TCP_ESTABLISHED", ssn);
1513 SCLogDebug(
"ssn %p: ssn->client.isn %u, ssn->client.next_seq %u",
1522 SCLogDebug(
"ssn %p: ssn->client.next_win %"PRIu32
", "
1523 "ssn->server.next_win %"PRIu32
"", ssn,
1525 SCLogDebug(
"ssn %p: ssn->client.last_ack %"PRIu32
", "
1526 "ssn->server.last_ack %"PRIu32
"", ssn,
1534 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1535 "ssn->client.last_ts %" PRIu32
"", ssn,
1554 SCLogDebug(
"ssn %p: assuming SACK permitted for both sides", ssn);
1568 const TCPHdr *tcph = PacketGetTCP(p);
1598 StreamTcp3whsSynAckToStateQueue(p, &search);
1606 search.
ts == q->
ts) {
1619 if (StreamTcp3whsFindSynAckBySynAck(ssn, p) != NULL)
1623 SCLogDebug(
"ssn %p: =~ SYN/ACK queue limit reached", ssn);
1629 SCLogDebug(
"ssn %p: =~ SYN/ACK queue failed: stream memcap reached", ssn);
1635 SCLogDebug(
"ssn %p: =~ SYN/ACK queue failed: alloc failed", ssn);
1640 StreamTcp3whsSynAckToStateQueue(p, q);
1654 const TCPHdr *tcph = PacketGetTCP(p);
1689 StreamTcp3whsSynAckToStateQueue(p, &update);
1696 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_SYN_RECV", ssn);
1712 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1713 "ssn->client.last_ts %" PRIu32
"", ssn,
1741 SCLogDebug(
"ssn %p: SACK permitted for session", ssn);
1748 SCLogDebug(
"ssn %p: ssn->server.next_win %" PRIu32
"", ssn,
1750 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
"", ssn,
1752 SCLogDebug(
"ssn %p: ssn->server.isn %" PRIu32
", "
1753 "ssn->server.next_seq %" PRIu32
", "
1754 "ssn->server.last_ack %" PRIu32
" "
1755 "(ssn->client.last_ack %" PRIu32
")", ssn,
1762 SCLogDebug(
"ssn %p: STREAMTCP_FLAG_4WHS unset, normal SYN/ACK"
1763 " so considering 3WHS", ssn);
1774 static inline bool StateSynSentValidateTimestamp(
TcpSession *ssn,
Packet *p)
1784 if (receiver_stream->
last_ts != 0 && ts_echo != 0 &&
1785 ts_echo != receiver_stream->
last_ts)
1787 SCLogDebug(
"%" PRIu64
": ssn %p: BAD TSECR echo %u recv %u", p->
pcap_cnt, ssn, ts_echo,
1792 if (receiver_stream->
last_ts == 0 && ts_echo != 0) {
1793 SCLogDebug(
"%" PRIu64
": ssn %p: BAD TSECR echo %u recv %u", p->
pcap_cnt, ssn, ts_echo,
1804 memset(q, 0,
sizeof(*q));
1825 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1831 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1835 memset(q, 0,
sizeof(*q));
1836 const TCPHdr *tcph = PacketGetTCP(p);
1855 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1862 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1866 memset(q, 0,
sizeof(*q));
1868 const TCPHdr *tcph = PacketGetTCP(p);
1886 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1902 SCLogDebug(
"ssn %p: search state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, s, s->
seq, s->
win,
1907 SCLogDebug(
"ssn %p: queue state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u (last:%s)", ssn, q,
1915 }
else if (ignore_ts) {
1935 ssn->
queue = new_head;
1938 tail->next = old_head;
1940 *old_head = *search;
1941 old_head->
next = NULL;
1947 TcpStateQueueInitFromSsnSyn(ssn, &search);
1951 if (ssn->
queue != NULL && StreamTcp3whsFindSyn(ssn, &search, &
tail,
false) != NULL)
1956 SCLogDebug(
"%" PRIu64
": ssn %p: =~ SYN queue limit reached, rotate", p->
pcap_cnt, ssn);
1960 AddAndRotate(ssn,
tail, &search);
1965 SCLogDebug(
"ssn %p: =~ SYN queue failed: stream memcap reached", ssn);
1971 SCLogDebug(
"ssn %p: =~ SYN queue failed: alloc failed", ssn);
1985 SCLogDebug(
"%" PRIu64
": ssn %p: =~ SYN with SEQ %u added (queue_len %u)", p->
pcap_cnt, ssn,
2025 static inline bool StateSynSentCheckSynAck3Whs(
TcpSession *ssn,
Packet *p,
const bool ts_mismatch)
2027 const TCPHdr *tcph = PacketGetTCP(p);
2029 if (seq_match && !ts_mismatch) {
2034 if (ssn->
queue == NULL) {
2039 TcpStateQueueInitFromPktSynAck(p, &search);
2049 SCLogDebug(
"ssn %p: found queued SYN state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q,
2051 StreamTcp3whsStoreSynApplyToSsn(ssn, q);
2056 }
else if (ts_mismatch) {
2070 static inline bool StateSynSentCheckSynAckTFO(
TcpSession *ssn,
Packet *p,
const bool ts_mismatch)
2072 const TCPHdr *tcph = PacketGetTCP(p);
2075 if (seq_match_tfo && !ts_mismatch) {
2077 }
else if (seq_match_nodata && !ts_mismatch) {
2084 if (ssn->
queue == NULL) {
2089 TcpStateQueueInitFromPktSynAck(p, &search);
2099 SCLogDebug(
"ssn %p: found queued SYN state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q,
2101 StreamTcp3whsStoreSynApplyToSsn(ssn, q);
2106 if (!seq_match_tfo && !seq_match_nodata) {
2108 }
else if (ts_mismatch) {
2124 static int StreamTcpPacketStateSynSent(
2128 const TCPHdr *tcph = PacketGetTCP(p);
2134 SCLogDebug(
"%" PRIu64
": ssn %p: SYN/ACK on SYN_SENT state for packet %" PRIu64,
2138 const bool ts_mismatch =
2143 if (StateSynSentCheckSynAck3Whs(ssn, p, ts_mismatch)) {
2144 SCLogDebug(
"ssn %p: ACK match, packet ACK %" PRIu32
" == "
2145 "%" PRIu32
" from stream",
2148 SCLogDebug(
"ssn %p: (3WHS) ACK mismatch, packet ACK %" PRIu32
" != "
2149 "%" PRIu32
" from stream",
2154 if (StateSynSentCheckSynAckTFO(ssn, p, ts_mismatch)) {
2155 SCLogDebug(
"ssn %p: (TFO) ACK matches next_seq, packet ACK %" PRIu32
" == "
2156 "%" PRIu32
" from stream",
2159 SCLogDebug(
"ssn %p: (TFO) ACK mismatch, packet ACK %" PRIu32
" != "
2160 "%" PRIu32
" from stream",
2166 StreamTcp3wsFreeQueue(ssn);
2168 StreamTcp3whsSynAckUpdate(ssn, p, NULL);
2169 SCLogDebug(
"%" PRIu64
": ssn %p: SYN/ACK on SYN_SENT state: accepted", p->
pcap_cnt, ssn);
2176 SCLogDebug(
"ssn %p: SYN/ACK received in the wrong direction", ssn);
2180 SCLogDebug(
"ssn %p: SYN/ACK received on 4WHS session", ssn);
2187 SCLogDebug(
"ssn %p: 4WHS ACK mismatch, packet ACK %" PRIu32
""
2188 " != %" PRIu32
" from stream",
2198 SCLogDebug(
"ssn %p: 4WHS SEQ mismatch, packet SEQ %" PRIu32
""
2199 " != %" PRIu32
" from *first* SYN pkt",
2206 SCLogDebug(
"ssn %p: =~ 4WHS ssn state is now TCP_SYN_RECV", ssn);
2220 SCLogDebug(
"ssn %p: 4WHS ssn->client.last_ts %" PRIu32
" "
2221 "ssn->server.last_ts %" PRIu32
"",
2246 SCLogDebug(
"ssn %p: SACK permitted for 4WHS session", ssn);
2253 SCLogDebug(
"ssn %p: 4WHS ssn->client.isn %" PRIu32
", "
2254 "ssn->client.next_seq %" PRIu32
", "
2255 "ssn->client.last_ack %" PRIu32
" "
2256 "(ssn->server.last_ack %" PRIu32
")",
2265 if (!StateSynSentValidateTimestamp(ssn, p)) {
2273 if (!StreamTcpValidateRst(ssn, p))
2280 SCLogDebug(
"ssn->server.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2282 StreamTcpCloseSsnWithReset(p, ssn);
2283 StreamTcp3wsFreeQueue(ssn);
2287 SCLogDebug(
"ssn->client.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2288 StreamTcpCloseSsnWithReset(p, ssn);
2289 StreamTcp3wsFreeQueue(ssn);
2297 SCLogDebug(
"ssn %p: SYN packet on state SYN_SENT... resent", ssn);
2299 SCLogDebug(
"ssn %p: SYN packet on state SYN_SENT... resent of "
2312 SCLogDebug(
"ssn %p: STREAMTCP_FLAG_4WHS flag set", ssn);
2349 SCLogDebug(
"ssn %p: 4WHS ssn->server.isn %" PRIu32
", "
2350 "ssn->server.next_seq %" PRIu32
", "
2351 "ssn->server.last_ack %"PRIu32
"", ssn,
2354 SCLogDebug(
"ssn %p: 4WHS ssn->client.isn %" PRIu32
", "
2355 "ssn->client.next_seq %" PRIu32
", "
2356 "ssn->client.last_ack %"PRIu32
"", ssn,
2365 TcpStateQueueInitFromPktSyn(p, &syn_pkt);
2366 TcpStateQueueInitFromSsnSyn(ssn, &syn_ssn);
2368 if (memcmp(&syn_pkt, &syn_ssn,
sizeof(
TcpStateQueue)) != 0) {
2370 StreamTcp3whsStoreSyn(ssn, p);
2371 SCLogDebug(
"ssn %p: Retransmitted SYN. Updating ssn from packet %" PRIu64
2372 ". Stored previous state",
2375 StreamTcp3whsStoreSynApplyToSsn(ssn, &syn_pkt);
2391 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
2392 "%" PRIu32
" from stream",
2399 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2400 StreamTcp3wsFreeQueue(ssn);
2413 SCLogDebug(
"ssn %p: synsent => Asynchronous stream, packet SEQ"
2414 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2415 "ssn->client.next_seq %" PRIu32
"",
2464 static int StreamTcpPacketStateSynRecv(
2468 const TCPHdr *tcph = PacketGetTCP(p);
2471 if (!StreamTcpValidateRst(ssn, p))
2488 SCLogDebug(
"Detection evasion has been attempted, so"
2489 " not resetting the connection !!");
2497 SCLogDebug(
"Detection evasion has been attempted, so"
2498 " not resetting the connection !!");
2504 StreamTcpCloseSsnWithReset(p, ssn);
2507 StreamTcpHandleTimestamp(ssn, p);
2514 if (!StreamTcpValidateTimestamp(ssn, p))
2518 if ((StreamTcpHandleFin(
tv, stt, ssn, p)) == -1)
2523 SCLogDebug(
"ssn %p: SYN/ACK packet on state SYN_RECV. resent", ssn);
2526 SCLogDebug(
"ssn %p: SYN/ACK-pkt to server in SYN_RECV state", ssn);
2535 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
2536 "%" PRIu32
" from stream",
2546 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
2547 "%" PRIu32
" from stream",
2550 if (StreamTcp3whsQueueSynAck(ssn, p) == -1)
2552 SCLogDebug(
"ssn %p: queued different SYN/ACK", ssn);
2556 SCLogDebug(
"ssn %p: SYN packet on state SYN_RECV... resent", ssn);
2559 SCLogDebug(
"ssn %p: SYN-pkt to client in SYN_RECV state", ssn);
2566 SCLogDebug(
"ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
2574 SCLogDebug(
"ssn %p: checking ACK against queued SYN/ACKs", ssn);
2577 SCLogDebug(
"ssn %p: here we update state against queued SYN/ACK", ssn);
2578 StreamTcp3whsSynAckUpdate(ssn, p, q);
2580 SCLogDebug(
"ssn %p: none found, now checking ACK against original SYN/ACK (state)", ssn);
2590 if (!(StreamTcpValidateTimestamp(ssn, p))) {
2596 SCLogDebug(
"ssn %p: ACK received on 4WHS session",ssn);
2599 SCLogDebug(
"ssn %p: 4WHS wrong seq nr on packet", ssn);
2604 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
2605 SCLogDebug(
"ssn %p: 4WHS invalid ack nr on packet", ssn);
2611 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
2612 "%" PRIu32
", ACK %" PRIu32
"",
2616 StreamTcpHandleTimestamp(ssn, p);
2625 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2629 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
", "
2630 "ssn->client.last_ack %"PRIu32
"", ssn,
2635 bool ack_indicates_missed_3whs_ack_packet =
false;
2645 SCLogDebug(
"ssn %p: ACK received on midstream SYN/ACK "
2646 "pickup session",ssn);
2649 SCLogDebug(
"ssn %p: ACK received on TFO session",ssn);
2666 SCLogDebug(
"ssn %p: possible data injection", ssn);
2671 SCLogDebug(
"ssn %p: ACK received in the wrong direction",
2676 ack_indicates_missed_3whs_ack_packet =
true;
2680 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ %" PRIu32
""
2681 ", ACK %" PRIu32
"",
2693 StreamTcpHandleTimestamp(ssn, p);
2717 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2743 StreamTcpHandleTimestamp(ssn, p);
2756 SCLogDebug(
"ssn %p: synrecv => Asynchronous stream, packet SEQ"
2757 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2758 "ssn->server.next_seq %" PRIu32,
2763 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2772 SCLogDebug(
"ssn %p: wrong ack nr on packet, possible evasion!!",
2782 SCLogDebug(
"ssn %p: ACK for missing data", ssn);
2785 StreamTcpHandleTimestamp(ssn, p);
2791 SCLogDebug(
"ssn %p: ACK for missing data: ssn->server.next_seq %u", ssn,
2801 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2810 SCLogDebug(
"ssn %p: ACK for missing data", ssn);
2813 StreamTcpHandleTimestamp(ssn, p);
2835 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2840 }
else if ((ack_indicates_missed_3whs_ack_packet ||
2844 if (ack_indicates_missed_3whs_ack_packet) {
2845 SCLogDebug(
"ssn %p: packet fits perfectly after a missed 3whs-ACK", ssn);
2847 SCLogDebug(
"ssn %p: (TFO) expected packet fits perfectly after SYN/ACK", ssn);
2856 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2861 SCLogDebug(
"ssn %p: wrong seq nr on packet", ssn);
2867 SCLogDebug(
"ssn %p: ssn->server.next_win %" PRIu32
", "
2868 "ssn->server.last_ack %"PRIu32
"", ssn,
2890 static int HandleEstablishedPacketToServer(
2893 const TCPHdr *tcph = PacketGetTCP(p);
2898 SCLogDebug(
"ssn %p: =+ pkt (%" PRIu32
") is to server: SEQ %" PRIu32
","
2899 "ACK %" PRIu32
", WIN %" PRIu16
"",
2905 SCLogDebug(
"ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
2908 }
else if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
2909 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
2917 SCLogDebug(
"ssn %p: pkt is keep alive", ssn);
2922 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ"
2923 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
2924 " ssn->client.last_ack %" PRIu32
", ssn->client.next_win"
2925 "%" PRIu32
"(%" PRIu32
")",
2935 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ."
2936 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2937 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2938 "%" PRIu32
"(%" PRIu32
")",
2950 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ"
2951 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2952 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2953 "%" PRIu32
"(%" PRIu32
")",
2968 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
2969 " before last_ack %" PRIu32
", after next_seq %" PRIu32
":"
2970 " acked data that we haven't seen before",
2973 SCLogDebug(
"ssn %p: server => SEQ before last_ack, packet SEQ"
2974 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2975 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2976 "%" PRIu32
"(%" PRIu32
")",
2980 SCLogDebug(
"ssn %p: rejecting because pkt before last_ack", ssn);
2986 int zerowindowprobe = 0;
2989 SCLogDebug(
"ssn %p: zero window probe", ssn);
2990 zerowindowprobe = 1;
3000 if (zerowindowprobe) {
3001 SCLogDebug(
"ssn %p: zero window probe, skipping oow check", ssn);
3004 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
3009 SCLogDebug(
"ssn %p: ssn->server.window %"PRIu32
"", ssn,
3026 StreamTcpHandleTimestamp(ssn, p);
3038 SCLogDebug(
"ssn %p: toserver => SEQ out of window, packet SEQ "
3039 "%" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3040 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
3041 "%" PRIu32
"(%" PRIu32
")",
3045 StreamTcpSackedSize(&ssn->
client));
3065 static int HandleEstablishedPacketToClient(
3068 const TCPHdr *tcph = PacketGetTCP(p);
3073 SCLogDebug(
"ssn %p: =+ pkt (%" PRIu32
") is to client: SEQ %" PRIu32
","
3074 " ACK %" PRIu32
", WIN %" PRIu16
"",
3080 SCLogDebug(
"ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
3083 }
else if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3084 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3098 SCLogDebug(
"ssn %p: adjusted midstream ssn->server.next_win to "
3104 SCLogDebug(
"ssn %p: pkt is keep alive", ssn);
3110 SCLogDebug(
"ssn %p: client => Asynchronous stream, packet SEQ"
3111 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3112 " ssn->client.last_ack %" PRIu32
", ssn->client.next_win"
3113 " %" PRIu32
"(%" PRIu32
")",
3124 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
3125 " before last_ack %" PRIu32
", after next_seq %" PRIu32
":"
3126 " acked data that we haven't seen before",
3129 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
3130 " before last_ack %" PRIu32
". next_seq %" PRIu32,
3137 int zerowindowprobe = 0;
3140 SCLogDebug(
"ssn %p: zero window probe", ssn);
3141 zerowindowprobe = 1;
3152 if (zerowindowprobe) {
3153 SCLogDebug(
"ssn %p: zero window probe, skipping oow check", ssn);
3156 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
3160 SCLogDebug(
"ssn %p: ssn->client.window %"PRIu32
"", ssn,
3173 StreamTcpHandleTimestamp(ssn, p);
3182 SCLogDebug(
"ssn %p: client => SEQ out of window, packet SEQ"
3183 "%" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3184 " ssn->server.last_ack %" PRIu32
", ssn->server.next_win "
3185 "%" PRIu32
"(%" PRIu32
")",
3194 static bool StreamTcpPacketIsZeroWindowProbeAck(
const TcpSession *ssn,
const Packet *p)
3196 const TCPHdr *tcph = PacketGetTCP(p);
3220 if (pkt_win != rcv->
window)
3227 SCLogDebug(
"ssn %p: packet %" PRIu64
" is a Zero Window Probe ACK", ssn, p->
pcap_cnt);
3234 static bool StreamTcpPacketIsDupAck(
const TcpSession *ssn,
const Packet *p)
3236 const TCPHdr *tcph = PacketGetTCP(p);
3254 if (pkt_win == 0 || rcv->
window == 0)
3256 if (pkt_win != rcv->
window)
3264 SCLogDebug(
"ssn %p: packet:%" PRIu64
" seq:%u ack:%u win:%u snd %u:%u:%u rcv %u:%u:%u", ssn,
3288 const TCPHdr *tcph = PacketGetTCP(p);
3339 static int StreamTcpPacketIsSpuriousRetransmission(
const TcpSession *ssn,
Packet *p)
3350 const TCPHdr *tcph = PacketGetTCP(p);
3356 "ssn %p: spurious retransmission; packet entirely before base_seq: SEQ %u(%u) "
3357 "last_ack %u base_seq %u",
3366 SCLogDebug(
"ssn %p: spurious retransmission; packet entirely before last_ack: SEQ %u(%u) "
3374 SCLogDebug(
"ssn %p: NOT spurious retransmission; packet NOT entirely before last_ack: SEQ "
3375 "%u(%u) last_ack %u, base_seq %u",
3392 static int StreamTcpPacketStateEstablished(
3396 const TCPHdr *tcph = PacketGetTCP(p);
3402 if (!StreamTcpValidateRst(ssn, p))
3406 StreamTcpCloseSsnWithReset(p, ssn);
3410 SCLogDebug(
"ssn %p: ssn->server.next_seq %" PRIu32
"", ssn,
3420 StreamTcpHandleTimestamp(ssn, p);
3424 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3432 StreamTcpCloseSsnWithReset(p, ssn);
3437 SCLogDebug(
"ssn %p: ssn->server.next_seq %" PRIu32
"", ssn,
3447 StreamTcpHandleTimestamp(ssn, p);
3451 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3462 if (!StreamTcpValidateTimestamp(ssn, p))
3467 " %" PRIu32
", last ACK %" PRIu32
", next win %"PRIu32
","
3472 if ((StreamTcpHandleFin(
tv, stt, ssn, p)) == -1)
3477 SCLogDebug(
"ssn %p: SYN/ACK packet on state ESTABLISHED... resent",
3481 SCLogDebug(
"ssn %p: SYN/ACK-pkt to server in ESTABLISHED state", ssn);
3490 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
3491 "%" PRIu32
" from stream",
3501 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
3502 "%" PRIu32
" from stream",
3515 SCLogDebug(
"ssn %p: SYN/ACK packet on state ESTABLISHED... resent. "
3516 "Likely due server not receiving final ACK in 3whs", ssn);
3520 SCLogDebug(
"ssn %p: SYN packet on state ESTABLISHED... resent", ssn);
3522 SCLogDebug(
"ssn %p: SYN-pkt to client in EST state", ssn);
3529 SCLogDebug(
"ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
3550 if (!StreamTcpValidateTimestamp(ssn, p))
3556 HandleEstablishedPacketToServer(
tv, ssn, p, stt);
3558 SCLogDebug(
"ssn %p: next SEQ %" PRIu32
", last ACK %" PRIu32
","
3559 " next win %" PRIu32
", win %" PRIu32
"", ssn,
3566 SCLogDebug(
"3whs is now confirmed by server");
3570 HandleEstablishedPacketToClient(
tv, ssn, p, stt);
3572 SCLogDebug(
"ssn %p: next SEQ %" PRIu32
", last ACK %" PRIu32
","
3573 " next win %" PRIu32
", win %" PRIu32
"", ssn,
3598 const TCPHdr *tcph = PacketGetTCP(p);
3604 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ %" PRIu32
","
3608 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3609 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3615 SCLogDebug(
"ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn,
seq, pkt_re,
3620 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
" != "
3621 "%" PRIu32
" from stream",
3634 SCLogDebug(
"ssn %p: state changed to TCP_CLOSE_WAIT", ssn);
3639 SCLogDebug(
"ssn %p: ssn->client.next_seq %" PRIu32
"", ssn,
3644 StreamTcpHandleTimestamp(ssn, p);
3657 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK %" PRIu32
"",
3660 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ %" PRIu32
", "
3664 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3665 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3671 SCLogDebug(
"ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn,
seq, pkt_re,
3676 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
" != "
3677 "%" PRIu32
" from stream (last_ack %u win %u = %u)",
3686 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT1", ssn);
3695 StreamTcpHandleTimestamp(ssn, p);
3708 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK %" PRIu32
"",
3728 static int StreamTcpPacketStateFinWait1(
3732 const TCPHdr *tcph = PacketGetTCP(p);
3738 if (!StreamTcpValidateRst(ssn, p))
3741 StreamTcpCloseSsnWithReset(p, ssn);
3750 StreamTcpHandleTimestamp(ssn, p);
3761 StreamTcpHandleTimestamp(ssn, p);
3769 if (!StreamTcpValidateTimestamp(ssn, p))
3774 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3775 "%" PRIu32
", ACK %" PRIu32
"",
3777 int retransmission = 0;
3779 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
3780 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3786 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3787 " != %" PRIu32
" from stream",
3793 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3794 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3799 if (!retransmission) {
3801 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
3807 StreamTcpHandleTimestamp(ssn, p);
3823 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3827 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3828 "%" PRIu32
", ACK %" PRIu32
"",
3830 int retransmission = 0;
3832 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
3833 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3838 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3844 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3845 " != %" PRIu32
" from stream",
3851 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3852 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3858 StreamTcpHandleTimestamp(ssn, p);
3861 if (!retransmission) {
3863 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
3881 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3888 if (!StreamTcpValidateTimestamp(ssn, p))
3893 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3894 "%" PRIu32
", ACK %" PRIu32
"",
3896 int retransmission = 0;
3898 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
3899 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3905 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3906 " != %" PRIu32
" from stream",
3912 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3913 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3918 if (!retransmission) {
3920 SCLogDebug(
"ssn %p: state changed to TCP_CLOSING", ssn);
3926 StreamTcpHandleTimestamp(ssn, p);
3943 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3947 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3948 "%" PRIu32
", ACK %" PRIu32
"",
3951 int retransmission = 0;
3953 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
3954 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3960 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3961 " != %" PRIu32
" from stream",
3967 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3968 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3973 if (!retransmission) {
3975 SCLogDebug(
"ssn %p: state changed to TCP_CLOSING", ssn);
3981 StreamTcpHandleTimestamp(ssn, p);
3998 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4003 SCLogDebug(
"ssn (%p): SYN pkt on FinWait1", ssn);
4009 if (!StreamTcpValidateTimestamp(ssn, p))
4014 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4015 "%" PRIu32
", ACK %" PRIu32
"",
4017 int retransmission = 0;
4019 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4020 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4025 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4026 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4033 "ssn %p: ACK's older segment as %u < %u", ssn, ack, ssn->
server.
next_seq);
4034 }
else if (!retransmission) {
4038 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
4044 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT2", ssn);
4047 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4048 " != %" PRIu32
" from stream",
4060 StreamTcpHandleTimestamp(ssn, p);
4081 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4087 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4088 "%" PRIu32
", ACK %" PRIu32
"",
4091 int retransmission = 0;
4093 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4094 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4099 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4100 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4105 if (!retransmission) {
4108 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
4114 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT2", ssn);
4117 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4118 " != %" PRIu32
" from stream",
4128 StreamTcpHandleTimestamp(ssn, p);
4149 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4170 static int StreamTcpPacketStateFinWait2(
4174 const TCPHdr *tcph = PacketGetTCP(p);
4180 if (!StreamTcpValidateRst(ssn, p))
4183 StreamTcpCloseSsnWithReset(p, ssn);
4192 StreamTcpHandleTimestamp(ssn, p);
4203 StreamTcpHandleTimestamp(ssn, p);
4211 if (!StreamTcpValidateTimestamp(ssn, p))
4216 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4217 "%" PRIu32
", ACK %" PRIu32
"",
4219 int retransmission = 0;
4225 }
else if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4226 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4232 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ "
4233 "%" PRIu32
" != %" PRIu32
" from stream",
4239 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4240 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4245 if (!retransmission) {
4247 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4257 StreamTcpHandleTimestamp(ssn, p);
4270 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4274 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4275 "%" PRIu32
", ACK %" PRIu32
"",
4277 int retransmission = 0;
4283 }
else if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4284 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4290 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ "
4291 "%" PRIu32
" != %" PRIu32
" from stream",
4297 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4298 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4303 if (!retransmission) {
4305 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4311 StreamTcpHandleTimestamp(ssn, p);
4323 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4329 SCLogDebug(
"ssn (%p): SYN pkt on FinWait2", ssn);
4335 if (!StreamTcpValidateTimestamp(ssn, p))
4340 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4341 "%" PRIu32
", ACK %" PRIu32
"",
4343 int retransmission = 0;
4345 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4346 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4351 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4352 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4357 if (!retransmission) {
4360 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
4365 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4366 " != %" PRIu32
" from stream",
4376 StreamTcpHandleTimestamp(ssn, p);
4392 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4396 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4397 "%" PRIu32
", ACK %" PRIu32
"",
4399 int retransmission = 0;
4401 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4402 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4407 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4408 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4413 if (!retransmission) {
4416 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
4420 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4421 " != %" PRIu32
" from stream",
4431 StreamTcpHandleTimestamp(ssn, p);
4447 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4468 static int StreamTcpPacketStateClosing(
4472 const TCPHdr *tcph = PacketGetTCP(p);
4478 if (!StreamTcpValidateRst(ssn, p))
4481 StreamTcpCloseSsnWithReset(p, ssn);
4490 StreamTcpHandleTimestamp(ssn, p);
4501 StreamTcpHandleTimestamp(ssn, p);
4508 SCLogDebug(
"ssn (%p): SYN pkt on Closing", ssn);
4514 if (!StreamTcpValidateTimestamp(ssn, p))
4519 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4520 "%" PRIu32
", ACK %" PRIu32
"",
4522 int retransmission = 0;
4523 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4524 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4530 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4531 " != %" PRIu32
" from stream",
4537 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4538 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4543 if (!retransmission) {
4545 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4551 StreamTcpHandleTimestamp(ssn, p);
4561 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4565 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4566 "%" PRIu32
", ACK %" PRIu32
"",
4568 int retransmission = 0;
4569 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4570 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4576 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4577 " != %" PRIu32
" from stream",
4583 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4584 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4589 if (!retransmission) {
4591 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4597 StreamTcpHandleTimestamp(ssn, p);
4608 SCLogDebug(
"StreamTcpPacketStateClosing (%p): =+ next SEQ "
4609 "%" PRIu32
", last ACK %" PRIu32
"", ssn,
4629 static int StreamTcpPacketStateCloseWait(
4633 const TCPHdr *tcph = PacketGetTCP(p);
4641 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4642 "%" PRIu32
", ACK %" PRIu32
"",
4645 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4646 "%" PRIu32
", ACK %" PRIu32
"",
4651 if (!StreamTcpValidateRst(ssn, p))
4654 StreamTcpCloseSsnWithReset(p, ssn);
4663 StreamTcpHandleTimestamp(ssn, p);
4674 StreamTcpHandleTimestamp(ssn, p);
4682 if (!StreamTcpValidateTimestamp(ssn, p))
4687 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4688 "%" PRIu32
", ACK %" PRIu32
"",
4691 int retransmission = 0;
4692 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4693 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4698 if (!retransmission) {
4701 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4702 " != %" PRIu32
" from stream",
4709 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4710 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4717 if (!retransmission)
4721 StreamTcpHandleTimestamp(ssn, p);
4733 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4737 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4738 "%" PRIu32
", ACK %" PRIu32
"",
4741 int retransmission = 0;
4742 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4743 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4748 if (!retransmission) {
4751 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4752 " != %" PRIu32
" from stream",
4759 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4760 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4765 if (!retransmission) {
4767 SCLogDebug(
"ssn %p: state changed to TCP_LAST_ACK", ssn);
4773 StreamTcpHandleTimestamp(ssn, p);
4785 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4791 SCLogDebug(
"ssn (%p): SYN pkt on CloseWait", ssn);
4797 if (!StreamTcpValidateTimestamp(ssn, p))
4802 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4803 "%" PRIu32
", ACK %" PRIu32
"",
4806 int retransmission = 0;
4807 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4808 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4814 SCLogDebug(
"ssn %p: -> retransmission", ssn);
4819 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4820 " != %" PRIu32
" from stream",
4826 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4827 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4832 if (!retransmission) {
4837 StreamTcpHandleTimestamp(ssn, p);
4851 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4855 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4856 "%" PRIu32
", ACK %" PRIu32
"",
4858 int retransmission = 0;
4859 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4860 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4866 SCLogDebug(
"ssn %p: -> retransmission", ssn);
4871 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4872 " != %" PRIu32
" from stream",
4878 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4879 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4884 if (!retransmission) {
4889 StreamTcpHandleTimestamp(ssn, p);
4903 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4924 static int StreamTcpPacketStateLastAck(
4928 const TCPHdr *tcph = PacketGetTCP(p);
4934 if (!StreamTcpValidateRst(ssn, p))
4937 StreamTcpCloseSsnWithReset(p, ssn);
4946 StreamTcpHandleTimestamp(ssn, p);
4957 StreamTcpHandleTimestamp(ssn, p);
4965 SCLogDebug(
"ssn (%p): FIN pkt on LastAck", ssn);
4968 SCLogDebug(
"ssn (%p): SYN pkt on LastAck", ssn);
4974 if (!StreamTcpValidateTimestamp(ssn, p))
4979 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4980 "%" PRIu32
", ACK %" PRIu32
"",
4983 int retransmission = 0;
4984 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4985 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4990 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4991 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4996 if (!retransmission) {
4998 SCLogDebug(
"ssn %p: not updating state as packet is before next_seq", ssn);
5000 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5001 " != %" PRIu32
" from stream",
5007 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5013 StreamTcpHandleTimestamp(ssn, p);
5024 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5045 static int StreamTcpPacketStateTimeWait(
5049 const TCPHdr *tcph = PacketGetTCP(p);
5055 if (!StreamTcpValidateRst(ssn, p))
5058 StreamTcpCloseSsnWithReset(p, ssn);
5067 StreamTcpHandleTimestamp(ssn, p);
5078 StreamTcpHandleTimestamp(ssn, p);
5088 SCLogDebug(
"ssn (%p): SYN pkt on TimeWait", ssn);
5094 if (!StreamTcpValidateTimestamp(ssn, p))
5099 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
5100 "%" PRIu32
", ACK %" PRIu32
"",
5102 int retransmission = 0;
5103 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
5104 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
5109 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5110 " != %" PRIu32
" from stream",
5116 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
5117 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5122 if (!retransmission) {
5124 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5130 StreamTcpHandleTimestamp(ssn, p);
5141 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5145 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
5146 "%" PRIu32
", ACK %" PRIu32
"",
5148 int retransmission = 0;
5149 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
5150 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
5155 SCLogDebug(
"ssn %p: -> retransmission", ssn);
5158 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5159 " != %" PRIu32
" from stream",
5166 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
5167 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5172 if (!retransmission) {
5174 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5180 StreamTcpHandleTimestamp(ssn, p);
5191 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5203 static int StreamTcpPacketStateClosed(
5208 const TCPHdr *tcph = PacketGetTCP(p);
5214 TcpStream *stream = NULL, *ostream = NULL;
5231 if (StreamTcpStateDispatch(
tv, p, stt, ssn, ssn->
pstate) < 0)
5246 const TCPHdr *tcph = PacketGetTCP(p);
5260 SCLogDebug(
"regular packet %"PRIu64
" from same sender as "
5261 "the previous RST. Looks like it injected!", p->
pcap_cnt);
5287 const TCPHdr *tcph = PacketGetTCP(p);
5292 TcpStream *stream = NULL, *ostream = NULL;
5303 if (ack == ostream->last_ack &&
seq == (stream->
next_seq - 1)) {
5319 TcpStream *stream = NULL, *ostream = NULL;
5330 const TCPHdr *tcph = PacketGetTCP(p);
5349 if (pkt_win != ostream->window)
5358 SCLogDebug(
"seq %u (%u), ack %u (%u) FLAG_KEEPALIVE: %s",
seq, stream->
next_seq, ack, ostream->last_ack,
5388 TcpStream *stream = NULL, *ostream = NULL;
5402 const TCPHdr *tcph = PacketGetTCP(p);
5421 if (pkt_win == ostream->window)
5424 if (ack == ostream->last_ack &&
seq == stream->
next_seq) {
5439 TcpStream *stream = NULL, *ostream = NULL;
5447 const TCPHdr *tcph = PacketGetTCP(p);
5464 SCLogDebug(
"%"PRIu64
", seq %u ack %u stream->next_seq %u ostream->next_seq %u",
5492 TcpStream *stream = NULL, *ostream = NULL;
5503 const TCPHdr *tcph = PacketGetTCP(p);
5519 if (pkt_win < ostream->window) {
5520 uint32_t diff = ostream->window - pkt_win;
5522 SEQ_GT(ack, ostream->next_seq) &&
5525 SCLogDebug(
"%"PRIu64
", pkt_win %u, stream win %u, diff %u, dsize %u",
5527 SCLogDebug(
"%"PRIu64
", pkt_win %u, stream win %u",
5528 p->
pcap_cnt, pkt_win, ostream->window);
5529 SCLogDebug(
"%"PRIu64
", seq %u ack %u ostream->next_seq %u ostream->last_ack %u, ostream->next_win %u, diff %u (%u)",
5530 p->
pcap_cnt,
seq, ack, ostream->next_seq, ostream->last_ack, ostream->next_win,
5531 ostream->next_seq - ostream->last_ack, stream->
next_seq - stream->
last_ack);
5538 uint32_t adiff = ack - ostream->last_ack;
5539 if (((pkt_win > 1024) && (diff > (adiff + 32))) ||
5540 ((pkt_win <= 1024) && (diff > adiff)))
5542 SCLogDebug(
"pkt ACK %u is %u bytes beyond last_ack %u, shrinks window by %u "
5543 "(allowing 32 bytes extra): pkt WIN %u", ack, adiff, ostream->last_ack, diff, pkt_win);
5544 SCLogDebug(
"%u - %u = %u (state %u)", diff, adiff, diff - adiff, ssn->
state);
5559 static inline int StreamTcpStateDispatch(
5567 SCLogDebug(
"packet received on TCP_SYN_SENT state");
5568 if (StreamTcpPacketStateSynSent(
tv, p, stt, ssn)) {
5573 SCLogDebug(
"packet received on TCP_SYN_RECV state");
5574 if (StreamTcpPacketStateSynRecv(
tv, p, stt, ssn)) {
5579 SCLogDebug(
"packet received on TCP_ESTABLISHED state");
5580 if (StreamTcpPacketStateEstablished(
tv, p, stt, ssn)) {
5585 SCLogDebug(
"packet received on TCP_FIN_WAIT1 state");
5586 if (StreamTcpPacketStateFinWait1(
tv, p, stt, ssn)) {
5591 SCLogDebug(
"packet received on TCP_FIN_WAIT2 state");
5592 if (StreamTcpPacketStateFinWait2(
tv, p, stt, ssn)) {
5597 SCLogDebug(
"packet received on TCP_CLOSING state");
5598 if (StreamTcpPacketStateClosing(
tv, p, stt, ssn)) {
5603 SCLogDebug(
"packet received on TCP_CLOSE_WAIT state");
5604 if (StreamTcpPacketStateCloseWait(
tv, p, stt, ssn)) {
5609 SCLogDebug(
"packet received on TCP_LAST_ACK state");
5610 if (StreamTcpPacketStateLastAck(
tv, p, stt, ssn)) {
5615 SCLogDebug(
"packet received on TCP_TIME_WAIT state");
5616 if (StreamTcpPacketStateTimeWait(
tv, p, stt, ssn)) {
5622 SCLogDebug(
"packet received on closed state");
5624 if (StreamTcpPacketStateClosed(
tv, p, stt, ssn)) {
5630 SCLogDebug(
"packet received on default state");
5666 const TCPHdr *tcph = PacketGetTCP(p);
5681 SCLogDebug(
"ssn %p: removing ASYNC flag as we have packets on both sides", ssn);
5701 if (StreamTcpCheckFlowDrops(p) == 1) {
5711 if (StreamTcpPacketStateNone(
tv, p, stt, ssn) == -1) {
5737 if (StreamTcpPacketIsKeepAlive(ssn, p) == 1) {
5740 if (StreamTcpPacketIsKeepAliveACK(ssn, p) == 1) {
5741 StreamTcpClearKeepAliveFlag(ssn, p);
5744 StreamTcpClearKeepAliveFlag(ssn, p);
5746 const bool is_zwp_ack = StreamTcpPacketIsZeroWindowProbeAck(ssn, p);
5757 if (StreamTcpPacketIsDupAck(ssn, p)) {
5764 if (StreamTcpPacketIsFinShutdownAck(ssn, p) == 0) {
5765 if (StreamTcpPacketIsWindowUpdate(ssn, p) == 0) {
5766 if (StreamTcpPacketIsBadWindowUpdate(ssn,p))
5768 if (StreamTcpPacketIsOutdatedAck(ssn, p))
5773 int ret = StreamTcpPacketIsSpuriousRetransmission(ssn, p);
5782 if (StreamTcpStateDispatch(
tv, p, stt, ssn, ssn->
state) < 0)
5786 StreamTcpPacketCheckPostRst(ssn, p);
5831 SCLogDebug(
"bypass as stream is dead and we have no rules");
5844 if (StreamTcpInlineDropInvalid()) {
5848 DecodeSetNoPayloadInspectionFlag(p);
5862 static inline int StreamTcpValidateChecksum(
Packet *p)
5870 const TCPHdr *tcph = PacketGetTCP(p);
5871 if (PacketIsIPv4(p)) {
5872 const IPV4Hdr *ip4h = PacketGetIPv4(p);
5873 p->
l4.
csum = TCPChecksum(ip4h->s_ip_addrs, (uint16_t *)tcph,
5876 }
else if (PacketIsIPv6(p)) {
5877 const IPV6Hdr *ip6h = PacketGetIPv6(p);
5878 p->
l4.
csum = TCPV6Checksum(ip6h->s_ip6_addrs, (uint16_t *)tcph,
5899 static int TcpSessionPacketIsStreamStarter(
const Packet *p)
5901 const TCPHdr *tcph = PacketGetTCP(p);
5924 static bool TcpSessionReuseDoneEnoughSyn(
const Packet *p,
const Flow *f,
const TcpSession *ssn)
5926 const TCPHdr *tcph = PacketGetTCP(p);
5931 SCLogDebug(
"steam starter packet %" PRIu64
", ssn %p null. Reuse.", p->
pcap_cnt, ssn);
5936 ", ssn %p. STREAMTCP_FLAG_TFO_DATA_IGNORED set. Reuse.",
5941 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.", p->
pcap_cnt, ssn);
5945 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5948 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5951 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
5961 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5964 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5967 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
5980 static bool TcpSessionReuseDoneEnoughSynAck(
const Packet *p,
const Flow *f,
const TcpSession *ssn)
5982 const TCPHdr *tcph = PacketGetTCP(p);
5985 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p null. No reuse.", p->
pcap_cnt, ssn);
5989 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.", p->
pcap_cnt, ssn);
5993 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5996 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5999 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
6009 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
6012 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
6015 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
6031 const TCPHdr *tcph = PacketGetTCP(p);
6033 return TcpSessionReuseDoneEnoughSyn(p, f, ssn);
6038 return TcpSessionReuseDoneEnoughSynAck(p, f, ssn);
6047 if (p->
proto == IPPROTO_TCP && PacketIsTCP(p)) {
6048 if (TcpSessionPacketIsStreamStarter(p) == 1) {
6049 if (TcpSessionReuseDoneEnough(p, f, tcp_ssn) == 1) {
6072 if (!(PacketIsTCP(p))) {
6076 CheckThreadId(
tv, p, stt);
6082 if (StreamTcpValidateChecksum(p) == 0) {
6104 *data = (
void *)stt;
6113 IsStreamTcpSessionMemcapExceptionPolicyStatsValid);
6121 "exception_policy.tcp.midstream.", IsMidstreamExceptionPolicyStatsValid);
6125 "exception_policy.tcp.midstream.", IsMidstreamExceptionPolicyStatsValid);
6140 "exception_policy.tcp.reassembly.", IsReassemblyMemcapExceptionPolicyStatsValid);
6154 SCLogDebug(
"StreamTcp thread specific ctx online at %p, reassembly ctx %p",
6163 StreamTcpSessionPoolAlloc,
6164 StreamTcpSessionPoolInit, NULL,
6165 StreamTcpSessionPoolCleanup, NULL);
6175 SCLogError(
"failed to setup/expand stream session pool. Expand stream.memcap?");
6220 const TCPHdr *tcph = PacketGetTCP(p);
6228 if (!StreamTcpValidateTimestamp(ssn, p)) {
6257 StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
6258 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
6270 StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
6271 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
6284 receiver_stream = &ssn->
server;
6286 receiver_stream = &ssn->
client;
6288 SCLogDebug(
"ssn %p: setting STREAMTCP_STREAM_FLAG_RST_RECV on receiver stream", ssn);
6308 switch (os_policy) {
6315 SCLogDebug(
"reset is not Valid! Packet SEQ: %" PRIu32
" "
6316 "and server SEQ: %" PRIu32
"",
6325 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" "
6326 "and client SEQ: %" PRIu32
"",
6343 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6344 " server SEQ: %" PRIu32
"",
6356 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6357 " client SEQ: %" PRIu32
"",
6378 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" "
6379 "and server SEQ: %" PRIu32
"",
6385 SCLogDebug(
"reset is valid! Packet SEQ: %" PRIu32
" Stream %u",
seq,
6389 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6390 " client SEQ: %" PRIu32
"",
6421 uint8_t check_ts = 1;
6422 const TCPHdr *tcph = PacketGetTCP(p);
6426 sender_stream = &ssn->
client;
6427 receiver_stream = &ssn->
server;
6429 sender_stream = &ssn->
server;
6430 receiver_stream = &ssn->
client;
6441 uint32_t last_pkt_ts = sender_stream->
last_pkt_ts;
6442 uint32_t last_ts = sender_stream->
last_ts;
6492 SCLogDebug(
"ts %"PRIu32
", last_ts %"PRIu32
"",
ts, last_ts);
6496 result = (int32_t) ((
ts - last_ts) + 1);
6498 result = (int32_t) (
ts - last_ts);
6501 SCLogDebug(
"result %" PRIi32
", p->ts(secs) %" PRIuMAX
"", result,
6504 if (last_pkt_ts == 0 &&
6512 "%" PRIu32
" p->tcpvars->ts %" PRIu32
" result "
6513 "%" PRId32
"", last_ts,
ts, result);
6516 }
else if ((sender_stream->
last_ts != 0) &&
6518 SCLogDebug(
"packet is not valid last_pkt_ts "
6519 "%" PRIu32
" p->ts(sec) %" PRIu32
"",
6531 SCLogDebug(
"timestamp considered valid anyway");
6563 uint8_t check_ts = 1;
6564 const TCPHdr *tcph = PacketGetTCP(p);
6568 sender_stream = &ssn->
client;
6569 receiver_stream = &ssn->
server;
6571 sender_stream = &ssn->
server;
6572 receiver_stream = &ssn->
client;
6640 result = (int32_t) ((
ts - sender_stream->
last_ts) + 1);
6642 result = (int32_t) (
ts - sender_stream->
last_ts);
6645 SCLogDebug(
"result %" PRIi32
", p->ts(sec) %" PRIuMAX
"", result,
6655 SCLogDebug(
"timestamp is not valid sender_stream->last_ts "
6656 "%" PRIu32
" p->tcpvars->ts %" PRIu32
" result "
6657 "%" PRId32
"", sender_stream->
last_ts,
ts, result);
6660 }
else if ((sender_stream->
last_ts != 0) &&
6663 SCLogDebug(
"packet is not valid sender_stream->last_pkt_ts "
6664 "%" PRIu32
" p->ts(sec) %" PRIu32
"",
6678 }
else if (ret == 0) {
6688 SCLogDebug(
"timestamp considered valid anyway");
6724 const TCPHdr *tcph = PacketGetTCP(p);
6739 SCLogDebug(
"ssn %p: pkt ACK %" PRIu32
" == stream last ACK %" PRIu32, ssn, ack,
6752 SCLogDebug(
"ACK %"PRIu32
" is before last_ack %"PRIu32
" - window "
6753 "%"PRIu32
" = %"PRIu32, ack, stream->
last_ack,
6776 SCLogDebug(
"default path leading to invalid: ACK %"PRIu32
", last_ack %"PRIu32
6789 const uint32_t progress)
6843 static void StreamTcpPseudoPacketCreateDetectLogFlush(
ThreadVars *
tv,
6866 np->
proto = IPPROTO_TCP;
6867 FlowReference(&np->
flow, f);
6877 DecodeSetNoPacketInspectionFlag(np);
6880 DecodeSetNoPayloadInspectionFlag(np);
6920 ip4h->
ip_len = htons(40);
6926 ip4h->s_ip_src.s_addr = f->
src.addr_data32[0];
6927 ip4h->s_ip_dst.s_addr = f->
dst.addr_data32[0];
6929 ip4h->s_ip_src.s_addr = f->
dst.addr_data32[0];
6930 ip4h->s_ip_dst.s_addr = f->
src.addr_data32[0];
6963 ip6h->s_ip6_vfc = 0x60;
6964 ip6h->s_ip6_flow = 0;
6965 ip6h->s_ip6_nxt = IPPROTO_TCP;
6966 ip6h->s_ip6_plen = htons(20);
6967 ip6h->s_ip6_hlim = 64;
6969 ip6h->s_ip6_src[0] = f->
src.addr_data32[0];
6970 ip6h->s_ip6_src[1] = f->
src.addr_data32[1];
6971 ip6h->s_ip6_src[2] = f->
src.addr_data32[2];
6972 ip6h->s_ip6_src[3] = f->
src.addr_data32[3];
6973 ip6h->s_ip6_dst[0] = f->
dst.addr_data32[0];
6974 ip6h->s_ip6_dst[1] = f->
dst.addr_data32[1];
6975 ip6h->s_ip6_dst[2] = f->
dst.addr_data32[2];
6976 ip6h->s_ip6_dst[3] = f->
dst.addr_data32[3];
6978 ip6h->s_ip6_src[0] = f->
dst.addr_data32[0];
6979 ip6h->s_ip6_src[1] = f->
dst.addr_data32[1];
6980 ip6h->s_ip6_src[2] = f->
dst.addr_data32[2];
6981 ip6h->s_ip6_src[3] = f->
dst.addr_data32[3];
6982 ip6h->s_ip6_dst[0] = f->
src.addr_data32[0];
6983 ip6h->s_ip6_dst[1] = f->
src.addr_data32[1];
6984 ip6h->s_ip6_dst[2] = f->
src.addr_data32[2];
6985 ip6h->s_ip6_dst[3] = f->
src.addr_data32[3];
7017 np->
ts = parent->
ts;
7025 FlowDeReference(&np->
flow);
7044 StreamTcpPseudoPacketCreateDetectLogFlush(
tv, stt, p, ssn, pq,
ts^0);
7045 StreamTcpPseudoPacketCreateDetectLogFlush(
tv, stt, p, ssn, pq,
ts^1);
7065 if (p->
flow == NULL)
7093 const uint8_t *seg_data;
7094 uint32_t seg_datalen;
7097 int ret = CallbackFunc(p, seg, data, seg_data, seg_datalen);
7125 if (p->
flow == NULL)
7139 if (server_node == NULL && client_node == NULL) {
7143 while (server_node != NULL || client_node != NULL) {
7144 const uint8_t *seg_data;
7145 uint32_t seg_datalen;
7146 if (server_node == NULL) {
7153 &client_stream->
sb, &client_node->
sbseg, &seg_data, &seg_datalen);
7154 ret = CallbackFunc(p, client_node, data, seg_data, seg_datalen);
7159 client_node = TCPSEG_RB_NEXT(client_node);
7160 }
else if (client_node == NULL) {
7167 &server_stream->
sb, &server_node->
sbseg, &seg_data, &seg_datalen);
7168 ret = CallbackFunc(p, server_node, data, seg_data, seg_datalen);
7173 server_node = TCPSEG_RB_NEXT(server_node);
7178 &client_stream->
sb, &client_node->
sbseg, &seg_data, &seg_datalen);
7179 ret = CallbackFunc(p, client_node, data, seg_data, seg_datalen);
7184 client_node = TCPSEG_RB_NEXT(client_node);
7187 &server_stream->
sb, &server_node->
sbseg, &seg_data, &seg_datalen);
7188 ret = CallbackFunc(p, server_node, data, seg_data, seg_datalen);
7193 server_node = TCPSEG_RB_NEXT(server_node);
7228 const char *tcp_state = NULL;
7234 tcp_state =
"syn_sent";
7237 tcp_state =
"syn_recv";
7240 tcp_state =
"established";
7243 tcp_state =
"fin_wait1";
7246 tcp_state =
"fin_wait2";
7249 tcp_state =
"time_wait";
7252 tcp_state =
"last_ack";
7255 tcp_state =
"close_wait";
7258 tcp_state =
"closing";
7261 tcp_state =
"closed";