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
107 .valid_settings_ips = {
135 .valid_settings_ips = {
163 .valid_settings_ips = {
191 .valid_settings_ips = {
215 static int StreamTcpStateDispatch(
224 static uint64_t ssn_pool_cnt = 0;
244 #if defined(DEBUG_VALIDATION) && defined(UNITTESTS)
247 BUG_ON(presize > UINT_MAX);
253 #if defined(DEBUG_VALIDATION) && defined(UNITTESTS)
256 BUG_ON(postsize > presize);
277 if (memcapcopy == 0 || size +
SC_ATOMIC_GET(st_memuse) <= memcapcopy)
289 if (size == 0 || (uint64_t)
SC_ATOMIC_GET(st_memuse) < size) {
310 if (stream != NULL) {
317 static void StreamTcp3wsFreeQueue(
TcpSession *ssn)
344 StreamTcp3wsFreeQueue(ssn);
405 static void *StreamTcpSessionPoolAlloc(
void)
419 static int StreamTcpSessionPoolInit(
void *data,
void* initdata)
429 static void StreamTcpSessionPoolCleanup(
void *s)
443 static inline bool StreamTcpInlineDropInvalid(
void)
454 static inline bool StreamTcpInlineDropUrg(
void)
463 static int RandomGetWrap(
void)
469 }
while(r >= ULONG_MAX - (ULONG_MAX % RAND_MAX));
499 uint16_t rdrange = 10;
508 if ((
SCConfGetInt(
"stream.max-sessions", &value)) == 1) {
510 "Number of concurrent sessions is now only limited by Flow and "
511 "TCP stream engine memcaps.");
514 if ((
SCConfGetInt(
"stream.prealloc-sessions", &value)) == 1) {
529 SCLogConfig(
"stream \"prealloc-sessions\": %"PRIu32
" (per thread)",
533 const char *temp_stream_memcap_str;
534 if (
SCConfGet(
"stream.memcap", &temp_stream_memcap_str) == 1) {
535 uint64_t stream_memcap_copy;
538 "from conf file - %s. Killing engine",
539 temp_stream_memcap_str);
570 if ((
SCConfGetBool(
"stream.checksum-validation", &csum)) == 1) {
582 "enabled" :
"disabled");
585 const char *temp_stream_inline_str;
586 if (
SCConfGet(
"stream.inline", &temp_stream_inline_str) == 1) {
591 if (strcmp(temp_stream_inline_str,
"auto") == 0) {
614 ?
"enabled" :
"disabled");
627 ?
"enabled" :
"disabled");
630 int drop_invalid = 0;
631 if ((
SCConfGetBool(
"stream.drop-invalid", &drop_invalid)) == 1) {
632 if (drop_invalid == 1) {
639 const char *temp_urgpol = NULL;
640 if (
SCConfGet(
"stream.reassembly.urgent.policy", &temp_urgpol) == 1 && temp_urgpol != NULL) {
641 if (strcmp(temp_urgpol,
"inline") == 0) {
643 }
else if (strcmp(temp_urgpol,
"drop") == 0) {
645 }
else if (strcmp(temp_urgpol,
"oob") == 0) {
647 }
else if (strcmp(temp_urgpol,
"gap") == 0) {
650 FatalError(
"stream.reassembly.urgent.policy: invalid value '%s'", temp_urgpol);
659 const char *temp_urgoobpol = NULL;
660 if (
SCConfGet(
"stream.reassembly.urgent.oob-limit-policy", &temp_urgoobpol) == 1 &&
661 temp_urgoobpol != NULL) {
662 if (strcmp(temp_urgoobpol,
"inline") == 0) {
664 }
else if (strcmp(temp_urgoobpol,
"drop") == 0) {
666 }
else if (strcmp(temp_urgoobpol,
"gap") == 0) {
669 FatalError(
"stream.reassembly.urgent.oob-limit-policy: invalid value '%s'", temp_urgoobpol);
679 if ((
SCConfGetInt(
"stream.max-syn-queued", &value)) == 1) {
680 if (value >= 0 && value <= 255) {
692 if ((
SCConfGetInt(
"stream.max-synack-queued", &value)) == 1) {
693 if (value >= 0 && value <= 255) {
705 const char *temp_stream_reassembly_memcap_str;
706 if (
SCConfGet(
"stream.reassembly.memcap", &temp_stream_reassembly_memcap_str) == 1) {
707 uint64_t stream_reassembly_memcap_copy;
709 &stream_reassembly_memcap_copy) < 0) {
711 "stream.reassembly.memcap "
712 "from conf file - %s. Killing engine",
713 temp_stream_reassembly_memcap_str);
723 SCLogConfig(
"stream.reassembly \"memcap\": %"PRIu64
"",
727 const char *temp_stream_reassembly_depth_str;
728 if (
SCConfGet(
"stream.reassembly.depth", &temp_stream_reassembly_depth_str) == 1) {
732 "stream.reassembly.depth "
733 "from conf file - %s. Killing engine",
734 temp_stream_reassembly_depth_str);
746 if ((
SCConfGetBool(
"stream.reassembly.randomize-chunk-size", &randomize)) == 0) {
754 const char *temp_rdrange;
755 if (
SCConfGet(
"stream.reassembly.randomize-chunk-range", &temp_rdrange) == 1) {
758 "stream.reassembly.randomize-chunk-range "
759 "from conf file - %s. Killing engine",
762 }
else if (rdrange >= 100) {
763 FatalError(
"stream.reassembly.randomize-chunk-range "
764 "must be lower than 100");
769 const char *temp_stream_reassembly_toserver_chunk_size_str;
770 if (
SCConfGet(
"stream.reassembly.toserver-chunk-size",
771 &temp_stream_reassembly_toserver_chunk_size_str) == 1) {
775 "stream.reassembly.toserver-chunk-size "
776 "from conf file - %s. Killing engine",
777 temp_stream_reassembly_toserver_chunk_size_str);
786 long int r = RandomGetWrap();
791 const char *temp_stream_reassembly_toclient_chunk_size_str;
792 if (
SCConfGet(
"stream.reassembly.toclient-chunk-size",
793 &temp_stream_reassembly_toclient_chunk_size_str) == 1) {
797 "stream.reassembly.toclient-chunk-size "
798 "from conf file - %s. Killing engine",
799 temp_stream_reassembly_toclient_chunk_size_str);
808 long int r = RandomGetWrap();
814 SCLogConfig(
"stream.reassembly \"toserver-chunk-size\": %"PRIu16,
816 SCLogConfig(
"stream.reassembly \"toclient-chunk-size\": %"PRIu16,
821 if (
SCConfGetBool(
"stream.reassembly.raw", &enable_raw) == 1) {
829 SCLogConfig(
"stream.reassembly.raw: %s", enable_raw ?
"enabled" :
"disabled");
833 int liberal_timestamps = 0;
834 if (
SCConfGetBool(
"stream.liberal-timestamps", &liberal_timestamps) == 1) {
838 SCLogConfig(
"stream.liberal-timestamps: %s", liberal_timestamps ?
"enabled" :
"disabled");
858 StreamTcpSessionPoolAlloc,
859 StreamTcpSessionPoolInit, NULL,
860 StreamTcpSessionPoolCleanup, NULL);
879 SCLogDebug(
"ssn_pool_cnt %"PRIu64
"", ssn_pool_cnt);
882 static bool IsReassemblyMemcapExceptionPolicyStatsValid(
enum ExceptionPolicy exception_policy)
890 static bool IsStreamTcpSessionMemcapExceptionPolicyStatsValid(
enum ExceptionPolicy policy)
898 static void StreamTcpSsnMemcapExceptionPolicyStatsIncr(
957 if (
unlikely((g_eps_stream_ssn_memcap != UINT64_MAX &&
958 g_eps_stream_ssn_memcap ==
t_pcapcnt))) {
973 const TCPHdr *tcph = PacketGetTCP(p);
1007 switch(ssn->
state) {
1032 if (PacketIsIPv4(p)) {
1042 }
else if (PacketIsIPv6(p)) {
1068 #define StreamTcpUpdateLastAck(ssn, stream, ack) \
1070 if (SEQ_GT((ack), (stream)->last_ack) && SEQ_GT(ack, (stream)->base_seq)) { \
1071 SCLogDebug("ssn %p: last_ack set to %" PRIu32 ", moved %u forward", (ssn), (ack), \
1072 (ack) - (stream)->last_ack); \
1073 if ((SEQ_LEQ((stream)->last_ack, (stream)->next_seq) && \
1074 SEQ_GT((ack), (stream)->next_seq))) { \
1075 SCLogDebug("last_ack just passed next_seq: %u (was %u) > %u", (ack), \
1076 (stream)->last_ack, (stream)->next_seq); \
1078 SCLogDebug("next_seq (%u) <> last_ack now %d", (stream)->next_seq, \
1079 (int)(stream)->next_seq - (ack)); \
1081 (stream)->last_ack = (ack); \
1082 StreamTcpSackPruneList((stream)); \
1084 SCLogDebug("ssn %p: no update: ack %u, last_ack %" PRIu32 ", next_seq %u (state %u)", \
1085 (ssn), (ack), (stream)->last_ack, (stream)->next_seq, (ssn)->state); \
1089 #define StreamTcpAsyncLastAckUpdate(ssn, stream) { \
1090 if ((ssn)->flags & STREAMTCP_FLAG_ASYNC) { \
1091 if (SEQ_GT((stream)->next_seq, (stream)->last_ack)) { \
1092 uint32_t ack_diff = (stream)->next_seq - (stream)->last_ack; \
1093 (stream)->last_ack += ack_diff; \
1094 SCLogDebug("ssn %p: ASYNC last_ack set to %"PRIu32", moved %u forward", \
1095 (ssn), (stream)->next_seq, ack_diff); \
1100 #define StreamTcpUpdateNextSeq(ssn, stream, seq) { \
1101 (stream)->next_seq = seq; \
1102 SCLogDebug("ssn %p: next_seq %" PRIu32, (ssn), (stream)->next_seq); \
1103 StreamTcpAsyncLastAckUpdate((ssn), (stream)); \
1113 #define StreamTcpUpdateNextWin(ssn, stream, win) { \
1114 uint32_t sacked_size__ = StreamTcpSackedSize((stream)); \
1115 if (SEQ_GT(((win) + sacked_size__), (stream)->next_win)) { \
1116 (stream)->next_win = ((win) + sacked_size__); \
1117 SCLogDebug("ssn %p: next_win set to %"PRIu32, (ssn), (stream)->next_win); \
1125 SCLogDebug(
"ssn %p: (state: %s) Reset received and state changed to "
1129 static bool IsMidstreamExceptionPolicyStatsValid(
enum ExceptionPolicy policy)
1143 static void StreamTcpMidstreamExceptionPolicyStatsIncr(
1152 static int StreamTcpPacketIsRetransmission(
TcpStream *stream,
Packet *p)
1157 const TCPHdr *tcph = PacketGetTCP(p);
1195 static int StreamTcpPacketStateNone(
1198 const TCPHdr *tcph = PacketGetTCP(p);
1201 SCLogDebug(
"RST packet received, no session setup");
1211 SCLogDebug(
"FIN packet received, no session setup");
1217 SCLogDebug(
"FIN packet received, no session setup");
1234 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1266 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
", "
1267 "ssn->server.next_win %" PRIu32
"",
1269 SCLogDebug(
"ssn %p: ssn->client.last_ack %" PRIu32
", "
1270 "ssn->server.last_ack %" PRIu32
"",
1278 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1279 "ssn->client.last_ts %" PRIu32
"",
1298 SCLogDebug(
"ssn %p: assuming SACK permitted for both sides", ssn);
1307 SCLogDebug(
"Midstream not enabled, so won't pick up a session");
1312 SCLogDebug(
"Midstream policy not permissive, so won't pick up a session");
1335 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1336 "TCP_SYN_RECV", ssn);
1367 SCLogDebug(
"ssn %p: wscale enabled. client %u server %u",
1371 SCLogDebug(
"ssn %p: ssn->client.isn %"PRIu32
", ssn->client.next_seq"
1372 " %"PRIu32
", ssn->client.last_ack %"PRIu32
"", ssn,
1375 SCLogDebug(
"ssn %p: ssn->server.isn %"PRIu32
", ssn->server.next_seq"
1376 " %"PRIu32
", ssn->server.last_ack %"PRIu32
"", ssn,
1385 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1386 "ssn->client.last_ts %" PRIu32
"", ssn,
1404 SCLogDebug(
"ssn %p: SYN/ACK with SACK permitted, assuming "
1405 "SACK permitted for both sides", ssn);
1423 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_SYN_SENT", ssn);
1456 SCLogDebug(
"ssn %p: SACK permitted on SYN packet", ssn);
1463 SCLogDebug(
"ssn: %p (TFO) isn %u base_seq %u next_seq %u payload len %u", ssn,
1470 SCLogDebug(
"ssn %p: ssn->client.isn %" PRIu32
", "
1471 "ssn->client.next_seq %" PRIu32
", ssn->client.last_ack "
1481 SCLogDebug(
"Midstream not enabled, so won't pick up a session");
1486 SCLogDebug(
"Midstream policy not permissive, so won't pick up a session");
1503 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1504 "TCP_ESTABLISHED", ssn);
1525 SCLogDebug(
"ssn %p: ssn->client.isn %u, ssn->client.next_seq %u",
1534 SCLogDebug(
"ssn %p: ssn->client.next_win %"PRIu32
", "
1535 "ssn->server.next_win %"PRIu32
"", ssn,
1537 SCLogDebug(
"ssn %p: ssn->client.last_ack %"PRIu32
", "
1538 "ssn->server.last_ack %"PRIu32
"", ssn,
1546 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1547 "ssn->client.last_ts %" PRIu32
"", ssn,
1566 SCLogDebug(
"ssn %p: assuming SACK permitted for both sides", ssn);
1580 const TCPHdr *tcph = PacketGetTCP(p);
1610 StreamTcp3whsSynAckToStateQueue(p, &search);
1618 search.
ts == q->
ts) {
1631 if (StreamTcp3whsFindSynAckBySynAck(ssn, p) != NULL)
1635 SCLogDebug(
"ssn %p: =~ SYN/ACK queue limit reached", ssn);
1641 SCLogDebug(
"ssn %p: =~ SYN/ACK queue failed: stream memcap reached", ssn);
1647 SCLogDebug(
"ssn %p: =~ SYN/ACK queue failed: alloc failed", ssn);
1652 StreamTcp3whsSynAckToStateQueue(p, q);
1666 const TCPHdr *tcph = PacketGetTCP(p);
1701 StreamTcp3whsSynAckToStateQueue(p, &update);
1708 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_SYN_RECV", ssn);
1724 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1725 "ssn->client.last_ts %" PRIu32
"", ssn,
1753 SCLogDebug(
"ssn %p: SACK permitted for session", ssn);
1760 SCLogDebug(
"ssn %p: ssn->server.next_win %" PRIu32
"", ssn,
1762 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
"", ssn,
1764 SCLogDebug(
"ssn %p: ssn->server.isn %" PRIu32
", "
1765 "ssn->server.next_seq %" PRIu32
", "
1766 "ssn->server.last_ack %" PRIu32
" "
1767 "(ssn->client.last_ack %" PRIu32
")", ssn,
1774 SCLogDebug(
"ssn %p: STREAMTCP_FLAG_4WHS unset, normal SYN/ACK"
1775 " so considering 3WHS", ssn);
1786 static inline bool StateSynSentValidateTimestamp(
TcpSession *ssn,
Packet *p)
1796 if (receiver_stream->
last_ts != 0 && ts_echo != 0 &&
1797 ts_echo != receiver_stream->
last_ts)
1799 SCLogDebug(
"%" PRIu64
": ssn %p: BAD TSECR echo %u recv %u", p->
pcap_cnt, ssn, ts_echo,
1804 if (receiver_stream->
last_ts == 0 && ts_echo != 0) {
1805 SCLogDebug(
"%" PRIu64
": ssn %p: BAD TSECR echo %u recv %u", p->
pcap_cnt, ssn, ts_echo,
1816 memset(q, 0,
sizeof(*q));
1837 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1843 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1847 memset(q, 0,
sizeof(*q));
1848 const TCPHdr *tcph = PacketGetTCP(p);
1867 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1874 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1878 memset(q, 0,
sizeof(*q));
1880 const TCPHdr *tcph = PacketGetTCP(p);
1898 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1914 SCLogDebug(
"ssn %p: search state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, s, s->
seq, s->
win,
1919 SCLogDebug(
"ssn %p: queue state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u (last:%s)", ssn, q,
1927 }
else if (ignore_ts) {
1947 ssn->
queue = new_head;
1950 tail->next = old_head;
1952 *old_head = *search;
1953 old_head->
next = NULL;
1959 TcpStateQueueInitFromSsnSyn(ssn, &search);
1963 if (ssn->
queue != NULL && StreamTcp3whsFindSyn(ssn, &search, &
tail,
false) != NULL)
1968 SCLogDebug(
"%" PRIu64
": ssn %p: =~ SYN queue limit reached, rotate", p->
pcap_cnt, ssn);
1972 AddAndRotate(ssn,
tail, &search);
1977 SCLogDebug(
"ssn %p: =~ SYN queue failed: stream memcap reached", ssn);
1983 SCLogDebug(
"ssn %p: =~ SYN queue failed: alloc failed", ssn);
1997 SCLogDebug(
"%" PRIu64
": ssn %p: =~ SYN with SEQ %u added (queue_len %u)", p->
pcap_cnt, ssn,
2037 static inline bool StateSynSentCheckSynAck3Whs(
TcpSession *ssn,
Packet *p,
const bool ts_mismatch)
2039 const TCPHdr *tcph = PacketGetTCP(p);
2041 if (seq_match && !ts_mismatch) {
2046 if (ssn->
queue == NULL) {
2051 TcpStateQueueInitFromPktSynAck(p, &search);
2061 SCLogDebug(
"ssn %p: found queued SYN state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q,
2063 StreamTcp3whsStoreSynApplyToSsn(ssn, q);
2068 }
else if (ts_mismatch) {
2082 static inline bool StateSynSentCheckSynAckTFO(
TcpSession *ssn,
Packet *p,
const bool ts_mismatch)
2084 const TCPHdr *tcph = PacketGetTCP(p);
2087 if (seq_match_tfo && !ts_mismatch) {
2089 }
else if (seq_match_nodata && !ts_mismatch) {
2096 if (ssn->
queue == NULL) {
2101 TcpStateQueueInitFromPktSynAck(p, &search);
2111 SCLogDebug(
"ssn %p: found queued SYN state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q,
2113 StreamTcp3whsStoreSynApplyToSsn(ssn, q);
2118 if (!seq_match_tfo && !seq_match_nodata) {
2120 }
else if (ts_mismatch) {
2136 static int StreamTcpPacketStateSynSent(
2140 const TCPHdr *tcph = PacketGetTCP(p);
2146 SCLogDebug(
"%" PRIu64
": ssn %p: SYN/ACK on SYN_SENT state for packet %" PRIu64,
2150 const bool ts_mismatch =
2155 if (StateSynSentCheckSynAck3Whs(ssn, p, ts_mismatch)) {
2156 SCLogDebug(
"ssn %p: ACK match, packet ACK %" PRIu32
" == "
2157 "%" PRIu32
" from stream",
2160 SCLogDebug(
"ssn %p: (3WHS) ACK mismatch, packet ACK %" PRIu32
" != "
2161 "%" PRIu32
" from stream",
2166 if (StateSynSentCheckSynAckTFO(ssn, p, ts_mismatch)) {
2167 SCLogDebug(
"ssn %p: (TFO) ACK matches next_seq, packet ACK %" PRIu32
" == "
2168 "%" PRIu32
" from stream",
2171 SCLogDebug(
"ssn %p: (TFO) ACK mismatch, packet ACK %" PRIu32
" != "
2172 "%" PRIu32
" from stream",
2178 StreamTcp3wsFreeQueue(ssn);
2180 StreamTcp3whsSynAckUpdate(ssn, p, NULL);
2181 SCLogDebug(
"%" PRIu64
": ssn %p: SYN/ACK on SYN_SENT state: accepted", p->
pcap_cnt, ssn);
2188 SCLogDebug(
"ssn %p: SYN/ACK received in the wrong direction", ssn);
2192 SCLogDebug(
"ssn %p: SYN/ACK received on 4WHS session", ssn);
2199 SCLogDebug(
"ssn %p: 4WHS ACK mismatch, packet ACK %" PRIu32
""
2200 " != %" PRIu32
" from stream",
2210 SCLogDebug(
"ssn %p: 4WHS SEQ mismatch, packet SEQ %" PRIu32
""
2211 " != %" PRIu32
" from *first* SYN pkt",
2218 SCLogDebug(
"ssn %p: =~ 4WHS ssn state is now TCP_SYN_RECV", ssn);
2232 SCLogDebug(
"ssn %p: 4WHS ssn->client.last_ts %" PRIu32
" "
2233 "ssn->server.last_ts %" PRIu32
"",
2258 SCLogDebug(
"ssn %p: SACK permitted for 4WHS session", ssn);
2265 SCLogDebug(
"ssn %p: 4WHS ssn->client.isn %" PRIu32
", "
2266 "ssn->client.next_seq %" PRIu32
", "
2267 "ssn->client.last_ack %" PRIu32
" "
2268 "(ssn->server.last_ack %" PRIu32
")",
2277 if (!StateSynSentValidateTimestamp(ssn, p)) {
2285 if (!StreamTcpValidateRst(ssn, p))
2292 SCLogDebug(
"ssn->server.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2294 StreamTcpCloseSsnWithReset(p, ssn);
2295 StreamTcp3wsFreeQueue(ssn);
2299 SCLogDebug(
"ssn->client.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2300 StreamTcpCloseSsnWithReset(p, ssn);
2301 StreamTcp3wsFreeQueue(ssn);
2309 SCLogDebug(
"ssn %p: SYN packet on state SYN_SENT... resent", ssn);
2311 SCLogDebug(
"ssn %p: SYN packet on state SYN_SENT... resent of "
2324 SCLogDebug(
"ssn %p: STREAMTCP_FLAG_4WHS flag set", ssn);
2361 SCLogDebug(
"ssn %p: 4WHS ssn->server.isn %" PRIu32
", "
2362 "ssn->server.next_seq %" PRIu32
", "
2363 "ssn->server.last_ack %"PRIu32
"", ssn,
2366 SCLogDebug(
"ssn %p: 4WHS ssn->client.isn %" PRIu32
", "
2367 "ssn->client.next_seq %" PRIu32
", "
2368 "ssn->client.last_ack %"PRIu32
"", ssn,
2377 TcpStateQueueInitFromPktSyn(p, &syn_pkt);
2378 TcpStateQueueInitFromSsnSyn(ssn, &syn_ssn);
2380 if (memcmp(&syn_pkt, &syn_ssn,
sizeof(
TcpStateQueue)) != 0) {
2382 StreamTcp3whsStoreSyn(ssn, p);
2383 SCLogDebug(
"ssn %p: Retransmitted SYN. Updating ssn from packet %" PRIu64
2384 ". Stored previous state",
2387 StreamTcp3whsStoreSynApplyToSsn(ssn, &syn_pkt);
2403 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
2404 "%" PRIu32
" from stream",
2411 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2412 StreamTcp3wsFreeQueue(ssn);
2425 SCLogDebug(
"ssn %p: synsent => Asynchronous stream, packet SEQ"
2426 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2427 "ssn->client.next_seq %" PRIu32
"",
2476 static int StreamTcpPacketStateSynRecv(
2480 const TCPHdr *tcph = PacketGetTCP(p);
2483 if (!StreamTcpValidateRst(ssn, p))
2500 SCLogDebug(
"Detection evasion has been attempted, so"
2501 " not resetting the connection !!");
2509 SCLogDebug(
"Detection evasion has been attempted, so"
2510 " not resetting the connection !!");
2516 StreamTcpCloseSsnWithReset(p, ssn);
2519 StreamTcpHandleTimestamp(ssn, p);
2526 if (!StreamTcpValidateTimestamp(ssn, p))
2530 if ((StreamTcpHandleFin(
tv, stt, ssn, p)) == -1)
2535 SCLogDebug(
"ssn %p: SYN/ACK packet on state SYN_RECV. resent", ssn);
2538 SCLogDebug(
"ssn %p: SYN/ACK-pkt to server in SYN_RECV state", ssn);
2547 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
2548 "%" PRIu32
" from stream",
2558 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
2559 "%" PRIu32
" from stream",
2562 if (StreamTcp3whsQueueSynAck(ssn, p) == -1)
2564 SCLogDebug(
"ssn %p: queued different SYN/ACK", ssn);
2568 SCLogDebug(
"ssn %p: SYN packet on state SYN_RECV... resent", ssn);
2571 SCLogDebug(
"ssn %p: SYN-pkt to client in SYN_RECV state", ssn);
2578 SCLogDebug(
"ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
2586 SCLogDebug(
"ssn %p: checking ACK against queued SYN/ACKs", ssn);
2589 SCLogDebug(
"ssn %p: here we update state against queued SYN/ACK", ssn);
2590 StreamTcp3whsSynAckUpdate(ssn, p, q);
2592 SCLogDebug(
"ssn %p: none found, now checking ACK against original SYN/ACK (state)", ssn);
2602 if (!(StreamTcpValidateTimestamp(ssn, p))) {
2608 SCLogDebug(
"ssn %p: ACK received on 4WHS session",ssn);
2611 SCLogDebug(
"ssn %p: 4WHS wrong seq nr on packet", ssn);
2616 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
2617 SCLogDebug(
"ssn %p: 4WHS invalid ack nr on packet", ssn);
2623 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
2624 "%" PRIu32
", ACK %" PRIu32
"",
2628 StreamTcpHandleTimestamp(ssn, p);
2637 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2641 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
", "
2642 "ssn->client.last_ack %"PRIu32
"", ssn,
2647 bool ack_indicates_missed_3whs_ack_packet =
false;
2657 SCLogDebug(
"ssn %p: ACK received on midstream SYN/ACK "
2658 "pickup session",ssn);
2661 SCLogDebug(
"ssn %p: ACK received on TFO session",ssn);
2678 SCLogDebug(
"ssn %p: possible data injection", ssn);
2683 SCLogDebug(
"ssn %p: ACK received in the wrong direction",
2688 ack_indicates_missed_3whs_ack_packet =
true;
2692 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ %" PRIu32
""
2693 ", ACK %" PRIu32
"",
2705 StreamTcpHandleTimestamp(ssn, p);
2729 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2755 StreamTcpHandleTimestamp(ssn, p);
2768 SCLogDebug(
"ssn %p: synrecv => Asynchronous stream, packet SEQ"
2769 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2770 "ssn->server.next_seq %" PRIu32,
2775 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2784 SCLogDebug(
"ssn %p: wrong ack nr on packet, possible evasion!!",
2794 SCLogDebug(
"ssn %p: ACK for missing data", ssn);
2797 StreamTcpHandleTimestamp(ssn, p);
2803 SCLogDebug(
"ssn %p: ACK for missing data: ssn->server.next_seq %u", ssn,
2813 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2822 SCLogDebug(
"ssn %p: ACK for missing data", ssn);
2825 StreamTcpHandleTimestamp(ssn, p);
2847 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2852 }
else if ((ack_indicates_missed_3whs_ack_packet ||
2856 if (ack_indicates_missed_3whs_ack_packet) {
2857 SCLogDebug(
"ssn %p: packet fits perfectly after a missed 3whs-ACK", ssn);
2859 SCLogDebug(
"ssn %p: (TFO) expected packet fits perfectly after SYN/ACK", ssn);
2868 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2873 SCLogDebug(
"ssn %p: wrong seq nr on packet", ssn);
2879 SCLogDebug(
"ssn %p: ssn->server.next_win %" PRIu32
", "
2880 "ssn->server.last_ack %"PRIu32
"", ssn,
2902 static int HandleEstablishedPacketToServer(
2905 const TCPHdr *tcph = PacketGetTCP(p);
2910 SCLogDebug(
"ssn %p: =+ pkt (%" PRIu32
") is to server: SEQ %" PRIu32
","
2911 "ACK %" PRIu32
", WIN %" PRIu16
"",
2917 SCLogDebug(
"ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
2920 }
else if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
2921 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
2929 SCLogDebug(
"ssn %p: pkt is keep alive", ssn);
2934 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ"
2935 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
2936 " ssn->client.last_ack %" PRIu32
", ssn->client.next_win"
2937 "%" PRIu32
"(%" PRIu32
")",
2947 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ."
2948 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2949 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2950 "%" PRIu32
"(%" PRIu32
")",
2962 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ"
2963 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2964 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2965 "%" PRIu32
"(%" PRIu32
")",
2980 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
2981 " before last_ack %" PRIu32
", after next_seq %" PRIu32
":"
2982 " acked data that we haven't seen before",
2985 SCLogDebug(
"ssn %p: server => SEQ before last_ack, packet SEQ"
2986 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2987 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2988 "%" PRIu32
"(%" PRIu32
")",
2992 SCLogDebug(
"ssn %p: rejecting because pkt before last_ack", ssn);
2998 int zerowindowprobe = 0;
3001 SCLogDebug(
"ssn %p: zero window probe", ssn);
3002 zerowindowprobe = 1;
3012 if (zerowindowprobe) {
3013 SCLogDebug(
"ssn %p: zero window probe, skipping oow check", ssn);
3016 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
3021 SCLogDebug(
"ssn %p: ssn->server.window %"PRIu32
"", ssn,
3038 StreamTcpHandleTimestamp(ssn, p);
3050 SCLogDebug(
"ssn %p: toserver => SEQ out of window, packet SEQ "
3051 "%" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3052 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
3053 "%" PRIu32
"(%" PRIu32
")",
3057 StreamTcpSackedSize(&ssn->
client));
3077 static int HandleEstablishedPacketToClient(
3080 const TCPHdr *tcph = PacketGetTCP(p);
3085 SCLogDebug(
"ssn %p: =+ pkt (%" PRIu32
") is to client: SEQ %" PRIu32
","
3086 " ACK %" PRIu32
", WIN %" PRIu16
"",
3092 SCLogDebug(
"ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
3095 }
else if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3096 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3110 SCLogDebug(
"ssn %p: adjusted midstream ssn->server.next_win to "
3116 SCLogDebug(
"ssn %p: pkt is keep alive", ssn);
3122 SCLogDebug(
"ssn %p: client => Asynchronous stream, packet SEQ"
3123 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3124 " ssn->client.last_ack %" PRIu32
", ssn->client.next_win"
3125 " %" PRIu32
"(%" PRIu32
")",
3136 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
3137 " before last_ack %" PRIu32
", after next_seq %" PRIu32
":"
3138 " acked data that we haven't seen before",
3141 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
3142 " before last_ack %" PRIu32
". next_seq %" PRIu32,
3149 int zerowindowprobe = 0;
3152 SCLogDebug(
"ssn %p: zero window probe", ssn);
3153 zerowindowprobe = 1;
3164 if (zerowindowprobe) {
3165 SCLogDebug(
"ssn %p: zero window probe, skipping oow check", ssn);
3168 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
3172 SCLogDebug(
"ssn %p: ssn->client.window %"PRIu32
"", ssn,
3185 StreamTcpHandleTimestamp(ssn, p);
3194 SCLogDebug(
"ssn %p: client => SEQ out of window, packet SEQ"
3195 "%" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3196 " ssn->server.last_ack %" PRIu32
", ssn->server.next_win "
3197 "%" PRIu32
"(%" PRIu32
")",
3206 static bool StreamTcpPacketIsZeroWindowProbeAck(
const TcpSession *ssn,
const Packet *p)
3208 const TCPHdr *tcph = PacketGetTCP(p);
3232 if (pkt_win != rcv->
window)
3239 SCLogDebug(
"ssn %p: packet %" PRIu64
" is a Zero Window Probe ACK", ssn, p->
pcap_cnt);
3246 static bool StreamTcpPacketIsDupAck(
const TcpSession *ssn,
const Packet *p)
3248 const TCPHdr *tcph = PacketGetTCP(p);
3266 if (pkt_win == 0 || rcv->
window == 0)
3268 if (pkt_win != rcv->
window)
3276 SCLogDebug(
"ssn %p: packet:%" PRIu64
" seq:%u ack:%u win:%u snd %u:%u:%u rcv %u:%u:%u", ssn,
3300 const TCPHdr *tcph = PacketGetTCP(p);
3351 static int StreamTcpPacketIsSpuriousRetransmission(
const TcpSession *ssn,
Packet *p)
3362 const TCPHdr *tcph = PacketGetTCP(p);
3368 "ssn %p: spurious retransmission; packet entirely before base_seq: SEQ %u(%u) "
3369 "last_ack %u base_seq %u",
3378 SCLogDebug(
"ssn %p: spurious retransmission; packet entirely before last_ack: SEQ %u(%u) "
3386 SCLogDebug(
"ssn %p: NOT spurious retransmission; packet NOT entirely before last_ack: SEQ "
3387 "%u(%u) last_ack %u, base_seq %u",
3404 static int StreamTcpPacketStateEstablished(
3408 const TCPHdr *tcph = PacketGetTCP(p);
3414 if (!StreamTcpValidateRst(ssn, p))
3418 StreamTcpCloseSsnWithReset(p, ssn);
3422 SCLogDebug(
"ssn %p: ssn->server.next_seq %" PRIu32
"", ssn,
3432 StreamTcpHandleTimestamp(ssn, p);
3436 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3444 StreamTcpCloseSsnWithReset(p, ssn);
3449 SCLogDebug(
"ssn %p: ssn->server.next_seq %" PRIu32
"", ssn,
3459 StreamTcpHandleTimestamp(ssn, p);
3463 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3474 if (!StreamTcpValidateTimestamp(ssn, p))
3479 " %" PRIu32
", last ACK %" PRIu32
", next win %"PRIu32
","
3484 if ((StreamTcpHandleFin(
tv, stt, ssn, p)) == -1)
3489 SCLogDebug(
"ssn %p: SYN/ACK packet on state ESTABLISHED... resent",
3493 SCLogDebug(
"ssn %p: SYN/ACK-pkt to server in ESTABLISHED state", ssn);
3502 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
3503 "%" PRIu32
" from stream",
3513 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
3514 "%" PRIu32
" from stream",
3527 SCLogDebug(
"ssn %p: SYN/ACK packet on state ESTABLISHED... resent. "
3528 "Likely due server not receiving final ACK in 3whs", ssn);
3532 SCLogDebug(
"ssn %p: SYN packet on state ESTABLISHED... resent", ssn);
3534 SCLogDebug(
"ssn %p: SYN-pkt to client in EST state", ssn);
3541 SCLogDebug(
"ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
3562 if (!StreamTcpValidateTimestamp(ssn, p))
3568 HandleEstablishedPacketToServer(
tv, ssn, p, stt);
3570 SCLogDebug(
"ssn %p: next SEQ %" PRIu32
", last ACK %" PRIu32
","
3571 " next win %" PRIu32
", win %" PRIu32
"", ssn,
3578 SCLogDebug(
"3whs is now confirmed by server");
3582 HandleEstablishedPacketToClient(
tv, ssn, p, stt);
3584 SCLogDebug(
"ssn %p: next SEQ %" PRIu32
", last ACK %" PRIu32
","
3585 " next win %" PRIu32
", win %" PRIu32
"", ssn,
3610 const TCPHdr *tcph = PacketGetTCP(p);
3616 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ %" PRIu32
","
3620 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3621 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3627 SCLogDebug(
"ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn,
seq, pkt_re,
3632 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
" != "
3633 "%" PRIu32
" from stream",
3646 SCLogDebug(
"ssn %p: state changed to TCP_CLOSE_WAIT", ssn);
3651 SCLogDebug(
"ssn %p: ssn->client.next_seq %" PRIu32
"", ssn,
3656 StreamTcpHandleTimestamp(ssn, p);
3669 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK %" PRIu32
"",
3672 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ %" PRIu32
", "
3676 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3677 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3683 SCLogDebug(
"ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn,
seq, pkt_re,
3688 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
" != "
3689 "%" PRIu32
" from stream (last_ack %u win %u = %u)",
3698 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT1", ssn);
3707 StreamTcpHandleTimestamp(ssn, p);
3720 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK %" PRIu32
"",
3740 static int StreamTcpPacketStateFinWait1(
3744 const TCPHdr *tcph = PacketGetTCP(p);
3750 if (!StreamTcpValidateRst(ssn, p))
3753 StreamTcpCloseSsnWithReset(p, ssn);
3762 StreamTcpHandleTimestamp(ssn, p);
3773 StreamTcpHandleTimestamp(ssn, p);
3781 if (!StreamTcpValidateTimestamp(ssn, p))
3786 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3787 "%" PRIu32
", ACK %" PRIu32
"",
3789 int retransmission = 0;
3791 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
3792 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3798 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3799 " != %" PRIu32
" from stream",
3805 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3806 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3811 if (!retransmission) {
3813 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
3819 StreamTcpHandleTimestamp(ssn, p);
3835 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3839 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3840 "%" PRIu32
", ACK %" PRIu32
"",
3842 int retransmission = 0;
3844 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
3845 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3850 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3856 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3857 " != %" PRIu32
" from stream",
3863 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3864 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3870 StreamTcpHandleTimestamp(ssn, p);
3873 if (!retransmission) {
3875 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
3893 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3900 if (!StreamTcpValidateTimestamp(ssn, p))
3905 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3906 "%" PRIu32
", ACK %" PRIu32
"",
3908 int retransmission = 0;
3910 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
3911 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3917 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3918 " != %" PRIu32
" from stream",
3924 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3925 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3930 if (!retransmission) {
3932 SCLogDebug(
"ssn %p: state changed to TCP_CLOSING", ssn);
3938 StreamTcpHandleTimestamp(ssn, p);
3955 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3959 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3960 "%" PRIu32
", ACK %" PRIu32
"",
3963 int retransmission = 0;
3965 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
3966 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3972 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3973 " != %" PRIu32
" from stream",
3979 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3980 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3985 if (!retransmission) {
3987 SCLogDebug(
"ssn %p: state changed to TCP_CLOSING", ssn);
3993 StreamTcpHandleTimestamp(ssn, p);
4010 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4015 SCLogDebug(
"ssn (%p): SYN pkt on FinWait1", ssn);
4021 if (!StreamTcpValidateTimestamp(ssn, p))
4026 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4027 "%" PRIu32
", ACK %" PRIu32
"",
4029 int retransmission = 0;
4031 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4032 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4037 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4038 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4045 "ssn %p: ACK's older segment as %u < %u", ssn, ack, ssn->
server.
next_seq);
4046 }
else if (!retransmission) {
4050 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
4056 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT2", ssn);
4059 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4060 " != %" PRIu32
" from stream",
4072 StreamTcpHandleTimestamp(ssn, p);
4093 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4099 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4100 "%" PRIu32
", ACK %" PRIu32
"",
4103 int retransmission = 0;
4105 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4106 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4111 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4112 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4117 if (!retransmission) {
4120 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
4126 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT2", ssn);
4129 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4130 " != %" PRIu32
" from stream",
4140 StreamTcpHandleTimestamp(ssn, p);
4161 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4182 static int StreamTcpPacketStateFinWait2(
4186 const TCPHdr *tcph = PacketGetTCP(p);
4192 if (!StreamTcpValidateRst(ssn, p))
4195 StreamTcpCloseSsnWithReset(p, ssn);
4204 StreamTcpHandleTimestamp(ssn, p);
4215 StreamTcpHandleTimestamp(ssn, p);
4223 if (!StreamTcpValidateTimestamp(ssn, p))
4228 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4229 "%" PRIu32
", ACK %" PRIu32
"",
4231 int retransmission = 0;
4237 }
else if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4238 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4244 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ "
4245 "%" PRIu32
" != %" PRIu32
" from stream",
4251 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4252 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4257 if (!retransmission) {
4259 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4269 StreamTcpHandleTimestamp(ssn, p);
4282 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4286 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4287 "%" PRIu32
", ACK %" PRIu32
"",
4289 int retransmission = 0;
4295 }
else if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4296 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4302 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ "
4303 "%" PRIu32
" != %" PRIu32
" from stream",
4309 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4310 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4315 if (!retransmission) {
4317 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4323 StreamTcpHandleTimestamp(ssn, p);
4335 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4341 SCLogDebug(
"ssn (%p): SYN pkt on FinWait2", ssn);
4347 if (!StreamTcpValidateTimestamp(ssn, p))
4352 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4353 "%" PRIu32
", ACK %" PRIu32
"",
4355 int retransmission = 0;
4357 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4358 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4363 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4364 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4369 if (!retransmission) {
4372 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
4377 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4378 " != %" PRIu32
" from stream",
4388 StreamTcpHandleTimestamp(ssn, p);
4404 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4408 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4409 "%" PRIu32
", ACK %" PRIu32
"",
4411 int retransmission = 0;
4413 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4414 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4419 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4420 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4425 if (!retransmission) {
4428 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
4432 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4433 " != %" PRIu32
" from stream",
4443 StreamTcpHandleTimestamp(ssn, p);
4459 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4480 static int StreamTcpPacketStateClosing(
4484 const TCPHdr *tcph = PacketGetTCP(p);
4490 if (!StreamTcpValidateRst(ssn, p))
4493 StreamTcpCloseSsnWithReset(p, ssn);
4502 StreamTcpHandleTimestamp(ssn, p);
4513 StreamTcpHandleTimestamp(ssn, p);
4520 SCLogDebug(
"ssn (%p): SYN pkt on Closing", ssn);
4526 if (!StreamTcpValidateTimestamp(ssn, p))
4531 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4532 "%" PRIu32
", ACK %" PRIu32
"",
4534 int retransmission = 0;
4535 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4536 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4542 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4543 " != %" PRIu32
" from stream",
4549 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4550 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4555 if (!retransmission) {
4557 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4563 StreamTcpHandleTimestamp(ssn, p);
4573 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4577 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4578 "%" PRIu32
", ACK %" PRIu32
"",
4580 int retransmission = 0;
4581 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4582 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4588 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4589 " != %" PRIu32
" from stream",
4595 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4596 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4601 if (!retransmission) {
4603 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4609 StreamTcpHandleTimestamp(ssn, p);
4620 SCLogDebug(
"StreamTcpPacketStateClosing (%p): =+ next SEQ "
4621 "%" PRIu32
", last ACK %" PRIu32
"", ssn,
4641 static int StreamTcpPacketStateCloseWait(
4645 const TCPHdr *tcph = PacketGetTCP(p);
4653 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4654 "%" PRIu32
", ACK %" PRIu32
"",
4657 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4658 "%" PRIu32
", ACK %" PRIu32
"",
4663 if (!StreamTcpValidateRst(ssn, p))
4666 StreamTcpCloseSsnWithReset(p, ssn);
4675 StreamTcpHandleTimestamp(ssn, p);
4686 StreamTcpHandleTimestamp(ssn, p);
4694 if (!StreamTcpValidateTimestamp(ssn, p))
4699 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4700 "%" PRIu32
", ACK %" PRIu32
"",
4703 int retransmission = 0;
4704 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4705 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4710 if (!retransmission) {
4713 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4714 " != %" PRIu32
" from stream",
4721 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4722 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4729 if (!retransmission)
4733 StreamTcpHandleTimestamp(ssn, p);
4745 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4749 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4750 "%" PRIu32
", ACK %" PRIu32
"",
4753 int retransmission = 0;
4754 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4755 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4760 if (!retransmission) {
4763 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4764 " != %" PRIu32
" from stream",
4771 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4772 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4777 if (!retransmission) {
4779 SCLogDebug(
"ssn %p: state changed to TCP_LAST_ACK", ssn);
4785 StreamTcpHandleTimestamp(ssn, p);
4797 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4803 SCLogDebug(
"ssn (%p): SYN pkt on CloseWait", ssn);
4809 if (!StreamTcpValidateTimestamp(ssn, p))
4814 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4815 "%" PRIu32
", ACK %" PRIu32
"",
4818 int retransmission = 0;
4819 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4820 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4826 SCLogDebug(
"ssn %p: -> retransmission", ssn);
4831 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4832 " != %" PRIu32
" from stream",
4838 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4839 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4844 if (!retransmission) {
4849 StreamTcpHandleTimestamp(ssn, p);
4863 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4867 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4868 "%" PRIu32
", ACK %" PRIu32
"",
4870 int retransmission = 0;
4871 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4872 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4878 SCLogDebug(
"ssn %p: -> retransmission", ssn);
4883 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4884 " != %" PRIu32
" from stream",
4890 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4891 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4896 if (!retransmission) {
4901 StreamTcpHandleTimestamp(ssn, p);
4915 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4936 static int StreamTcpPacketStateLastAck(
4940 const TCPHdr *tcph = PacketGetTCP(p);
4946 if (!StreamTcpValidateRst(ssn, p))
4949 StreamTcpCloseSsnWithReset(p, ssn);
4958 StreamTcpHandleTimestamp(ssn, p);
4969 StreamTcpHandleTimestamp(ssn, p);
4977 SCLogDebug(
"ssn (%p): FIN pkt on LastAck", ssn);
4980 SCLogDebug(
"ssn (%p): SYN pkt on LastAck", ssn);
4986 if (!StreamTcpValidateTimestamp(ssn, p))
4991 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4992 "%" PRIu32
", ACK %" PRIu32
"",
4995 int retransmission = 0;
4996 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4997 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
5002 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
5003 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5008 if (!retransmission) {
5010 SCLogDebug(
"ssn %p: not updating state as packet is before next_seq", ssn);
5012 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5013 " != %" PRIu32
" from stream",
5019 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5025 StreamTcpHandleTimestamp(ssn, p);
5036 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5057 static int StreamTcpPacketStateTimeWait(
5061 const TCPHdr *tcph = PacketGetTCP(p);
5067 if (!StreamTcpValidateRst(ssn, p))
5070 StreamTcpCloseSsnWithReset(p, ssn);
5079 StreamTcpHandleTimestamp(ssn, p);
5090 StreamTcpHandleTimestamp(ssn, p);
5100 SCLogDebug(
"ssn (%p): SYN pkt on TimeWait", ssn);
5106 if (!StreamTcpValidateTimestamp(ssn, p))
5111 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
5112 "%" PRIu32
", ACK %" PRIu32
"",
5114 int retransmission = 0;
5115 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
5116 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
5121 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5122 " != %" PRIu32
" from stream",
5128 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
5129 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5134 if (!retransmission) {
5136 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5142 StreamTcpHandleTimestamp(ssn, p);
5153 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5157 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
5158 "%" PRIu32
", ACK %" PRIu32
"",
5160 int retransmission = 0;
5161 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
5162 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
5167 SCLogDebug(
"ssn %p: -> retransmission", ssn);
5170 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5171 " != %" PRIu32
" from stream",
5178 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
5179 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5184 if (!retransmission) {
5186 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5192 StreamTcpHandleTimestamp(ssn, p);
5203 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5215 static int StreamTcpPacketStateClosed(
5220 const TCPHdr *tcph = PacketGetTCP(p);
5226 TcpStream *stream = NULL, *ostream = NULL;
5243 if (StreamTcpStateDispatch(
tv, p, stt, ssn, ssn->
pstate) < 0)
5258 const TCPHdr *tcph = PacketGetTCP(p);
5272 SCLogDebug(
"regular packet %"PRIu64
" from same sender as "
5273 "the previous RST. Looks like it injected!", p->
pcap_cnt);
5299 const TCPHdr *tcph = PacketGetTCP(p);
5304 TcpStream *stream = NULL, *ostream = NULL;
5315 if (ack == ostream->last_ack &&
seq == (stream->
next_seq - 1)) {
5331 TcpStream *stream = NULL, *ostream = NULL;
5342 const TCPHdr *tcph = PacketGetTCP(p);
5361 if (pkt_win != ostream->window)
5370 SCLogDebug(
"seq %u (%u), ack %u (%u) FLAG_KEEPALIVE: %s",
seq, stream->
next_seq, ack, ostream->last_ack,
5400 TcpStream *stream = NULL, *ostream = NULL;
5414 const TCPHdr *tcph = PacketGetTCP(p);
5433 if (pkt_win == ostream->window)
5436 if (ack == ostream->last_ack &&
seq == stream->
next_seq) {
5451 TcpStream *stream = NULL, *ostream = NULL;
5459 const TCPHdr *tcph = PacketGetTCP(p);
5476 SCLogDebug(
"%"PRIu64
", seq %u ack %u stream->next_seq %u ostream->next_seq %u",
5504 TcpStream *stream = NULL, *ostream = NULL;
5515 const TCPHdr *tcph = PacketGetTCP(p);
5531 if (pkt_win < ostream->window) {
5532 uint32_t diff = ostream->window - pkt_win;
5534 SEQ_GT(ack, ostream->next_seq) &&
5537 SCLogDebug(
"%"PRIu64
", pkt_win %u, stream win %u, diff %u, dsize %u",
5539 SCLogDebug(
"%"PRIu64
", pkt_win %u, stream win %u",
5540 p->
pcap_cnt, pkt_win, ostream->window);
5541 SCLogDebug(
"%"PRIu64
", seq %u ack %u ostream->next_seq %u ostream->last_ack %u, ostream->next_win %u, diff %u (%u)",
5542 p->
pcap_cnt,
seq, ack, ostream->next_seq, ostream->last_ack, ostream->next_win,
5543 ostream->next_seq - ostream->last_ack, stream->
next_seq - stream->
last_ack);
5550 uint32_t adiff = ack - ostream->last_ack;
5551 if (((pkt_win > 1024) && (diff > (adiff + 32))) ||
5552 ((pkt_win <= 1024) && (diff > adiff)))
5554 SCLogDebug(
"pkt ACK %u is %u bytes beyond last_ack %u, shrinks window by %u "
5555 "(allowing 32 bytes extra): pkt WIN %u", ack, adiff, ostream->last_ack, diff, pkt_win);
5556 SCLogDebug(
"%u - %u = %u (state %u)", diff, adiff, diff - adiff, ssn->
state);
5571 static inline int StreamTcpStateDispatch(
5579 SCLogDebug(
"packet received on TCP_SYN_SENT state");
5580 if (StreamTcpPacketStateSynSent(
tv, p, stt, ssn)) {
5585 SCLogDebug(
"packet received on TCP_SYN_RECV state");
5586 if (StreamTcpPacketStateSynRecv(
tv, p, stt, ssn)) {
5591 SCLogDebug(
"packet received on TCP_ESTABLISHED state");
5592 if (StreamTcpPacketStateEstablished(
tv, p, stt, ssn)) {
5597 SCLogDebug(
"packet received on TCP_FIN_WAIT1 state");
5598 if (StreamTcpPacketStateFinWait1(
tv, p, stt, ssn)) {
5603 SCLogDebug(
"packet received on TCP_FIN_WAIT2 state");
5604 if (StreamTcpPacketStateFinWait2(
tv, p, stt, ssn)) {
5609 SCLogDebug(
"packet received on TCP_CLOSING state");
5610 if (StreamTcpPacketStateClosing(
tv, p, stt, ssn)) {
5615 SCLogDebug(
"packet received on TCP_CLOSE_WAIT state");
5616 if (StreamTcpPacketStateCloseWait(
tv, p, stt, ssn)) {
5621 SCLogDebug(
"packet received on TCP_LAST_ACK state");
5622 if (StreamTcpPacketStateLastAck(
tv, p, stt, ssn)) {
5627 SCLogDebug(
"packet received on TCP_TIME_WAIT state");
5628 if (StreamTcpPacketStateTimeWait(
tv, p, stt, ssn)) {
5634 SCLogDebug(
"packet received on closed state");
5636 if (StreamTcpPacketStateClosed(
tv, p, stt, ssn)) {
5642 SCLogDebug(
"packet received on default state");
5678 const TCPHdr *tcph = PacketGetTCP(p);
5693 SCLogDebug(
"ssn %p: removing ASYNC flag as we have packets on both sides", ssn);
5713 if (StreamTcpCheckFlowDrops(p) == 1) {
5723 if (StreamTcpPacketStateNone(
tv, p, stt, ssn) == -1) {
5749 if (StreamTcpPacketIsKeepAlive(ssn, p) == 1) {
5752 if (StreamTcpPacketIsKeepAliveACK(ssn, p) == 1) {
5753 StreamTcpClearKeepAliveFlag(ssn, p);
5756 StreamTcpClearKeepAliveFlag(ssn, p);
5758 const bool is_zwp_ack = StreamTcpPacketIsZeroWindowProbeAck(ssn, p);
5769 if (StreamTcpPacketIsDupAck(ssn, p)) {
5776 if (StreamTcpPacketIsFinShutdownAck(ssn, p) == 0) {
5777 if (StreamTcpPacketIsWindowUpdate(ssn, p) == 0) {
5778 if (StreamTcpPacketIsBadWindowUpdate(ssn,p))
5780 if (StreamTcpPacketIsOutdatedAck(ssn, p))
5785 int ret = StreamTcpPacketIsSpuriousRetransmission(ssn, p);
5794 if (StreamTcpStateDispatch(
tv, p, stt, ssn, ssn->
state) < 0)
5798 StreamTcpPacketCheckPostRst(ssn, p);
5843 SCLogDebug(
"bypass as stream is dead and we have no rules");
5856 if (StreamTcpInlineDropInvalid()) {
5860 DecodeSetNoPayloadInspectionFlag(p);
5874 static inline int StreamTcpValidateChecksum(
Packet *p)
5882 const TCPHdr *tcph = PacketGetTCP(p);
5883 if (PacketIsIPv4(p)) {
5884 const IPV4Hdr *ip4h = PacketGetIPv4(p);
5885 p->
l4.
csum = TCPChecksum(ip4h->s_ip_addrs, (uint16_t *)tcph,
5888 }
else if (PacketIsIPv6(p)) {
5889 const IPV6Hdr *ip6h = PacketGetIPv6(p);
5890 p->
l4.
csum = TCPV6Checksum(ip6h->s_ip6_addrs, (uint16_t *)tcph,
5911 static int TcpSessionPacketIsStreamStarter(
const Packet *p)
5913 const TCPHdr *tcph = PacketGetTCP(p);
5936 static bool TcpSessionReuseDoneEnoughSyn(
const Packet *p,
const Flow *f,
const TcpSession *ssn)
5938 const TCPHdr *tcph = PacketGetTCP(p);
5943 SCLogDebug(
"steam starter packet %" PRIu64
", ssn %p null. Reuse.", p->
pcap_cnt, ssn);
5948 ", ssn %p. STREAMTCP_FLAG_TFO_DATA_IGNORED set. Reuse.",
5953 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.", p->
pcap_cnt, ssn);
5957 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5960 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5963 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
5973 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5976 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5979 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
5992 static bool TcpSessionReuseDoneEnoughSynAck(
const Packet *p,
const Flow *f,
const TcpSession *ssn)
5994 const TCPHdr *tcph = PacketGetTCP(p);
5997 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p null. No reuse.", p->
pcap_cnt, ssn);
6001 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.", p->
pcap_cnt, ssn);
6005 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
6008 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
6011 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
6021 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
6024 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
6027 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
6043 const TCPHdr *tcph = PacketGetTCP(p);
6045 return TcpSessionReuseDoneEnoughSyn(p, f, ssn);
6050 return TcpSessionReuseDoneEnoughSynAck(p, f, ssn);
6059 if (p->
proto == IPPROTO_TCP && PacketIsTCP(p)) {
6060 if (TcpSessionPacketIsStreamStarter(p) == 1) {
6061 if (TcpSessionReuseDoneEnough(p, f, tcp_ssn) == 1) {
6084 if (!(PacketIsTCP(p))) {
6088 CheckThreadId(
tv, p, stt);
6094 if (StreamTcpValidateChecksum(p) == 0) {
6116 *data = (
void *)stt;
6125 IsStreamTcpSessionMemcapExceptionPolicyStatsValid);
6133 "exception_policy.tcp.midstream.", IsMidstreamExceptionPolicyStatsValid);
6137 "exception_policy.tcp.midstream.", IsMidstreamExceptionPolicyStatsValid);
6153 "exception_policy.tcp.reassembly.", IsReassemblyMemcapExceptionPolicyStatsValid);
6172 SCLogDebug(
"StreamTcp thread specific ctx online at %p, reassembly ctx %p",
6181 StreamTcpSessionPoolAlloc,
6182 StreamTcpSessionPoolInit, NULL,
6183 StreamTcpSessionPoolCleanup, NULL);
6193 SCLogError(
"failed to setup/expand stream session pool. Expand stream.memcap?");
6238 const TCPHdr *tcph = PacketGetTCP(p);
6246 if (!StreamTcpValidateTimestamp(ssn, p)) {
6275 StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
6276 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
6288 StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
6289 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
6302 receiver_stream = &ssn->
server;
6304 receiver_stream = &ssn->
client;
6306 SCLogDebug(
"ssn %p: setting STREAMTCP_STREAM_FLAG_RST_RECV on receiver stream", ssn);
6326 switch (os_policy) {
6333 SCLogDebug(
"reset is not Valid! Packet SEQ: %" PRIu32
" "
6334 "and server SEQ: %" PRIu32
"",
6343 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" "
6344 "and client SEQ: %" PRIu32
"",
6361 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6362 " server SEQ: %" PRIu32
"",
6374 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6375 " client SEQ: %" PRIu32
"",
6396 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" "
6397 "and server SEQ: %" PRIu32
"",
6403 SCLogDebug(
"reset is valid! Packet SEQ: %" PRIu32
" Stream %u",
seq,
6407 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6408 " client SEQ: %" PRIu32
"",
6439 uint8_t check_ts = 1;
6440 const TCPHdr *tcph = PacketGetTCP(p);
6444 sender_stream = &ssn->
client;
6445 receiver_stream = &ssn->
server;
6447 sender_stream = &ssn->
server;
6448 receiver_stream = &ssn->
client;
6459 uint32_t last_pkt_ts = sender_stream->
last_pkt_ts;
6460 uint32_t last_ts = sender_stream->
last_ts;
6510 SCLogDebug(
"ts %"PRIu32
", last_ts %"PRIu32
"",
ts, last_ts);
6514 result = (int32_t) ((
ts - last_ts) + 1);
6516 result = (int32_t) (
ts - last_ts);
6519 SCLogDebug(
"result %" PRIi32
", p->ts(secs) %" PRIuMAX
"", result,
6522 if (last_pkt_ts == 0 &&
6530 "%" PRIu32
" p->tcpvars->ts %" PRIu32
" result "
6531 "%" PRId32
"", last_ts,
ts, result);
6534 }
else if ((sender_stream->
last_ts != 0) &&
6536 SCLogDebug(
"packet is not valid last_pkt_ts "
6537 "%" PRIu32
" p->ts(sec) %" PRIu32
"",
6549 SCLogDebug(
"timestamp considered valid anyway");
6581 uint8_t check_ts = 1;
6582 const TCPHdr *tcph = PacketGetTCP(p);
6586 sender_stream = &ssn->
client;
6587 receiver_stream = &ssn->
server;
6589 sender_stream = &ssn->
server;
6590 receiver_stream = &ssn->
client;
6658 result = (int32_t) ((
ts - sender_stream->
last_ts) + 1);
6660 result = (int32_t) (
ts - sender_stream->
last_ts);
6663 SCLogDebug(
"result %" PRIi32
", p->ts(sec) %" PRIuMAX
"", result,
6673 SCLogDebug(
"timestamp is not valid sender_stream->last_ts "
6674 "%" PRIu32
" p->tcpvars->ts %" PRIu32
" result "
6675 "%" PRId32
"", sender_stream->
last_ts,
ts, result);
6678 }
else if ((sender_stream->
last_ts != 0) &&
6681 SCLogDebug(
"packet is not valid sender_stream->last_pkt_ts "
6682 "%" PRIu32
" p->ts(sec) %" PRIu32
"",
6696 }
else if (ret == 0) {
6706 SCLogDebug(
"timestamp considered valid anyway");
6742 const TCPHdr *tcph = PacketGetTCP(p);
6757 SCLogDebug(
"ssn %p: pkt ACK %" PRIu32
" == stream last ACK %" PRIu32, ssn, ack,
6770 SCLogDebug(
"ACK %"PRIu32
" is before last_ack %"PRIu32
" - window "
6771 "%"PRIu32
" = %"PRIu32, ack, stream->
last_ack,
6794 SCLogDebug(
"default path leading to invalid: ACK %"PRIu32
", last_ack %"PRIu32
6807 const uint32_t progress)
6861 static void StreamTcpPseudoPacketCreateDetectLogFlush(
ThreadVars *
tv,
6884 np->
proto = IPPROTO_TCP;
6885 FlowReference(&np->
flow, f);
6895 DecodeSetNoPacketInspectionFlag(np);
6898 DecodeSetNoPayloadInspectionFlag(np);
6938 ip4h->
ip_len = htons(40);
6944 ip4h->s_ip_src.s_addr = f->
src.addr_data32[0];
6945 ip4h->s_ip_dst.s_addr = f->
dst.addr_data32[0];
6947 ip4h->s_ip_src.s_addr = f->
dst.addr_data32[0];
6948 ip4h->s_ip_dst.s_addr = f->
src.addr_data32[0];
6981 ip6h->s_ip6_vfc = 0x60;
6982 ip6h->s_ip6_flow = 0;
6983 ip6h->s_ip6_nxt = IPPROTO_TCP;
6984 ip6h->s_ip6_plen = htons(20);
6985 ip6h->s_ip6_hlim = 64;
6987 ip6h->s_ip6_src[0] = f->
src.addr_data32[0];
6988 ip6h->s_ip6_src[1] = f->
src.addr_data32[1];
6989 ip6h->s_ip6_src[2] = f->
src.addr_data32[2];
6990 ip6h->s_ip6_src[3] = f->
src.addr_data32[3];
6991 ip6h->s_ip6_dst[0] = f->
dst.addr_data32[0];
6992 ip6h->s_ip6_dst[1] = f->
dst.addr_data32[1];
6993 ip6h->s_ip6_dst[2] = f->
dst.addr_data32[2];
6994 ip6h->s_ip6_dst[3] = f->
dst.addr_data32[3];
6996 ip6h->s_ip6_src[0] = f->
dst.addr_data32[0];
6997 ip6h->s_ip6_src[1] = f->
dst.addr_data32[1];
6998 ip6h->s_ip6_src[2] = f->
dst.addr_data32[2];
6999 ip6h->s_ip6_src[3] = f->
dst.addr_data32[3];
7000 ip6h->s_ip6_dst[0] = f->
src.addr_data32[0];
7001 ip6h->s_ip6_dst[1] = f->
src.addr_data32[1];
7002 ip6h->s_ip6_dst[2] = f->
src.addr_data32[2];
7003 ip6h->s_ip6_dst[3] = f->
src.addr_data32[3];
7035 np->
ts = parent->
ts;
7043 FlowDeReference(&np->
flow);
7062 StreamTcpPseudoPacketCreateDetectLogFlush(
tv, stt, p, ssn, pq,
ts^0);
7063 StreamTcpPseudoPacketCreateDetectLogFlush(
tv, stt, p, ssn, pq,
ts^1);
7083 if (p->
flow == NULL)
7111 const uint8_t *seg_data;
7112 uint32_t seg_datalen;
7115 int ret = CallbackFunc(p, seg, data, seg_data, seg_datalen);
7143 if (p->
flow == NULL)
7157 if (server_node == NULL && client_node == NULL) {
7161 while (server_node != NULL || client_node != NULL) {
7162 const uint8_t *seg_data;
7163 uint32_t seg_datalen;
7164 if (server_node == NULL) {
7171 &client_stream->
sb, &client_node->
sbseg, &seg_data, &seg_datalen);
7172 ret = CallbackFunc(p, client_node, data, seg_data, seg_datalen);
7177 client_node = TCPSEG_RB_NEXT(client_node);
7178 }
else if (client_node == NULL) {
7185 &server_stream->
sb, &server_node->
sbseg, &seg_data, &seg_datalen);
7186 ret = CallbackFunc(p, server_node, data, seg_data, seg_datalen);
7191 server_node = TCPSEG_RB_NEXT(server_node);
7196 &client_stream->
sb, &client_node->
sbseg, &seg_data, &seg_datalen);
7197 ret = CallbackFunc(p, client_node, data, seg_data, seg_datalen);
7202 client_node = TCPSEG_RB_NEXT(client_node);
7205 &server_stream->
sb, &server_node->
sbseg, &seg_data, &seg_datalen);
7206 ret = CallbackFunc(p, server_node, data, seg_data, seg_datalen);
7211 server_node = TCPSEG_RB_NEXT(server_node);
7246 const char *tcp_state = NULL;
7252 tcp_state =
"syn_sent";
7255 tcp_state =
"syn_recv";
7258 tcp_state =
"established";
7261 tcp_state =
"fin_wait1";
7264 tcp_state =
"fin_wait2";
7267 tcp_state =
"time_wait";
7270 tcp_state =
"last_ack";
7273 tcp_state =
"close_wait";
7276 tcp_state =
"closing";
7279 tcp_state =
"closed";