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;
237 #if defined(DEBUG_VALIDATION) && defined(UNITTESTS)
240 BUG_ON(presize > UINT_MAX);
246 #if defined(DEBUG_VALIDATION) && defined(UNITTESTS)
249 BUG_ON(postsize > presize);
271 if (memcapcopy == 0 || size +
SC_ATOMIC_GET(st_memuse) <= memcapcopy)
283 if (size == 0 || (uint64_t)
SC_ATOMIC_GET(st_memuse) < size) {
304 if (stream != NULL) {
311 static void StreamTcp3wsFreeQueue(
TcpSession *ssn)
338 StreamTcp3wsFreeQueue(ssn);
399 static void *StreamTcpSessionPoolAlloc(
void)
413 static int StreamTcpSessionPoolInit(
void *data,
void* initdata)
423 static void StreamTcpSessionPoolCleanup(
void *s)
437 static inline bool StreamTcpInlineDropInvalid(
void)
446 static int RandomGetWrap(
void)
452 }
while(r >= ULONG_MAX - (ULONG_MAX % RAND_MAX));
466 uint16_t rdrange = 10;
475 if ((
ConfGetInt(
"stream.max-sessions", &value)) == 1) {
477 "Number of concurrent sessions is now only limited by Flow and "
478 "TCP stream engine memcaps.");
481 if ((
ConfGetInt(
"stream.prealloc-sessions", &value)) == 1) {
488 if (
ConfGetNode(
"stream.prealloc-sessions") != NULL) {
496 SCLogConfig(
"stream \"prealloc-sessions\": %"PRIu32
" (per thread)",
500 const char *temp_stream_memcap_str;
501 if (
ConfGet(
"stream.memcap", &temp_stream_memcap_str) == 1) {
502 uint64_t stream_memcap_copy;
505 "from conf file - %s. Killing engine",
506 temp_stream_memcap_str);
520 (void)
ConfGetBool(
"stream.midstream", &imidstream);
528 (void)
ConfGetBool(
"stream.async-oneside", &async_oneside);
537 if ((
ConfGetBool(
"stream.checksum-validation", &csum)) == 1) {
549 "enabled" :
"disabled");
552 const char *temp_stream_inline_str;
553 if (
ConfGet(
"stream.inline", &temp_stream_inline_str) == 1) {
558 if (strcmp(temp_stream_inline_str,
"auto") == 0) {
562 }
else if (
ConfGetBool(
"stream.inline", &inl) == 1) {
581 ?
"enabled" :
"disabled");
585 if ((
ConfGetBool(
"stream.bypass", &bypass)) == 1) {
594 ?
"enabled" :
"disabled");
597 int drop_invalid = 0;
598 if ((
ConfGetBool(
"stream.drop-invalid", &drop_invalid)) == 1) {
599 if (drop_invalid == 1) {
606 if ((
ConfGetInt(
"stream.max-syn-queued", &value)) == 1) {
607 if (value >= 0 && value <= 255) {
619 if ((
ConfGetInt(
"stream.max-synack-queued", &value)) == 1) {
620 if (value >= 0 && value <= 255) {
632 const char *temp_stream_reassembly_memcap_str;
633 if (
ConfGet(
"stream.reassembly.memcap", &temp_stream_reassembly_memcap_str) == 1) {
634 uint64_t stream_reassembly_memcap_copy;
636 &stream_reassembly_memcap_copy) < 0) {
638 "stream.reassembly.memcap "
639 "from conf file - %s. Killing engine",
640 temp_stream_reassembly_memcap_str);
650 SCLogConfig(
"stream.reassembly \"memcap\": %"PRIu64
"",
654 const char *temp_stream_reassembly_depth_str;
655 if (
ConfGet(
"stream.reassembly.depth", &temp_stream_reassembly_depth_str) == 1) {
659 "stream.reassembly.depth "
660 "from conf file - %s. Killing engine",
661 temp_stream_reassembly_depth_str);
673 if ((
ConfGetBool(
"stream.reassembly.randomize-chunk-size", &randomize)) == 0) {
681 const char *temp_rdrange;
682 if (
ConfGet(
"stream.reassembly.randomize-chunk-range", &temp_rdrange) == 1) {
685 "stream.reassembly.randomize-chunk-range "
686 "from conf file - %s. Killing engine",
689 }
else if (rdrange >= 100) {
690 FatalError(
"stream.reassembly.randomize-chunk-range "
691 "must be lower than 100");
696 const char *temp_stream_reassembly_toserver_chunk_size_str;
697 if (
ConfGet(
"stream.reassembly.toserver-chunk-size",
698 &temp_stream_reassembly_toserver_chunk_size_str) == 1) {
702 "stream.reassembly.toserver-chunk-size "
703 "from conf file - %s. Killing engine",
704 temp_stream_reassembly_toserver_chunk_size_str);
713 long int r = RandomGetWrap();
718 const char *temp_stream_reassembly_toclient_chunk_size_str;
719 if (
ConfGet(
"stream.reassembly.toclient-chunk-size",
720 &temp_stream_reassembly_toclient_chunk_size_str) == 1) {
724 "stream.reassembly.toclient-chunk-size "
725 "from conf file - %s. Killing engine",
726 temp_stream_reassembly_toclient_chunk_size_str);
735 long int r = RandomGetWrap();
741 SCLogConfig(
"stream.reassembly \"toserver-chunk-size\": %"PRIu16,
743 SCLogConfig(
"stream.reassembly \"toclient-chunk-size\": %"PRIu16,
748 if (
ConfGetBool(
"stream.reassembly.raw", &enable_raw) == 1) {
756 SCLogConfig(
"stream.reassembly.raw: %s", enable_raw ?
"enabled" :
"disabled");
760 int liberal_timestamps = 0;
761 if (
ConfGetBool(
"stream.liberal-timestamps", &liberal_timestamps) == 1) {
765 SCLogConfig(
"stream.liberal-timestamps: %s", liberal_timestamps ?
"enabled" :
"disabled");
785 StreamTcpSessionPoolAlloc,
786 StreamTcpSessionPoolInit, NULL,
787 StreamTcpSessionPoolCleanup, NULL);
806 SCLogDebug(
"ssn_pool_cnt %"PRIu64
"", ssn_pool_cnt);
809 static bool IsReassemblyMemcapExceptionPolicyStatsValid(
enum ExceptionPolicy exception_policy)
817 static bool IsStreamTcpSessionMemcapExceptionPolicyStatsValid(
enum ExceptionPolicy policy)
825 static void StreamTcpSsnMemcapExceptionPolicyStatsIncr(
869 if (
unlikely((g_eps_stream_ssn_memcap != UINT64_MAX &&
870 g_eps_stream_ssn_memcap ==
t_pcapcnt))) {
885 const TCPHdr *tcph = PacketGetTCP(p);
944 if (PacketIsIPv4(p)) {
954 }
else if (PacketIsIPv6(p)) {
981 #define StreamTcpUpdateLastAck(ssn, stream, ack) { \
982 if (SEQ_GT((ack), (stream)->last_ack)) \
984 SCLogDebug("ssn %p: last_ack set to %"PRIu32", moved %u forward", (ssn), (ack), (ack) - (stream)->last_ack); \
985 if ((SEQ_LEQ((stream)->last_ack, (stream)->next_seq) && SEQ_GT((ack),(stream)->next_seq))) { \
986 SCLogDebug("last_ack just passed next_seq: %u (was %u) > %u", (ack), (stream)->last_ack, (stream)->next_seq); \
988 SCLogDebug("next_seq (%u) <> last_ack now %d", (stream)->next_seq, (int)(stream)->next_seq - (ack)); \
990 (stream)->last_ack = (ack); \
991 StreamTcpSackPruneList((stream)); \
993 SCLogDebug("ssn %p: no update: ack %u, last_ack %"PRIu32", next_seq %u (state %u)", \
994 (ssn), (ack), (stream)->last_ack, (stream)->next_seq, (ssn)->state); \
998 #define StreamTcpAsyncLastAckUpdate(ssn, stream) { \
999 if ((ssn)->flags & STREAMTCP_FLAG_ASYNC) { \
1000 if (SEQ_GT((stream)->next_seq, (stream)->last_ack)) { \
1001 uint32_t ack_diff = (stream)->next_seq - (stream)->last_ack; \
1002 (stream)->last_ack += ack_diff; \
1003 SCLogDebug("ssn %p: ASYNC last_ack set to %"PRIu32", moved %u forward", \
1004 (ssn), (stream)->next_seq, ack_diff); \
1009 #define StreamTcpUpdateNextSeq(ssn, stream, seq) { \
1010 (stream)->next_seq = seq; \
1011 SCLogDebug("ssn %p: next_seq %" PRIu32, (ssn), (stream)->next_seq); \
1012 StreamTcpAsyncLastAckUpdate((ssn), (stream)); \
1022 #define StreamTcpUpdateNextWin(ssn, stream, win) { \
1023 uint32_t sacked_size__ = StreamTcpSackedSize((stream)); \
1024 if (SEQ_GT(((win) + sacked_size__), (stream)->next_win)) { \
1025 (stream)->next_win = ((win) + sacked_size__); \
1026 SCLogDebug("ssn %p: next_win set to %"PRIu32, (ssn), (stream)->next_win); \
1034 SCLogDebug(
"ssn %p: (state: %s) Reset received and state changed to "
1038 static bool IsMidstreamExceptionPolicyStatsValid(
enum ExceptionPolicy policy)
1052 static void StreamTcpMidstreamExceptionPolicyStatsIncr(
1061 static int StreamTcpPacketIsRetransmission(
TcpStream *stream,
Packet *p)
1066 const TCPHdr *tcph = PacketGetTCP(p);
1104 static int StreamTcpPacketStateNone(
1107 const TCPHdr *tcph = PacketGetTCP(p);
1110 SCLogDebug(
"RST packet received, no session setup");
1120 SCLogDebug(
"FIN packet received, no session setup");
1126 SCLogDebug(
"FIN packet received, no session setup");
1143 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1175 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
", "
1176 "ssn->server.next_win %" PRIu32
"",
1178 SCLogDebug(
"ssn %p: ssn->client.last_ack %" PRIu32
", "
1179 "ssn->server.last_ack %" PRIu32
"",
1187 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1188 "ssn->client.last_ts %" PRIu32
"",
1207 SCLogDebug(
"ssn %p: assuming SACK permitted for both sides", ssn);
1216 SCLogDebug(
"Midstream not enabled, so won't pick up a session");
1221 SCLogDebug(
"Midstream policy not permissive, so won't pick up a session");
1244 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1245 "TCP_SYN_RECV", ssn);
1276 SCLogDebug(
"ssn %p: wscale enabled. client %u server %u",
1280 SCLogDebug(
"ssn %p: ssn->client.isn %"PRIu32
", ssn->client.next_seq"
1281 " %"PRIu32
", ssn->client.last_ack %"PRIu32
"", ssn,
1284 SCLogDebug(
"ssn %p: ssn->server.isn %"PRIu32
", ssn->server.next_seq"
1285 " %"PRIu32
", ssn->server.last_ack %"PRIu32
"", ssn,
1294 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1295 "ssn->client.last_ts %" PRIu32
"", ssn,
1313 SCLogDebug(
"ssn %p: SYN/ACK with SACK permitted, assuming "
1314 "SACK permitted for both sides", ssn);
1332 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_SYN_SENT", ssn);
1365 SCLogDebug(
"ssn %p: SACK permitted on SYN packet", ssn);
1372 SCLogDebug(
"ssn: %p (TFO) isn %u base_seq %u next_seq %u payload len %u", ssn,
1379 SCLogDebug(
"ssn %p: ssn->client.isn %" PRIu32
", "
1380 "ssn->client.next_seq %" PRIu32
", ssn->client.last_ack "
1390 SCLogDebug(
"Midstream not enabled, so won't pick up a session");
1395 SCLogDebug(
"Midstream policy not permissive, so won't pick up a session");
1412 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1413 "TCP_ESTABLISHED", ssn);
1434 SCLogDebug(
"ssn %p: ssn->client.isn %u, ssn->client.next_seq %u",
1443 SCLogDebug(
"ssn %p: ssn->client.next_win %"PRIu32
", "
1444 "ssn->server.next_win %"PRIu32
"", ssn,
1446 SCLogDebug(
"ssn %p: ssn->client.last_ack %"PRIu32
", "
1447 "ssn->server.last_ack %"PRIu32
"", ssn,
1455 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1456 "ssn->client.last_ts %" PRIu32
"", ssn,
1475 SCLogDebug(
"ssn %p: assuming SACK permitted for both sides", ssn);
1489 const TCPHdr *tcph = PacketGetTCP(p);
1519 StreamTcp3whsSynAckToStateQueue(p, &search);
1527 search.
ts == q->
ts) {
1540 if (StreamTcp3whsFindSynAckBySynAck(ssn, p) != NULL)
1544 SCLogDebug(
"ssn %p: =~ SYN/ACK queue limit reached", ssn);
1550 SCLogDebug(
"ssn %p: =~ SYN/ACK queue failed: stream memcap reached", ssn);
1556 SCLogDebug(
"ssn %p: =~ SYN/ACK queue failed: alloc failed", ssn);
1561 StreamTcp3whsSynAckToStateQueue(p, q);
1575 const TCPHdr *tcph = PacketGetTCP(p);
1610 StreamTcp3whsSynAckToStateQueue(p, &update);
1617 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_SYN_RECV", ssn);
1633 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1634 "ssn->client.last_ts %" PRIu32
"", ssn,
1662 SCLogDebug(
"ssn %p: SACK permitted for session", ssn);
1669 SCLogDebug(
"ssn %p: ssn->server.next_win %" PRIu32
"", ssn,
1671 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
"", ssn,
1673 SCLogDebug(
"ssn %p: ssn->server.isn %" PRIu32
", "
1674 "ssn->server.next_seq %" PRIu32
", "
1675 "ssn->server.last_ack %" PRIu32
" "
1676 "(ssn->client.last_ack %" PRIu32
")", ssn,
1683 SCLogDebug(
"ssn %p: STREAMTCP_FLAG_4WHS unset, normal SYN/ACK"
1684 " so considering 3WHS", ssn);
1695 static inline bool StateSynSentValidateTimestamp(
TcpSession *ssn,
Packet *p)
1705 if (receiver_stream->
last_ts != 0 && ts_echo != 0 &&
1706 ts_echo != receiver_stream->
last_ts)
1708 SCLogDebug(
"ssn %p: BAD TSECR echo %u recv %u", ssn,
1709 ts_echo, receiver_stream->
last_ts);
1713 if (receiver_stream->
last_ts == 0 && ts_echo != 0) {
1714 SCLogDebug(
"ssn %p: BAD TSECR echo %u recv %u", ssn,
1715 ts_echo, receiver_stream->
last_ts);
1725 memset(q, 0,
sizeof(*q));
1745 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1751 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1755 memset(q, 0,
sizeof(*q));
1756 const TCPHdr *tcph = PacketGetTCP(p);
1774 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1781 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1788 memset(q, 0,
sizeof(*q));
1790 const TCPHdr *tcph = PacketGetTCP(p);
1807 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1817 SCLogDebug(
"ssn %p: search state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, s, s->
seq, s->
win,
1821 SCLogDebug(
"ssn %p: queue state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq,
1835 TcpStateQueueInitFromSsnSyn(ssn, &search);
1838 if (ssn->
queue != NULL && StreamTcp3whsFindSyn(ssn, &search) != NULL)
1842 SCLogDebug(
"ssn %p: =~ SYN queue limit reached", ssn);
1848 SCLogDebug(
"ssn %p: =~ SYN queue failed: stream memcap reached", ssn);
1854 SCLogDebug(
"ssn %p: =~ SYN queue failed: alloc failed", ssn);
1901 static int StreamTcpPacketStateSynSent(
1905 const TCPHdr *tcph = PacketGetTCP(p);
1911 SCLogDebug(
"ssn %p: SYN/ACK on SYN_SENT state for packet %" PRIu64, ssn, p->
pcap_cnt);
1918 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
1919 "%" PRIu32
" from stream",
1925 SCLogDebug(
"ssn %p: (TFO) ACK matches next_seq, packet ACK %" PRIu32
" == "
1926 "%" PRIu32
" from stream",
1929 SCLogDebug(
"ssn %p: (TFO) ACK matches ISN+1, packet ACK %" PRIu32
" == "
1930 "%" PRIu32
" from stream",
1938 SCLogDebug(
"ssn %p: (TFO) ACK mismatch, packet ACK %" PRIu32
" != "
1939 "%" PRIu32
" from stream",
1947 const bool ts_mismatch = !StateSynSentValidateTimestamp(ssn, p);
1952 TcpStateQueueInitFromPktSynAck(p, &search);
1954 const TcpStateQueue *q = StreamTcp3whsFindSyn(ssn, &search);
1960 SCLogDebug(
"ssn %p: found queued SYN state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u",
1964 StreamTcp3whsStoreSynApplyToSsn(ssn, q);
1974 StreamTcp3wsFreeQueue(ssn);
1976 StreamTcp3whsSynAckUpdate(ssn, p, NULL);
1983 SCLogDebug(
"ssn %p: SYN/ACK received in the wrong direction", ssn);
1987 SCLogDebug(
"ssn %p: SYN/ACK received on 4WHS session", ssn);
1994 SCLogDebug(
"ssn %p: 4WHS ACK mismatch, packet ACK %" PRIu32
""
1995 " != %" PRIu32
" from stream",
2005 SCLogDebug(
"ssn %p: 4WHS SEQ mismatch, packet SEQ %" PRIu32
""
2006 " != %" PRIu32
" from *first* SYN pkt",
2013 SCLogDebug(
"ssn %p: =~ 4WHS ssn state is now TCP_SYN_RECV", ssn);
2027 SCLogDebug(
"ssn %p: 4WHS ssn->client.last_ts %" PRIu32
" "
2028 "ssn->server.last_ts %" PRIu32
"",
2053 SCLogDebug(
"ssn %p: SACK permitted for 4WHS session", ssn);
2060 SCLogDebug(
"ssn %p: 4WHS ssn->client.isn %" PRIu32
", "
2061 "ssn->client.next_seq %" PRIu32
", "
2062 "ssn->client.last_ack %" PRIu32
" "
2063 "(ssn->server.last_ack %" PRIu32
")",
2072 if (StateSynSentValidateTimestamp(ssn, p) ==
false) {
2080 if (!StreamTcpValidateRst(ssn, p))
2087 SCLogDebug(
"ssn->server.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2089 StreamTcpCloseSsnWithReset(p, ssn);
2090 StreamTcp3wsFreeQueue(ssn);
2094 SCLogDebug(
"ssn->client.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2095 StreamTcpCloseSsnWithReset(p, ssn);
2096 StreamTcp3wsFreeQueue(ssn);
2104 SCLogDebug(
"ssn %p: SYN packet on state SYN_SENT... resent", ssn);
2106 SCLogDebug(
"ssn %p: SYN packet on state SYN_SENT... resent of "
2119 SCLogDebug(
"ssn %p: STREAMTCP_FLAG_4WHS flag set", ssn);
2156 SCLogDebug(
"ssn %p: 4WHS ssn->server.isn %" PRIu32
", "
2157 "ssn->server.next_seq %" PRIu32
", "
2158 "ssn->server.last_ack %"PRIu32
"", ssn,
2161 SCLogDebug(
"ssn %p: 4WHS ssn->client.isn %" PRIu32
", "
2162 "ssn->client.next_seq %" PRIu32
", "
2163 "ssn->client.last_ack %"PRIu32
"", ssn,
2172 TcpStateQueueInitFromPktSyn(p, &syn_pkt);
2173 TcpStateQueueInitFromSsnSyn(ssn, &syn_ssn);
2175 if (memcmp(&syn_pkt, &syn_ssn,
sizeof(
TcpStateQueue)) != 0) {
2177 StreamTcp3whsStoreSyn(ssn, p);
2178 SCLogDebug(
"ssn %p: Retransmitted SYN. Updating ssn from packet %" PRIu64
2179 ". Stored previous state",
2182 StreamTcp3whsStoreSynApplyToSsn(ssn, &syn_pkt);
2198 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
2199 "%" PRIu32
" from stream",
2206 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2207 StreamTcp3wsFreeQueue(ssn);
2220 SCLogDebug(
"ssn %p: synsent => Asynchronous stream, packet SEQ"
2221 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2222 "ssn->client.next_seq %" PRIu32
"",
2271 static int StreamTcpPacketStateSynRecv(
2275 const TCPHdr *tcph = PacketGetTCP(p);
2278 if (!StreamTcpValidateRst(ssn, p))
2295 SCLogDebug(
"Detection evasion has been attempted, so"
2296 " not resetting the connection !!");
2304 SCLogDebug(
"Detection evasion has been attempted, so"
2305 " not resetting the connection !!");
2311 StreamTcpCloseSsnWithReset(p, ssn);
2314 StreamTcpHandleTimestamp(ssn, p);
2321 if (!StreamTcpValidateTimestamp(ssn, p))
2325 if ((StreamTcpHandleFin(
tv, stt, ssn, p)) == -1)
2330 SCLogDebug(
"ssn %p: SYN/ACK packet on state SYN_RECV. resent", ssn);
2333 SCLogDebug(
"ssn %p: SYN/ACK-pkt to server in SYN_RECV state", ssn);
2342 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
2343 "%" PRIu32
" from stream",
2353 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
2354 "%" PRIu32
" from stream",
2357 if (StreamTcp3whsQueueSynAck(ssn, p) == -1)
2359 SCLogDebug(
"ssn %p: queued different SYN/ACK", ssn);
2363 SCLogDebug(
"ssn %p: SYN packet on state SYN_RECV... resent", ssn);
2366 SCLogDebug(
"ssn %p: SYN-pkt to client in SYN_RECV state", ssn);
2373 SCLogDebug(
"ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
2381 SCLogDebug(
"ssn %p: checking ACK against queued SYN/ACKs", ssn);
2384 SCLogDebug(
"ssn %p: here we update state against queued SYN/ACK", ssn);
2385 StreamTcp3whsSynAckUpdate(ssn, p, q);
2387 SCLogDebug(
"ssn %p: none found, now checking ACK against original SYN/ACK (state)", ssn);
2397 if (!(StreamTcpValidateTimestamp(ssn, p))) {
2403 SCLogDebug(
"ssn %p: ACK received on 4WHS session",ssn);
2406 SCLogDebug(
"ssn %p: 4WHS wrong seq nr on packet", ssn);
2411 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
2412 SCLogDebug(
"ssn %p: 4WHS invalid ack nr on packet", ssn);
2418 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
2419 "%" PRIu32
", ACK %" PRIu32
"",
2423 StreamTcpHandleTimestamp(ssn, p);
2432 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2436 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
", "
2437 "ssn->client.last_ack %"PRIu32
"", ssn,
2442 bool ack_indicates_missed_3whs_ack_packet =
false;
2452 SCLogDebug(
"ssn %p: ACK received on midstream SYN/ACK "
2453 "pickup session",ssn);
2456 SCLogDebug(
"ssn %p: ACK received on TFO session",ssn);
2473 SCLogDebug(
"ssn %p: possible data injection", ssn);
2478 SCLogDebug(
"ssn %p: ACK received in the wrong direction",
2483 ack_indicates_missed_3whs_ack_packet =
true;
2487 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ %" PRIu32
""
2488 ", ACK %" PRIu32
"",
2500 StreamTcpHandleTimestamp(ssn, p);
2524 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2542 StreamTcpHandleTimestamp(ssn, p);
2555 SCLogDebug(
"ssn %p: synrecv => Asynchronous stream, packet SEQ"
2556 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2557 "ssn->server.next_seq %" PRIu32,
2562 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2571 SCLogDebug(
"ssn %p: wrong ack nr on packet, possible evasion!!",
2581 SCLogDebug(
"ssn %p: ACK for missing data", ssn);
2584 StreamTcpHandleTimestamp(ssn, p);
2590 SCLogDebug(
"ssn %p: ACK for missing data: ssn->server.next_seq %u", ssn,
2600 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2609 SCLogDebug(
"ssn %p: ACK for missing data", ssn);
2612 StreamTcpHandleTimestamp(ssn, p);
2634 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2639 }
else if ((ack_indicates_missed_3whs_ack_packet ||
2643 if (ack_indicates_missed_3whs_ack_packet) {
2644 SCLogDebug(
"ssn %p: packet fits perfectly after a missed 3whs-ACK", ssn);
2646 SCLogDebug(
"ssn %p: (TFO) expected packet fits perfectly after SYN/ACK", ssn);
2655 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2660 SCLogDebug(
"ssn %p: wrong seq nr on packet", ssn);
2666 SCLogDebug(
"ssn %p: ssn->server.next_win %" PRIu32
", "
2667 "ssn->server.last_ack %"PRIu32
"", ssn,
2689 static int HandleEstablishedPacketToServer(
2692 const TCPHdr *tcph = PacketGetTCP(p);
2697 SCLogDebug(
"ssn %p: =+ pkt (%" PRIu32
") is to server: SEQ %" PRIu32
","
2698 "ACK %" PRIu32
", WIN %" PRIu16
"",
2704 SCLogDebug(
"ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
2707 }
else if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
2708 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
2716 SCLogDebug(
"ssn %p: pkt is keep alive", ssn);
2721 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ"
2722 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
2723 " ssn->client.last_ack %" PRIu32
", ssn->client.next_win"
2724 "%" PRIu32
"(%" PRIu32
")",
2734 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ."
2735 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2736 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2737 "%" PRIu32
"(%" PRIu32
")",
2749 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ"
2750 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2751 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2752 "%" PRIu32
"(%" PRIu32
")",
2767 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
2768 " before last_ack %" PRIu32
", after next_seq %" PRIu32
":"
2769 " acked data that we haven't seen before",
2772 SCLogDebug(
"ssn %p: server => SEQ before last_ack, packet SEQ"
2773 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2774 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2775 "%" PRIu32
"(%" PRIu32
")",
2779 SCLogDebug(
"ssn %p: rejecting because pkt before last_ack", ssn);
2785 int zerowindowprobe = 0;
2788 SCLogDebug(
"ssn %p: zero window probe", ssn);
2789 zerowindowprobe = 1;
2799 if (zerowindowprobe) {
2800 SCLogDebug(
"ssn %p: zero window probe, skipping oow check", ssn);
2803 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
2808 SCLogDebug(
"ssn %p: ssn->server.window %"PRIu32
"", ssn,
2825 StreamTcpHandleTimestamp(ssn, p);
2837 SCLogDebug(
"ssn %p: toserver => SEQ out of window, packet SEQ "
2838 "%" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
2839 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2840 "%" PRIu32
"(%" PRIu32
")",
2844 StreamTcpSackedSize(&ssn->
client));
2864 static int HandleEstablishedPacketToClient(
2867 const TCPHdr *tcph = PacketGetTCP(p);
2872 SCLogDebug(
"ssn %p: =+ pkt (%" PRIu32
") is to client: SEQ %" PRIu32
","
2873 " ACK %" PRIu32
", WIN %" PRIu16
"",
2879 SCLogDebug(
"ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
2882 }
else if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
2883 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
2897 SCLogDebug(
"ssn %p: adjusted midstream ssn->server.next_win to "
2903 SCLogDebug(
"ssn %p: pkt is keep alive", ssn);
2909 SCLogDebug(
"ssn %p: client => Asynchronous stream, packet SEQ"
2910 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
2911 " ssn->client.last_ack %" PRIu32
", ssn->client.next_win"
2912 " %" PRIu32
"(%" PRIu32
")",
2923 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
2924 " before last_ack %" PRIu32
", after next_seq %" PRIu32
":"
2925 " acked data that we haven't seen before",
2928 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
2929 " before last_ack %" PRIu32
". next_seq %" PRIu32,
2936 int zerowindowprobe = 0;
2939 SCLogDebug(
"ssn %p: zero window probe", ssn);
2940 zerowindowprobe = 1;
2951 if (zerowindowprobe) {
2952 SCLogDebug(
"ssn %p: zero window probe, skipping oow check", ssn);
2955 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
2959 SCLogDebug(
"ssn %p: ssn->client.window %"PRIu32
"", ssn,
2972 StreamTcpHandleTimestamp(ssn, p);
2981 SCLogDebug(
"ssn %p: client => SEQ out of window, packet SEQ"
2982 "%" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
2983 " ssn->server.last_ack %" PRIu32
", ssn->server.next_win "
2984 "%" PRIu32
"(%" PRIu32
")",
3005 static inline uint32_t StreamTcpResetGetMaxAck(
TcpStream *stream, uint32_t
seq)
3011 if (
SEQ_GT(tail_seq, ack)) {
3019 static bool StreamTcpPacketIsZeroWindowProbeAck(
const TcpSession *ssn,
const Packet *p)
3021 const TCPHdr *tcph = PacketGetTCP(p);
3045 if (pkt_win != rcv->
window)
3052 SCLogDebug(
"ssn %p: packet %" PRIu64
" is a Zero Window Probe ACK", ssn, p->
pcap_cnt);
3059 static bool StreamTcpPacketIsDupAck(
const TcpSession *ssn,
const Packet *p)
3061 const TCPHdr *tcph = PacketGetTCP(p);
3079 if (pkt_win == 0 || rcv->
window == 0)
3081 if (pkt_win != rcv->
window)
3089 SCLogDebug(
"ssn %p: packet:%" PRIu64
" seq:%u ack:%u win:%u snd %u:%u:%u rcv %u:%u:%u", ssn,
3113 const TCPHdr *tcph = PacketGetTCP(p);
3164 static int StreamTcpPacketIsSpuriousRetransmission(
const TcpSession *ssn,
Packet *p)
3175 const TCPHdr *tcph = PacketGetTCP(p);
3181 "ssn %p: spurious retransmission; packet entirely before base_seq: SEQ %u(%u) "
3182 "last_ack %u base_seq %u",
3191 SCLogDebug(
"ssn %p: spurious retransmission; packet entirely before last_ack: SEQ %u(%u) "
3199 SCLogDebug(
"ssn %p: NOT spurious retransmission; packet NOT entirely before last_ack: SEQ "
3200 "%u(%u) last_ack %u, base_seq %u",
3217 static int StreamTcpPacketStateEstablished(
3221 const TCPHdr *tcph = PacketGetTCP(p);
3227 if (!StreamTcpValidateRst(ssn, p))
3231 StreamTcpCloseSsnWithReset(p, ssn);
3235 SCLogDebug(
"ssn %p: ssn->server.next_seq %" PRIu32
"", ssn,
3241 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, window));
3246 StreamTcpHandleTimestamp(ssn, p);
3250 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3258 StreamTcpCloseSsnWithReset(p, ssn);
3263 SCLogDebug(
"ssn %p: ssn->server.next_seq %" PRIu32
"", ssn,
3269 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
3274 StreamTcpHandleTimestamp(ssn, p);
3278 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3289 if (!StreamTcpValidateTimestamp(ssn, p))
3294 " %" PRIu32
", last ACK %" PRIu32
", next win %"PRIu32
","
3299 if ((StreamTcpHandleFin(
tv, stt, ssn, p)) == -1)
3304 SCLogDebug(
"ssn %p: SYN/ACK packet on state ESTABLISHED... resent",
3308 SCLogDebug(
"ssn %p: SYN/ACK-pkt to server in ESTABLISHED state", ssn);
3317 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
3318 "%" PRIu32
" from stream",
3328 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
3329 "%" PRIu32
" from stream",
3342 SCLogDebug(
"ssn %p: SYN/ACK packet on state ESTABLISHED... resent. "
3343 "Likely due server not receiving final ACK in 3whs", ssn);
3347 SCLogDebug(
"ssn %p: SYN packet on state ESTABLISHED... resent", ssn);
3349 SCLogDebug(
"ssn %p: SYN-pkt to client in EST state", ssn);
3356 SCLogDebug(
"ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
3377 if (!StreamTcpValidateTimestamp(ssn, p))
3383 HandleEstablishedPacketToServer(
tv, ssn, p, stt);
3385 SCLogDebug(
"ssn %p: next SEQ %" PRIu32
", last ACK %" PRIu32
","
3386 " next win %" PRIu32
", win %" PRIu32
"", ssn,
3393 SCLogDebug(
"3whs is now confirmed by server");
3397 HandleEstablishedPacketToClient(
tv, ssn, p, stt);
3399 SCLogDebug(
"ssn %p: next SEQ %" PRIu32
", last ACK %" PRIu32
","
3400 " next win %" PRIu32
", win %" PRIu32
"", ssn,
3425 const TCPHdr *tcph = PacketGetTCP(p);
3431 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ %" PRIu32
","
3435 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3436 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3442 SCLogDebug(
"ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn,
seq, pkt_re,
3447 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
" != "
3448 "%" PRIu32
" from stream",
3461 SCLogDebug(
"ssn %p: state changed to TCP_CLOSE_WAIT", ssn);
3466 SCLogDebug(
"ssn %p: ssn->client.next_seq %" PRIu32
"", ssn,
3471 StreamTcpHandleTimestamp(ssn, p);
3484 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK %" PRIu32
"",
3487 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ %" PRIu32
", "
3491 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3492 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3498 SCLogDebug(
"ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn,
seq, pkt_re,
3503 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
" != "
3504 "%" PRIu32
" from stream (last_ack %u win %u = %u)",
3513 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT1", ssn);
3522 StreamTcpHandleTimestamp(ssn, p);
3535 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK %" PRIu32
"",
3555 static int StreamTcpPacketStateFinWait1(
3559 const TCPHdr *tcph = PacketGetTCP(p);
3565 if (!StreamTcpValidateRst(ssn, p))
3568 StreamTcpCloseSsnWithReset(p, ssn);
3573 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, ack));
3578 StreamTcpHandleTimestamp(ssn, p);
3585 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
3590 StreamTcpHandleTimestamp(ssn, p);
3598 if (!StreamTcpValidateTimestamp(ssn, p))
3603 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3604 "%" PRIu32
", ACK %" PRIu32
"",
3606 int retransmission = 0;
3608 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
3609 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3615 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3616 " != %" PRIu32
" from stream",
3622 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3623 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3628 if (!retransmission) {
3630 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
3636 StreamTcpHandleTimestamp(ssn, p);
3652 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3656 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3657 "%" PRIu32
", ACK %" PRIu32
"",
3659 int retransmission = 0;
3661 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
3662 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3667 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3673 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3674 " != %" PRIu32
" from stream",
3680 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3681 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3687 StreamTcpHandleTimestamp(ssn, p);
3690 if (!retransmission) {
3692 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
3710 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3717 if (!StreamTcpValidateTimestamp(ssn, p))
3722 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3723 "%" PRIu32
", ACK %" PRIu32
"",
3725 int retransmission = 0;
3727 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
3728 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3734 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3735 " != %" PRIu32
" from stream",
3741 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3742 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3747 if (!retransmission) {
3749 SCLogDebug(
"ssn %p: state changed to TCP_CLOSING", ssn);
3755 StreamTcpHandleTimestamp(ssn, p);
3772 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3776 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3777 "%" PRIu32
", ACK %" PRIu32
"",
3780 int retransmission = 0;
3782 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
3783 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3789 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3790 " != %" PRIu32
" from stream",
3796 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3797 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3802 if (!retransmission) {
3804 SCLogDebug(
"ssn %p: state changed to TCP_CLOSING", ssn);
3810 StreamTcpHandleTimestamp(ssn, p);
3827 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3832 SCLogDebug(
"ssn (%p): SYN pkt on FinWait1", ssn);
3838 if (!StreamTcpValidateTimestamp(ssn, p))
3843 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3844 "%" PRIu32
", ACK %" PRIu32
"",
3846 int retransmission = 0;
3848 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
3849 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3854 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3855 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3862 "ssn %p: ACK's older segment as %u < %u", ssn, ack, ssn->
server.
next_seq);
3863 }
else if (!retransmission) {
3867 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
3873 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT2", ssn);
3876 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3877 " != %" PRIu32
" from stream",
3889 StreamTcpHandleTimestamp(ssn, p);
3910 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3916 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3917 "%" PRIu32
", ACK %" PRIu32
"",
3920 int retransmission = 0;
3922 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
3923 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3928 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3929 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3934 if (!retransmission) {
3937 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
3943 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT2", ssn);
3946 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3947 " != %" PRIu32
" from stream",
3957 StreamTcpHandleTimestamp(ssn, p);
3978 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3999 static int StreamTcpPacketStateFinWait2(
4003 const TCPHdr *tcph = PacketGetTCP(p);
4009 if (!StreamTcpValidateRst(ssn, p))
4012 StreamTcpCloseSsnWithReset(p, ssn);
4017 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, ack));
4022 StreamTcpHandleTimestamp(ssn, p);
4029 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
4034 StreamTcpHandleTimestamp(ssn, p);
4042 if (!StreamTcpValidateTimestamp(ssn, p))
4047 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4048 "%" PRIu32
", ACK %" PRIu32
"",
4050 int retransmission = 0;
4056 }
else if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4057 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4063 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ "
4064 "%" PRIu32
" != %" PRIu32
" from stream",
4070 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4071 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4076 if (!retransmission) {
4078 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4088 StreamTcpHandleTimestamp(ssn, p);
4101 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4105 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4106 "%" PRIu32
", ACK %" PRIu32
"",
4108 int retransmission = 0;
4114 }
else if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4115 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4121 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ "
4122 "%" PRIu32
" != %" PRIu32
" from stream",
4128 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4129 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4134 if (!retransmission) {
4136 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4142 StreamTcpHandleTimestamp(ssn, p);
4154 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4160 SCLogDebug(
"ssn (%p): SYN pkt on FinWait2", ssn);
4166 if (!StreamTcpValidateTimestamp(ssn, p))
4171 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4172 "%" PRIu32
", ACK %" PRIu32
"",
4174 int retransmission = 0;
4176 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4177 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4182 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4183 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4188 if (!retransmission) {
4191 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
4196 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4197 " != %" PRIu32
" from stream",
4207 StreamTcpHandleTimestamp(ssn, p);
4223 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4227 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4228 "%" PRIu32
", ACK %" PRIu32
"",
4230 int retransmission = 0;
4232 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4233 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4238 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4239 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4244 if (!retransmission) {
4247 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
4251 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4252 " != %" PRIu32
" from stream",
4262 StreamTcpHandleTimestamp(ssn, p);
4278 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4299 static int StreamTcpPacketStateClosing(
4303 const TCPHdr *tcph = PacketGetTCP(p);
4309 if (!StreamTcpValidateRst(ssn, p))
4312 StreamTcpCloseSsnWithReset(p, ssn);
4317 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, ack));
4322 StreamTcpHandleTimestamp(ssn, p);
4329 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
4334 StreamTcpHandleTimestamp(ssn, p);
4341 SCLogDebug(
"ssn (%p): SYN pkt on Closing", ssn);
4347 if (!StreamTcpValidateTimestamp(ssn, p))
4352 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4353 "%" PRIu32
", ACK %" PRIu32
"",
4355 int retransmission = 0;
4356 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4357 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4363 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4364 " != %" PRIu32
" from stream",
4370 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4371 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4376 if (!retransmission) {
4378 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4384 StreamTcpHandleTimestamp(ssn, p);
4394 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4398 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4399 "%" PRIu32
", ACK %" PRIu32
"",
4401 int retransmission = 0;
4402 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4403 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4409 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4410 " != %" PRIu32
" from stream",
4416 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4417 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4422 if (!retransmission) {
4424 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4430 StreamTcpHandleTimestamp(ssn, p);
4441 SCLogDebug(
"StreamTcpPacketStateClosing (%p): =+ next SEQ "
4442 "%" PRIu32
", last ACK %" PRIu32
"", ssn,
4462 static int StreamTcpPacketStateCloseWait(
4466 const TCPHdr *tcph = PacketGetTCP(p);
4474 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4475 "%" PRIu32
", ACK %" PRIu32
"",
4478 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4479 "%" PRIu32
", ACK %" PRIu32
"",
4484 if (!StreamTcpValidateRst(ssn, p))
4487 StreamTcpCloseSsnWithReset(p, ssn);
4492 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, ack));
4497 StreamTcpHandleTimestamp(ssn, p);
4504 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
4509 StreamTcpHandleTimestamp(ssn, p);
4517 if (!StreamTcpValidateTimestamp(ssn, p))
4522 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4523 "%" PRIu32
", ACK %" PRIu32
"",
4526 int retransmission = 0;
4527 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4528 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4533 if (!retransmission) {
4536 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4537 " != %" PRIu32
" from stream",
4544 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4545 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4552 if (!retransmission)
4556 StreamTcpHandleTimestamp(ssn, p);
4568 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4572 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4573 "%" PRIu32
", ACK %" PRIu32
"",
4576 int retransmission = 0;
4577 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4578 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4583 if (!retransmission) {
4586 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4587 " != %" PRIu32
" from stream",
4594 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4595 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4600 if (!retransmission) {
4602 SCLogDebug(
"ssn %p: state changed to TCP_LAST_ACK", ssn);
4608 StreamTcpHandleTimestamp(ssn, p);
4620 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4626 SCLogDebug(
"ssn (%p): SYN pkt on CloseWait", ssn);
4632 if (!StreamTcpValidateTimestamp(ssn, p))
4637 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4638 "%" PRIu32
", ACK %" PRIu32
"",
4641 int retransmission = 0;
4642 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4643 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4649 SCLogDebug(
"ssn %p: -> retransmission", ssn);
4654 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4655 " != %" PRIu32
" from stream",
4661 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4662 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4667 if (!retransmission) {
4672 StreamTcpHandleTimestamp(ssn, p);
4686 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4690 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4691 "%" PRIu32
", ACK %" PRIu32
"",
4693 int retransmission = 0;
4694 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4695 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4701 SCLogDebug(
"ssn %p: -> retransmission", ssn);
4706 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4707 " != %" PRIu32
" from stream",
4713 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4714 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4719 if (!retransmission) {
4724 StreamTcpHandleTimestamp(ssn, p);
4738 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4759 static int StreamTcpPacketStateLastAck(
4763 const TCPHdr *tcph = PacketGetTCP(p);
4769 if (!StreamTcpValidateRst(ssn, p))
4772 StreamTcpCloseSsnWithReset(p, ssn);
4777 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, ack));
4782 StreamTcpHandleTimestamp(ssn, p);
4789 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
4794 StreamTcpHandleTimestamp(ssn, p);
4802 SCLogDebug(
"ssn (%p): FIN pkt on LastAck", ssn);
4805 SCLogDebug(
"ssn (%p): SYN pkt on LastAck", ssn);
4811 if (!StreamTcpValidateTimestamp(ssn, p))
4816 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4817 "%" PRIu32
", ACK %" PRIu32
"",
4820 int retransmission = 0;
4821 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4822 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4827 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4828 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4833 if (!retransmission) {
4835 SCLogDebug(
"ssn %p: not updating state as packet is before next_seq", ssn);
4837 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4838 " != %" PRIu32
" from stream",
4844 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
4850 StreamTcpHandleTimestamp(ssn, p);
4861 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4882 static int StreamTcpPacketStateTimeWait(
4886 const TCPHdr *tcph = PacketGetTCP(p);
4892 if (!StreamTcpValidateRst(ssn, p))
4895 StreamTcpCloseSsnWithReset(p, ssn);
4900 ssn, &ssn->
server, StreamTcpResetGetMaxAck(&ssn->
server, ack));
4905 StreamTcpHandleTimestamp(ssn, p);
4912 ssn, &ssn->
client, StreamTcpResetGetMaxAck(&ssn->
client, ack));
4917 StreamTcpHandleTimestamp(ssn, p);
4927 SCLogDebug(
"ssn (%p): SYN pkt on TimeWait", ssn);
4933 if (!StreamTcpValidateTimestamp(ssn, p))
4938 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4939 "%" PRIu32
", ACK %" PRIu32
"",
4941 int retransmission = 0;
4942 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4943 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4948 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4949 " != %" PRIu32
" from stream",
4955 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4956 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4961 if (!retransmission) {
4963 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
4969 StreamTcpHandleTimestamp(ssn, p);
4980 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4984 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4985 "%" PRIu32
", ACK %" PRIu32
"",
4987 int retransmission = 0;
4988 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4989 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4994 SCLogDebug(
"ssn %p: -> retransmission", ssn);
4997 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4998 " != %" PRIu32
" from stream",
5005 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
5006 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5011 if (!retransmission) {
5013 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5019 StreamTcpHandleTimestamp(ssn, p);
5030 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5042 static int StreamTcpPacketStateClosed(
5047 const TCPHdr *tcph = PacketGetTCP(p);
5053 TcpStream *stream = NULL, *ostream = NULL;
5070 if (StreamTcpStateDispatch(
tv, p, stt, ssn, ssn->
pstate) < 0)
5085 const TCPHdr *tcph = PacketGetTCP(p);
5099 SCLogDebug(
"regular packet %"PRIu64
" from same sender as "
5100 "the previous RST. Looks like it injected!", p->
pcap_cnt);
5127 const TCPHdr *tcph = PacketGetTCP(p);
5132 TcpStream *stream = NULL, *ostream = NULL;
5143 if (ack == ostream->last_ack &&
seq == (stream->
next_seq - 1)) {
5159 TcpStream *stream = NULL, *ostream = NULL;
5170 const TCPHdr *tcph = PacketGetTCP(p);
5189 if (pkt_win != ostream->window)
5198 SCLogDebug(
"seq %u (%u), ack %u (%u) FLAG_KEEPALIVE: %s",
seq, stream->
next_seq, ack, ostream->last_ack,
5228 TcpStream *stream = NULL, *ostream = NULL;
5242 const TCPHdr *tcph = PacketGetTCP(p);
5261 if (pkt_win == ostream->window)
5264 if (ack == ostream->last_ack &&
seq == stream->
next_seq) {
5279 TcpStream *stream = NULL, *ostream = NULL;
5287 const TCPHdr *tcph = PacketGetTCP(p);
5304 SCLogDebug(
"%"PRIu64
", seq %u ack %u stream->next_seq %u ostream->next_seq %u",
5332 TcpStream *stream = NULL, *ostream = NULL;
5343 const TCPHdr *tcph = PacketGetTCP(p);
5359 if (pkt_win < ostream->window) {
5360 uint32_t diff = ostream->window - pkt_win;
5362 SEQ_GT(ack, ostream->next_seq) &&
5365 SCLogDebug(
"%"PRIu64
", pkt_win %u, stream win %u, diff %u, dsize %u",
5367 SCLogDebug(
"%"PRIu64
", pkt_win %u, stream win %u",
5368 p->
pcap_cnt, pkt_win, ostream->window);
5369 SCLogDebug(
"%"PRIu64
", seq %u ack %u ostream->next_seq %u ostream->last_ack %u, ostream->next_win %u, diff %u (%u)",
5370 p->
pcap_cnt,
seq, ack, ostream->next_seq, ostream->last_ack, ostream->next_win,
5371 ostream->next_seq - ostream->last_ack, stream->
next_seq - stream->
last_ack);
5378 uint32_t adiff = ack - ostream->last_ack;
5379 if (((pkt_win > 1024) && (diff > (adiff + 32))) ||
5380 ((pkt_win <= 1024) && (diff > adiff)))
5382 SCLogDebug(
"pkt ACK %u is %u bytes beyond last_ack %u, shrinks window by %u "
5383 "(allowing 32 bytes extra): pkt WIN %u", ack, adiff, ostream->last_ack, diff, pkt_win);
5384 SCLogDebug(
"%u - %u = %u (state %u)", diff, adiff, diff - adiff, ssn->
state);
5399 static inline int StreamTcpStateDispatch(
5407 SCLogDebug(
"packet received on TCP_SYN_SENT state");
5408 if (StreamTcpPacketStateSynSent(
tv, p, stt, ssn)) {
5413 SCLogDebug(
"packet received on TCP_SYN_RECV state");
5414 if (StreamTcpPacketStateSynRecv(
tv, p, stt, ssn)) {
5419 SCLogDebug(
"packet received on TCP_ESTABLISHED state");
5420 if (StreamTcpPacketStateEstablished(
tv, p, stt, ssn)) {
5425 SCLogDebug(
"packet received on TCP_FIN_WAIT1 state");
5426 if (StreamTcpPacketStateFinWait1(
tv, p, stt, ssn)) {
5431 SCLogDebug(
"packet received on TCP_FIN_WAIT2 state");
5432 if (StreamTcpPacketStateFinWait2(
tv, p, stt, ssn)) {
5437 SCLogDebug(
"packet received on TCP_CLOSING state");
5438 if (StreamTcpPacketStateClosing(
tv, p, stt, ssn)) {
5443 SCLogDebug(
"packet received on TCP_CLOSE_WAIT state");
5444 if (StreamTcpPacketStateCloseWait(
tv, p, stt, ssn)) {
5449 SCLogDebug(
"packet received on TCP_LAST_ACK state");
5450 if (StreamTcpPacketStateLastAck(
tv, p, stt, ssn)) {
5455 SCLogDebug(
"packet received on TCP_TIME_WAIT state");
5456 if (StreamTcpPacketStateTimeWait(
tv, p, stt, ssn)) {
5462 SCLogDebug(
"packet received on closed state");
5464 if (StreamTcpPacketStateClosed(
tv, p, stt, ssn)) {
5470 SCLogDebug(
"packet received on default state");
5506 const TCPHdr *tcph = PacketGetTCP(p);
5521 SCLogDebug(
"ssn %p: removing ASYNC flag as we have packets on both sides", ssn);
5535 if (StreamTcpCheckFlowDrops(p) == 1) {
5545 if (StreamTcpPacketStateNone(
tv, p, stt, ssn) == -1) {
5573 if (StreamTcpPacketIsKeepAlive(ssn, p) == 1) {
5576 if (StreamTcpPacketIsKeepAliveACK(ssn, p) == 1) {
5577 StreamTcpClearKeepAliveFlag(ssn, p);
5580 StreamTcpClearKeepAliveFlag(ssn, p);
5582 const bool is_zwp_ack = StreamTcpPacketIsZeroWindowProbeAck(ssn, p);
5593 if (StreamTcpPacketIsDupAck(ssn, p) ==
true) {
5600 if (StreamTcpPacketIsFinShutdownAck(ssn, p) == 0) {
5601 if (StreamTcpPacketIsWindowUpdate(ssn, p) == 0) {
5602 if (StreamTcpPacketIsBadWindowUpdate(ssn,p))
5604 if (StreamTcpPacketIsOutdatedAck(ssn, p))
5609 int ret = StreamTcpPacketIsSpuriousRetransmission(ssn, p);
5618 if (StreamTcpStateDispatch(
tv, p, stt, ssn, ssn->
state) < 0)
5622 StreamTcpPacketCheckPostRst(ssn, p);
5671 SCLogDebug(
"bypass as stream is dead and we have no rules");
5684 if (StreamTcpInlineDropInvalid()) {
5688 DecodeSetNoPayloadInspectionFlag(p);
5702 static inline int StreamTcpValidateChecksum(
Packet *p)
5710 const TCPHdr *tcph = PacketGetTCP(p);
5711 if (PacketIsIPv4(p)) {
5712 const IPV4Hdr *ip4h = PacketGetIPv4(p);
5713 p->
l4.
csum = TCPChecksum(ip4h->s_ip_addrs, (uint16_t *)tcph,
5716 }
else if (PacketIsIPv6(p)) {
5717 const IPV6Hdr *ip6h = PacketGetIPv6(p);
5718 p->
l4.
csum = TCPV6Checksum(ip6h->s_ip6_addrs, (uint16_t *)tcph,
5739 static int TcpSessionPacketIsStreamStarter(
const Packet *p)
5741 const TCPHdr *tcph = PacketGetTCP(p);
5766 const TCPHdr *tcph = PacketGetTCP(p);
5771 SCLogDebug(
"steam starter packet %" PRIu64
", ssn %p null. Reuse.", p->
pcap_cnt, ssn);
5776 ", ssn %p. STREAMTCP_FLAG_TFO_DATA_IGNORED set. Reuse.",
5781 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.", p->
pcap_cnt, ssn);
5785 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5788 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5791 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
5801 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5804 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5807 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
5820 static int TcpSessionReuseDoneEnoughSynAck(
const Packet *p,
const Flow *f,
const TcpSession *ssn)
5822 const TCPHdr *tcph = PacketGetTCP(p);
5825 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p null. No reuse.", p->
pcap_cnt, ssn);
5829 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.", p->
pcap_cnt, ssn);
5833 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5836 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5839 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
5849 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5852 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5855 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
5871 const TCPHdr *tcph = PacketGetTCP(p);
5873 return TcpSessionReuseDoneEnoughSyn(p, f, ssn);
5878 return TcpSessionReuseDoneEnoughSynAck(p, f, ssn);
5887 if (p->
proto == IPPROTO_TCP && PacketIsTCP(p)) {
5888 if (TcpSessionPacketIsStreamStarter(p) == 1) {
5889 if (TcpSessionReuseDoneEnough(p, f, tcp_ssn) == 1) {
5912 if (!(PacketIsTCP(p))) {
5916 HandleThreadId(
tv, p, stt);
5922 if (StreamTcpValidateChecksum(p) == 0) {
5948 *data = (
void *)stt;
5957 IsStreamTcpSessionMemcapExceptionPolicyStatsValid);
5966 "tcp.midstream_exception_policy.", IsMidstreamExceptionPolicyStatsValid);
5970 "tcp.midstream_exception_policy.", IsMidstreamExceptionPolicyStatsValid);
5985 "tcp.reassembly_exception_policy.", IsReassemblyMemcapExceptionPolicyStatsValid);
5998 SCLogDebug(
"StreamTcp thread specific ctx online at %p, reassembly ctx %p",
6007 StreamTcpSessionPoolAlloc,
6008 StreamTcpSessionPoolInit, NULL,
6009 StreamTcpSessionPoolCleanup, NULL);
6019 SCLogError(
"failed to setup/expand stream session pool. Expand stream.memcap?");
6064 const TCPHdr *tcph = PacketGetTCP(p);
6072 if (!StreamTcpValidateTimestamp(ssn, p)) {
6101 StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
6102 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
6114 StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
6115 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
6128 receiver_stream = &ssn->
server;
6130 receiver_stream = &ssn->
client;
6132 SCLogDebug(
"ssn %p: setting STREAMTCP_STREAM_FLAG_RST_RECV on receiver stream", ssn);
6152 switch (os_policy) {
6159 SCLogDebug(
"reset is not Valid! Packet SEQ: %" PRIu32
" "
6160 "and server SEQ: %" PRIu32
"",
6169 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" "
6170 "and client SEQ: %" PRIu32
"",
6187 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6188 " server SEQ: %" PRIu32
"",
6200 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6201 " client SEQ: %" PRIu32
"",
6222 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" "
6223 "and server SEQ: %" PRIu32
"",
6229 SCLogDebug(
"reset is valid! Packet SEQ: %" PRIu32
" Stream %u",
seq,
6233 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6234 " client SEQ: %" PRIu32
"",
6265 uint8_t check_ts = 1;
6266 const TCPHdr *tcph = PacketGetTCP(p);
6270 sender_stream = &ssn->
client;
6271 receiver_stream = &ssn->
server;
6273 sender_stream = &ssn->
server;
6274 receiver_stream = &ssn->
client;
6285 uint32_t last_pkt_ts = sender_stream->
last_pkt_ts;
6286 uint32_t last_ts = sender_stream->
last_ts;
6336 SCLogDebug(
"ts %"PRIu32
", last_ts %"PRIu32
"",
ts, last_ts);
6340 result = (int32_t) ((
ts - last_ts) + 1);
6342 result = (int32_t) (
ts - last_ts);
6345 SCLogDebug(
"result %" PRIi32
", p->ts(secs) %" PRIuMAX
"", result,
6348 if (last_pkt_ts == 0 &&
6356 "%" PRIu32
" p->tcpvars->ts %" PRIu32
" result "
6357 "%" PRId32
"", last_ts,
ts, result);
6360 }
else if ((sender_stream->
last_ts != 0) &&
6362 SCLogDebug(
"packet is not valid last_pkt_ts "
6363 "%" PRIu32
" p->ts(sec) %" PRIu32
"",
6375 SCLogDebug(
"timestamp considered valid anyway");
6407 uint8_t check_ts = 1;
6408 const TCPHdr *tcph = PacketGetTCP(p);
6412 sender_stream = &ssn->
client;
6413 receiver_stream = &ssn->
server;
6415 sender_stream = &ssn->
server;
6416 receiver_stream = &ssn->
client;
6484 result = (int32_t) ((
ts - sender_stream->
last_ts) + 1);
6486 result = (int32_t) (
ts - sender_stream->
last_ts);
6489 SCLogDebug(
"result %" PRIi32
", p->ts(sec) %" PRIuMAX
"", result,
6499 SCLogDebug(
"timestamp is not valid sender_stream->last_ts "
6500 "%" PRIu32
" p->tcpvars->ts %" PRIu32
" result "
6501 "%" PRId32
"", sender_stream->
last_ts,
ts, result);
6504 }
else if ((sender_stream->
last_ts != 0) &&
6507 SCLogDebug(
"packet is not valid sender_stream->last_pkt_ts "
6508 "%" PRIu32
" p->ts(sec) %" PRIu32
"",
6522 }
else if (ret == 0) {
6532 SCLogDebug(
"timestamp considered valid anyway");
6568 const TCPHdr *tcph = PacketGetTCP(p);
6583 SCLogDebug(
"ssn %p: pkt ACK %" PRIu32
" == stream last ACK %" PRIu32, ssn, ack,
6596 SCLogDebug(
"ACK %"PRIu32
" is before last_ack %"PRIu32
" - window "
6597 "%"PRIu32
" = %"PRIu32, ack, stream->
last_ack,
6620 SCLogDebug(
"default path leading to invalid: ACK %"PRIu32
", last_ack %"PRIu32
6633 const uint32_t progress)
6691 static void StreamTcpPseudoPacketCreateDetectLogFlush(
ThreadVars *
tv,
6714 np->
proto = IPPROTO_TCP;
6715 FlowReference(&np->
flow, f);
6725 DecodeSetNoPacketInspectionFlag(np);
6728 DecodeSetNoPayloadInspectionFlag(np);
6768 ip4h->
ip_len = htons(40);
6774 ip4h->s_ip_src.s_addr = f->
src.addr_data32[0];
6775 ip4h->s_ip_dst.s_addr = f->
dst.addr_data32[0];
6777 ip4h->s_ip_src.s_addr = f->
dst.addr_data32[0];
6778 ip4h->s_ip_dst.s_addr = f->
src.addr_data32[0];
6811 ip6h->s_ip6_vfc = 0x60;
6812 ip6h->s_ip6_flow = 0;
6813 ip6h->s_ip6_nxt = IPPROTO_TCP;
6814 ip6h->s_ip6_plen = htons(20);
6815 ip6h->s_ip6_hlim = 64;
6817 ip6h->s_ip6_src[0] = f->
src.addr_data32[0];
6818 ip6h->s_ip6_src[1] = f->
src.addr_data32[1];
6819 ip6h->s_ip6_src[2] = f->
src.addr_data32[2];
6820 ip6h->s_ip6_src[3] = f->
src.addr_data32[3];
6821 ip6h->s_ip6_dst[0] = f->
dst.addr_data32[0];
6822 ip6h->s_ip6_dst[1] = f->
dst.addr_data32[1];
6823 ip6h->s_ip6_dst[2] = f->
dst.addr_data32[2];
6824 ip6h->s_ip6_dst[3] = f->
dst.addr_data32[3];
6826 ip6h->s_ip6_src[0] = f->
dst.addr_data32[0];
6827 ip6h->s_ip6_src[1] = f->
dst.addr_data32[1];
6828 ip6h->s_ip6_src[2] = f->
dst.addr_data32[2];
6829 ip6h->s_ip6_src[3] = f->
dst.addr_data32[3];
6830 ip6h->s_ip6_dst[0] = f->
src.addr_data32[0];
6831 ip6h->s_ip6_dst[1] = f->
src.addr_data32[1];
6832 ip6h->s_ip6_dst[2] = f->
src.addr_data32[2];
6833 ip6h->s_ip6_dst[3] = f->
src.addr_data32[3];
6865 np->
ts = parent->
ts;
6873 FlowDeReference(&np->
flow);
6892 StreamTcpPseudoPacketCreateDetectLogFlush(
tv, stt, p, ssn, pq,
ts^0);
6893 StreamTcpPseudoPacketCreateDetectLogFlush(
tv, stt, p, ssn, pq,
ts^1);
6913 if (p->
flow == NULL)
6941 const uint8_t *seg_data;
6942 uint32_t seg_datalen;
6945 int ret = CallbackFunc(p, seg, data, seg_data, seg_datalen);
6973 if (p->
flow == NULL)
6987 if (server_node == NULL && client_node == NULL) {
6991 while (server_node != NULL || client_node != NULL) {
6992 const uint8_t *seg_data;
6993 uint32_t seg_datalen;
6994 if (server_node == NULL) {
7001 &client_stream->
sb, &client_node->
sbseg, &seg_data, &seg_datalen);
7002 ret = CallbackFunc(p, client_node, data, seg_data, seg_datalen);
7007 client_node = TCPSEG_RB_NEXT(client_node);
7008 }
else if (client_node == NULL) {
7015 &server_stream->
sb, &server_node->
sbseg, &seg_data, &seg_datalen);
7016 ret = CallbackFunc(p, server_node, data, seg_data, seg_datalen);
7021 server_node = TCPSEG_RB_NEXT(server_node);
7026 &client_stream->
sb, &client_node->
sbseg, &seg_data, &seg_datalen);
7027 ret = CallbackFunc(p, client_node, data, seg_data, seg_datalen);
7032 client_node = TCPSEG_RB_NEXT(client_node);
7035 &server_stream->
sb, &server_node->
sbseg, &seg_data, &seg_datalen);
7036 ret = CallbackFunc(p, server_node, data, seg_data, seg_datalen);
7041 server_node = TCPSEG_RB_NEXT(server_node);
7078 const char *tcp_state = NULL;
7084 tcp_state =
"syn_sent";
7087 tcp_state =
"syn_recv";
7090 tcp_state =
"established";
7093 tcp_state =
"fin_wait1";
7096 tcp_state =
"fin_wait2";
7099 tcp_state =
"time_wait";
7102 tcp_state =
"last_ack";
7105 tcp_state =
"close_wait";
7108 tcp_state =
"closing";
7111 tcp_state =
"closed";