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(
223 extern thread_local uint64_t t_pcapcnt;
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))) {
959 SCLogNotice(
"simulating memcap reached condition for packet %" PRIu64, t_pcapcnt);
973 const TCPHdr *tcph = PacketGetTCP(p);
1007 switch(ssn->
state) {
1032 if (PacketIsIPv4(p)) {
1042 }
else if (PacketIsIPv6(p)) {
1068 #define StreamTcpUpdateLastAck(ssn, stream, ack) \
1070 if (SEQ_GT((ack), (stream)->last_ack) && SEQ_GT(ack, (stream)->base_seq)) { \
1071 SCLogDebug("ssn %p: last_ack set to %" PRIu32 ", moved %u forward", (ssn), (ack), \
1072 (ack) - (stream)->last_ack); \
1073 if ((SEQ_LEQ((stream)->last_ack, (stream)->next_seq) && \
1074 SEQ_GT((ack), (stream)->next_seq))) { \
1075 SCLogDebug("last_ack just passed next_seq: %u (was %u) > %u", (ack), \
1076 (stream)->last_ack, (stream)->next_seq); \
1078 SCLogDebug("next_seq (%u) <> last_ack now %d", (stream)->next_seq, \
1079 (int)(stream)->next_seq - (ack)); \
1081 (stream)->last_ack = (ack); \
1082 StreamTcpSackPruneList((stream)); \
1084 SCLogDebug("ssn %p: no update: ack %u, last_ack %" PRIu32 ", next_seq %u (state %u)", \
1085 (ssn), (ack), (stream)->last_ack, (stream)->next_seq, (ssn)->state); \
1089 #define StreamTcpAsyncLastAckUpdate(ssn, stream) { \
1090 if ((ssn)->flags & STREAMTCP_FLAG_ASYNC) { \
1091 if (SEQ_GT((stream)->next_seq, (stream)->last_ack)) { \
1092 uint32_t ack_diff = (stream)->next_seq - (stream)->last_ack; \
1093 (stream)->last_ack += ack_diff; \
1094 SCLogDebug("ssn %p: ASYNC last_ack set to %"PRIu32", moved %u forward", \
1095 (ssn), (stream)->next_seq, ack_diff); \
1100 #define StreamTcpUpdateNextSeq(ssn, stream, seq) { \
1101 (stream)->next_seq = seq; \
1102 SCLogDebug("ssn %p: next_seq %" PRIu32, (ssn), (stream)->next_seq); \
1103 StreamTcpAsyncLastAckUpdate((ssn), (stream)); \
1113 #define StreamTcpUpdateNextWin(ssn, stream, win) { \
1114 uint32_t sacked_size__ = StreamTcpSackedSize((stream)); \
1115 if (SEQ_GT(((win) + sacked_size__), (stream)->next_win)) { \
1116 (stream)->next_win = ((win) + sacked_size__); \
1117 SCLogDebug("ssn %p: next_win set to %"PRIu32, (ssn), (stream)->next_win); \
1125 SCLogDebug(
"ssn %p: (state: %s) Reset received and state changed to "
1129 static bool IsMidstreamExceptionPolicyStatsValid(
enum ExceptionPolicy policy)
1143 static void StreamTcpMidstreamExceptionPolicyStatsIncr(
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,
1471 SCLogDebug(
"ssn %p: ssn->client.isn %" PRIu32
", "
1472 "ssn->client.next_seq %" PRIu32
", ssn->client.last_ack "
1482 SCLogDebug(
"Midstream not enabled, so won't pick up a session");
1487 SCLogDebug(
"Midstream policy not permissive, so won't pick up a session");
1504 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1505 "TCP_ESTABLISHED", ssn);
1526 SCLogDebug(
"ssn %p: ssn->client.isn %u, ssn->client.next_seq %u",
1535 SCLogDebug(
"ssn %p: ssn->client.next_win %"PRIu32
", "
1536 "ssn->server.next_win %"PRIu32
"", ssn,
1538 SCLogDebug(
"ssn %p: ssn->client.last_ack %"PRIu32
", "
1539 "ssn->server.last_ack %"PRIu32
"", ssn,
1547 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1548 "ssn->client.last_ts %" PRIu32
"", ssn,
1567 SCLogDebug(
"ssn %p: assuming SACK permitted for both sides", ssn);
1581 const TCPHdr *tcph = PacketGetTCP(p);
1611 StreamTcp3whsSynAckToStateQueue(p, &search);
1619 search.
ts == q->
ts) {
1632 if (StreamTcp3whsFindSynAckBySynAck(ssn, p) != NULL)
1636 SCLogDebug(
"ssn %p: =~ SYN/ACK queue limit reached", ssn);
1642 SCLogDebug(
"ssn %p: =~ SYN/ACK queue failed: stream memcap reached", ssn);
1648 SCLogDebug(
"ssn %p: =~ SYN/ACK queue failed: alloc failed", ssn);
1653 StreamTcp3whsSynAckToStateQueue(p, q);
1667 const TCPHdr *tcph = PacketGetTCP(p);
1702 StreamTcp3whsSynAckToStateQueue(p, &update);
1709 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_SYN_RECV", ssn);
1725 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1726 "ssn->client.last_ts %" PRIu32
"", ssn,
1754 SCLogDebug(
"ssn %p: SACK permitted for session", ssn);
1761 SCLogDebug(
"ssn %p: ssn->server.next_win %" PRIu32
"", ssn,
1763 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
"", ssn,
1765 SCLogDebug(
"ssn %p: ssn->server.isn %" PRIu32
", "
1766 "ssn->server.next_seq %" PRIu32
", "
1767 "ssn->server.last_ack %" PRIu32
" "
1768 "(ssn->client.last_ack %" PRIu32
")", ssn,
1775 SCLogDebug(
"ssn %p: STREAMTCP_FLAG_4WHS unset, normal SYN/ACK"
1776 " so considering 3WHS", ssn);
1787 static inline bool StateSynSentValidateTimestamp(
TcpSession *ssn,
Packet *p)
1797 if (receiver_stream->
last_ts != 0 && ts_echo != 0 &&
1798 ts_echo != receiver_stream->
last_ts)
1801 ts_echo, receiver_stream->
last_ts);
1805 if (receiver_stream->
last_ts == 0 && ts_echo != 0) {
1807 ts_echo, receiver_stream->
last_ts);
1817 memset(q, 0,
sizeof(*q));
1838 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1844 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1848 memset(q, 0,
sizeof(*q));
1849 const TCPHdr *tcph = PacketGetTCP(p);
1868 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1875 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1879 memset(q, 0,
sizeof(*q));
1881 const TCPHdr *tcph = PacketGetTCP(p);
1899 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1915 SCLogDebug(
"ssn %p: search state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, s, s->
seq, s->
win,
1920 SCLogDebug(
"ssn %p: queue state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u (last:%s)", ssn, q,
1928 }
else if (ignore_ts) {
1948 ssn->
queue = new_head;
1951 tail->next = old_head;
1953 *old_head = *search;
1954 old_head->
next = NULL;
1960 TcpStateQueueInitFromSsnSyn(ssn, &search);
1964 if (ssn->
queue != NULL && StreamTcp3whsFindSyn(ssn, &search, &
tail,
false) != NULL)
1974 AddAndRotate(ssn,
tail, &search);
1979 SCLogDebug(
"ssn %p: =~ SYN queue failed: stream memcap reached", ssn);
1985 SCLogDebug(
"ssn %p: =~ SYN queue failed: alloc failed", ssn);
2039 static inline bool StateSynSentCheckSynAck3Whs(
TcpSession *ssn,
Packet *p,
const bool ts_mismatch)
2041 const TCPHdr *tcph = PacketGetTCP(p);
2043 if (seq_match && !ts_mismatch) {
2048 if (ssn->
queue == NULL) {
2053 TcpStateQueueInitFromPktSynAck(p, &search);
2064 SCLogDebug(
"ssn %p: found queued SYN state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q,
2066 StreamTcp3whsStoreSynApplyToSsn(ssn, q);
2071 }
else if (ts_mismatch) {
2085 static inline bool StateSynSentCheckSynAckTFO(
TcpSession *ssn,
Packet *p,
const bool ts_mismatch)
2087 const TCPHdr *tcph = PacketGetTCP(p);
2090 if (seq_match_tfo && !ts_mismatch) {
2092 }
else if (seq_match_nodata && !ts_mismatch) {
2099 if (ssn->
queue == NULL) {
2104 TcpStateQueueInitFromPktSynAck(p, &search);
2115 SCLogDebug(
"ssn %p: found queued SYN state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q,
2117 StreamTcp3whsStoreSynApplyToSsn(ssn, q);
2122 if (!seq_match_tfo && !seq_match_nodata) {
2124 }
else if (ts_mismatch) {
2140 static int StreamTcpPacketStateSynSent(
2144 const TCPHdr *tcph = PacketGetTCP(p);
2150 SCLogDebug(
"%" PRIu64
": ssn %p: SYN/ACK on SYN_SENT state for packet %" PRIu64,
2154 const bool ts_mismatch =
2159 if (StateSynSentCheckSynAck3Whs(ssn, p, ts_mismatch)) {
2160 SCLogDebug(
"ssn %p: ACK match, packet ACK %" PRIu32
" == "
2161 "%" PRIu32
" from stream",
2164 SCLogDebug(
"ssn %p: (3WHS) ACK mismatch, packet ACK %" PRIu32
" != "
2165 "%" PRIu32
" from stream",
2170 if (StateSynSentCheckSynAckTFO(ssn, p, ts_mismatch)) {
2171 SCLogDebug(
"ssn %p: (TFO) ACK matches next_seq, packet ACK %" PRIu32
" == "
2172 "%" PRIu32
" from stream",
2175 SCLogDebug(
"ssn %p: (TFO) ACK mismatch, packet ACK %" PRIu32
" != "
2176 "%" PRIu32
" from stream",
2182 StreamTcp3wsFreeQueue(ssn);
2184 StreamTcp3whsSynAckUpdate(ssn, p, NULL);
2193 SCLogDebug(
"ssn %p: SYN/ACK received in the wrong direction", ssn);
2197 SCLogDebug(
"ssn %p: SYN/ACK received on 4WHS session", ssn);
2204 SCLogDebug(
"ssn %p: 4WHS ACK mismatch, packet ACK %" PRIu32
""
2205 " != %" PRIu32
" from stream",
2215 SCLogDebug(
"ssn %p: 4WHS SEQ mismatch, packet SEQ %" PRIu32
""
2216 " != %" PRIu32
" from *first* SYN pkt",
2223 SCLogDebug(
"ssn %p: =~ 4WHS ssn state is now TCP_SYN_RECV", ssn);
2237 SCLogDebug(
"ssn %p: 4WHS ssn->client.last_ts %" PRIu32
" "
2238 "ssn->server.last_ts %" PRIu32
"",
2263 SCLogDebug(
"ssn %p: SACK permitted for 4WHS session", ssn);
2270 SCLogDebug(
"ssn %p: 4WHS ssn->client.isn %" PRIu32
", "
2271 "ssn->client.next_seq %" PRIu32
", "
2272 "ssn->client.last_ack %" PRIu32
" "
2273 "(ssn->server.last_ack %" PRIu32
")",
2282 if (!StateSynSentValidateTimestamp(ssn, p)) {
2290 if (!StreamTcpValidateRst(ssn, p))
2297 SCLogDebug(
"ssn->server.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2299 StreamTcpCloseSsnWithReset(p, ssn);
2300 StreamTcp3wsFreeQueue(ssn);
2304 SCLogDebug(
"ssn->client.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2305 StreamTcpCloseSsnWithReset(p, ssn);
2306 StreamTcp3wsFreeQueue(ssn);
2314 SCLogDebug(
"ssn %p: SYN packet on state SYN_SENT... resent", ssn);
2316 SCLogDebug(
"ssn %p: SYN packet on state SYN_SENT... resent of "
2329 SCLogDebug(
"ssn %p: STREAMTCP_FLAG_4WHS flag set", ssn);
2366 SCLogDebug(
"ssn %p: 4WHS ssn->server.isn %" PRIu32
", "
2367 "ssn->server.next_seq %" PRIu32
", "
2368 "ssn->server.last_ack %"PRIu32
"", ssn,
2371 SCLogDebug(
"ssn %p: 4WHS ssn->client.isn %" PRIu32
", "
2372 "ssn->client.next_seq %" PRIu32
", "
2373 "ssn->client.last_ack %"PRIu32
"", ssn,
2382 TcpStateQueueInitFromPktSyn(p, &syn_pkt);
2383 TcpStateQueueInitFromSsnSyn(ssn, &syn_ssn);
2385 if (memcmp(&syn_pkt, &syn_ssn,
sizeof(
TcpStateQueue)) != 0) {
2387 StreamTcp3whsStoreSyn(ssn, p);
2388 SCLogDebug(
"ssn %p: Retransmitted SYN. Updating ssn from packet %" PRIu64
2389 ". Stored previous state",
2392 StreamTcp3whsStoreSynApplyToSsn(ssn, &syn_pkt);
2408 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
2409 "%" PRIu32
" from stream",
2416 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2417 StreamTcp3wsFreeQueue(ssn);
2430 SCLogDebug(
"ssn %p: synsent => Asynchronous stream, packet SEQ"
2431 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2432 "ssn->client.next_seq %" PRIu32
"",
2481 static int StreamTcpPacketStateSynRecv(
2485 const TCPHdr *tcph = PacketGetTCP(p);
2488 if (!StreamTcpValidateRst(ssn, p))
2505 SCLogDebug(
"Detection evasion has been attempted, so"
2506 " not resetting the connection !!");
2514 SCLogDebug(
"Detection evasion has been attempted, so"
2515 " not resetting the connection !!");
2521 StreamTcpCloseSsnWithReset(p, ssn);
2524 StreamTcpHandleTimestamp(ssn, p);
2531 if (!StreamTcpValidateTimestamp(ssn, p))
2535 if ((StreamTcpHandleFin(
tv, stt, ssn, p)) == -1)
2540 SCLogDebug(
"ssn %p: SYN/ACK packet on state SYN_RECV. resent", ssn);
2543 SCLogDebug(
"ssn %p: SYN/ACK-pkt to server in SYN_RECV state", ssn);
2552 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
2553 "%" PRIu32
" from stream",
2563 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
2564 "%" PRIu32
" from stream",
2567 if (StreamTcp3whsQueueSynAck(ssn, p) == -1)
2569 SCLogDebug(
"ssn %p: queued different SYN/ACK", ssn);
2573 SCLogDebug(
"ssn %p: SYN packet on state SYN_RECV... resent", ssn);
2576 SCLogDebug(
"ssn %p: SYN-pkt to client in SYN_RECV state", ssn);
2583 SCLogDebug(
"ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
2591 SCLogDebug(
"ssn %p: checking ACK against queued SYN/ACKs", ssn);
2594 SCLogDebug(
"ssn %p: here we update state against queued SYN/ACK", ssn);
2595 StreamTcp3whsSynAckUpdate(ssn, p, q);
2597 SCLogDebug(
"ssn %p: none found, now checking ACK against original SYN/ACK (state)", ssn);
2607 if (!(StreamTcpValidateTimestamp(ssn, p))) {
2613 SCLogDebug(
"ssn %p: ACK received on 4WHS session",ssn);
2616 SCLogDebug(
"ssn %p: 4WHS wrong seq nr on packet", ssn);
2621 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
2622 SCLogDebug(
"ssn %p: 4WHS invalid ack nr on packet", ssn);
2628 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
2629 "%" PRIu32
", ACK %" PRIu32
"",
2633 StreamTcpHandleTimestamp(ssn, p);
2642 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2646 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
", "
2647 "ssn->client.last_ack %"PRIu32
"", ssn,
2652 bool ack_indicates_missed_3whs_ack_packet =
false;
2662 SCLogDebug(
"ssn %p: ACK received on midstream SYN/ACK "
2663 "pickup session",ssn);
2666 SCLogDebug(
"ssn %p: ACK received on TFO session",ssn);
2683 SCLogDebug(
"ssn %p: possible data injection", ssn);
2688 SCLogDebug(
"ssn %p: ACK received in the wrong direction",
2693 ack_indicates_missed_3whs_ack_packet =
true;
2697 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ %" PRIu32
""
2698 ", ACK %" PRIu32
"",
2710 StreamTcpHandleTimestamp(ssn, p);
2734 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2760 StreamTcpHandleTimestamp(ssn, p);
2773 SCLogDebug(
"ssn %p: synrecv => Asynchronous stream, packet SEQ"
2774 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2775 "ssn->server.next_seq %" PRIu32,
2780 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2789 SCLogDebug(
"ssn %p: wrong ack nr on packet, possible evasion!!",
2799 SCLogDebug(
"ssn %p: ACK for missing data", ssn);
2802 StreamTcpHandleTimestamp(ssn, p);
2808 SCLogDebug(
"ssn %p: ACK for missing data: ssn->server.next_seq %u", ssn,
2818 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2827 SCLogDebug(
"ssn %p: ACK for missing data", ssn);
2830 StreamTcpHandleTimestamp(ssn, p);
2852 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2857 }
else if ((ack_indicates_missed_3whs_ack_packet ||
2861 if (ack_indicates_missed_3whs_ack_packet) {
2862 SCLogDebug(
"ssn %p: packet fits perfectly after a missed 3whs-ACK", ssn);
2864 SCLogDebug(
"ssn %p: (TFO) expected packet fits perfectly after SYN/ACK", ssn);
2873 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2878 SCLogDebug(
"ssn %p: wrong seq nr on packet", ssn);
2884 SCLogDebug(
"ssn %p: ssn->server.next_win %" PRIu32
", "
2885 "ssn->server.last_ack %"PRIu32
"", ssn,
2907 static int HandleEstablishedPacketToServer(
2910 const TCPHdr *tcph = PacketGetTCP(p);
2915 SCLogDebug(
"ssn %p: =+ pkt (%" PRIu32
") is to server: SEQ %" PRIu32
","
2916 "ACK %" PRIu32
", WIN %" PRIu16
"",
2922 SCLogDebug(
"ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
2925 }
else if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
2926 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
2934 SCLogDebug(
"ssn %p: pkt is keep alive", ssn);
2939 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ"
2940 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
2941 " ssn->client.last_ack %" PRIu32
", ssn->client.next_win"
2942 "%" PRIu32
"(%" PRIu32
")",
2952 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ."
2953 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2954 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2955 "%" PRIu32
"(%" PRIu32
")",
2967 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ"
2968 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2969 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2970 "%" PRIu32
"(%" PRIu32
")",
2985 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
2986 " before last_ack %" PRIu32
", after next_seq %" PRIu32
":"
2987 " acked data that we haven't seen before",
2990 SCLogDebug(
"ssn %p: server => SEQ before last_ack, packet SEQ"
2991 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2992 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2993 "%" PRIu32
"(%" PRIu32
")",
2997 SCLogDebug(
"ssn %p: rejecting because pkt before last_ack", ssn);
3003 int zerowindowprobe = 0;
3006 SCLogDebug(
"ssn %p: zero window probe", ssn);
3007 zerowindowprobe = 1;
3017 if (zerowindowprobe) {
3018 SCLogDebug(
"ssn %p: zero window probe, skipping oow check", ssn);
3021 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
3026 SCLogDebug(
"ssn %p: ssn->server.window %"PRIu32
"", ssn,
3043 StreamTcpHandleTimestamp(ssn, p);
3055 SCLogDebug(
"ssn %p: toserver => SEQ out of window, packet SEQ "
3056 "%" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3057 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
3058 "%" PRIu32
"(%" PRIu32
")",
3062 StreamTcpSackedSize(&ssn->
client));
3082 static int HandleEstablishedPacketToClient(
3085 const TCPHdr *tcph = PacketGetTCP(p);
3090 SCLogDebug(
"ssn %p: =+ pkt (%" PRIu32
") is to client: SEQ %" PRIu32
","
3091 " ACK %" PRIu32
", WIN %" PRIu16
"",
3097 SCLogDebug(
"ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
3100 }
else if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3101 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3115 SCLogDebug(
"ssn %p: adjusted midstream ssn->server.next_win to "
3121 SCLogDebug(
"ssn %p: pkt is keep alive", ssn);
3127 SCLogDebug(
"ssn %p: client => Asynchronous stream, packet SEQ"
3128 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3129 " ssn->client.last_ack %" PRIu32
", ssn->client.next_win"
3130 " %" PRIu32
"(%" PRIu32
")",
3141 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
3142 " before last_ack %" PRIu32
", after next_seq %" PRIu32
":"
3143 " acked data that we haven't seen before",
3146 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
3147 " before last_ack %" PRIu32
". next_seq %" PRIu32,
3154 int zerowindowprobe = 0;
3157 SCLogDebug(
"ssn %p: zero window probe", ssn);
3158 zerowindowprobe = 1;
3169 if (zerowindowprobe) {
3170 SCLogDebug(
"ssn %p: zero window probe, skipping oow check", ssn);
3173 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
3177 SCLogDebug(
"ssn %p: ssn->client.window %"PRIu32
"", ssn,
3190 StreamTcpHandleTimestamp(ssn, p);
3199 SCLogDebug(
"ssn %p: client => SEQ out of window, packet SEQ"
3200 "%" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3201 " ssn->server.last_ack %" PRIu32
", ssn->server.next_win "
3202 "%" PRIu32
"(%" PRIu32
")",
3211 static bool StreamTcpPacketIsZeroWindowProbeAck(
const TcpSession *ssn,
const Packet *p)
3213 const TCPHdr *tcph = PacketGetTCP(p);
3237 if (pkt_win != rcv->
window)
3251 static bool StreamTcpPacketIsDupAck(
const TcpSession *ssn,
const Packet *p)
3253 const TCPHdr *tcph = PacketGetTCP(p);
3271 if (pkt_win == 0 || rcv->
window == 0)
3273 if (pkt_win != rcv->
window)
3281 SCLogDebug(
"ssn %p: packet:%" PRIu64
" seq:%u ack:%u win:%u snd %u:%u:%u rcv %u:%u:%u", ssn,
3305 const TCPHdr *tcph = PacketGetTCP(p);
3356 static int StreamTcpPacketIsSpuriousRetransmission(
const TcpSession *ssn,
Packet *p)
3367 const TCPHdr *tcph = PacketGetTCP(p);
3373 "ssn %p: spurious retransmission; packet entirely before base_seq: SEQ %u(%u) "
3374 "last_ack %u base_seq %u",
3383 SCLogDebug(
"ssn %p: spurious retransmission; packet entirely before last_ack: SEQ %u(%u) "
3391 SCLogDebug(
"ssn %p: NOT spurious retransmission; packet NOT entirely before last_ack: SEQ "
3392 "%u(%u) last_ack %u, base_seq %u",
3409 static int StreamTcpPacketStateEstablished(
3413 const TCPHdr *tcph = PacketGetTCP(p);
3419 if (!StreamTcpValidateRst(ssn, p))
3423 StreamTcpCloseSsnWithReset(p, ssn);
3427 SCLogDebug(
"ssn %p: ssn->server.next_seq %" PRIu32
"", ssn,
3437 StreamTcpHandleTimestamp(ssn, p);
3441 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3449 StreamTcpCloseSsnWithReset(p, ssn);
3454 SCLogDebug(
"ssn %p: ssn->server.next_seq %" PRIu32
"", ssn,
3464 StreamTcpHandleTimestamp(ssn, p);
3468 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3479 if (!StreamTcpValidateTimestamp(ssn, p))
3484 " %" PRIu32
", last ACK %" PRIu32
", next win %"PRIu32
","
3489 if ((StreamTcpHandleFin(
tv, stt, ssn, p)) == -1)
3494 SCLogDebug(
"ssn %p: SYN/ACK packet on state ESTABLISHED... resent",
3498 SCLogDebug(
"ssn %p: SYN/ACK-pkt to server in ESTABLISHED state", ssn);
3507 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
3508 "%" PRIu32
" from stream",
3518 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
3519 "%" PRIu32
" from stream",
3532 SCLogDebug(
"ssn %p: SYN/ACK packet on state ESTABLISHED... resent. "
3533 "Likely due server not receiving final ACK in 3whs", ssn);
3537 SCLogDebug(
"ssn %p: SYN packet on state ESTABLISHED... resent", ssn);
3539 SCLogDebug(
"ssn %p: SYN-pkt to client in EST state", ssn);
3546 SCLogDebug(
"ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
3567 if (!StreamTcpValidateTimestamp(ssn, p))
3573 HandleEstablishedPacketToServer(
tv, ssn, p, stt);
3575 SCLogDebug(
"ssn %p: next SEQ %" PRIu32
", last ACK %" PRIu32
","
3576 " next win %" PRIu32
", win %" PRIu32
"", ssn,
3583 SCLogDebug(
"3whs is now confirmed by server");
3587 HandleEstablishedPacketToClient(
tv, ssn, p, stt);
3589 SCLogDebug(
"ssn %p: next SEQ %" PRIu32
", last ACK %" PRIu32
","
3590 " next win %" PRIu32
", win %" PRIu32
"", ssn,
3615 const TCPHdr *tcph = PacketGetTCP(p);
3621 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ %" PRIu32
","
3625 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3626 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3632 SCLogDebug(
"ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn,
seq, pkt_re,
3637 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
" != "
3638 "%" PRIu32
" from stream",
3651 SCLogDebug(
"ssn %p: state changed to TCP_CLOSE_WAIT", ssn);
3656 SCLogDebug(
"ssn %p: ssn->client.next_seq %" PRIu32
"", ssn,
3661 StreamTcpHandleTimestamp(ssn, p);
3674 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK %" PRIu32
"",
3677 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ %" PRIu32
", "
3681 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3682 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3688 SCLogDebug(
"ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn,
seq, pkt_re,
3693 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
" != "
3694 "%" PRIu32
" from stream (last_ack %u win %u = %u)",
3703 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT1", ssn);
3712 StreamTcpHandleTimestamp(ssn, p);
3725 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK %" PRIu32
"",
3745 static int StreamTcpPacketStateFinWait1(
3749 const TCPHdr *tcph = PacketGetTCP(p);
3755 if (!StreamTcpValidateRst(ssn, p))
3758 StreamTcpCloseSsnWithReset(p, ssn);
3767 StreamTcpHandleTimestamp(ssn, p);
3778 StreamTcpHandleTimestamp(ssn, p);
3786 if (!StreamTcpValidateTimestamp(ssn, p))
3791 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3792 "%" PRIu32
", ACK %" PRIu32
"",
3794 int retransmission = 0;
3796 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
3797 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3803 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3804 " != %" PRIu32
" from stream",
3810 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3811 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3816 if (!retransmission) {
3818 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
3824 StreamTcpHandleTimestamp(ssn, p);
3840 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3844 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3845 "%" PRIu32
", ACK %" PRIu32
"",
3847 int retransmission = 0;
3849 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
3850 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3855 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3861 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3862 " != %" PRIu32
" from stream",
3868 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3869 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3875 StreamTcpHandleTimestamp(ssn, p);
3878 if (!retransmission) {
3880 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
3898 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3905 if (!StreamTcpValidateTimestamp(ssn, p))
3910 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3911 "%" PRIu32
", ACK %" PRIu32
"",
3913 int retransmission = 0;
3915 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
3916 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3922 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3923 " != %" PRIu32
" from stream",
3929 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3930 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3935 if (!retransmission) {
3937 SCLogDebug(
"ssn %p: state changed to TCP_CLOSING", ssn);
3943 StreamTcpHandleTimestamp(ssn, p);
3960 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3964 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3965 "%" PRIu32
", ACK %" PRIu32
"",
3968 int retransmission = 0;
3970 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
3971 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3977 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3978 " != %" PRIu32
" from stream",
3984 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3985 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3990 if (!retransmission) {
3992 SCLogDebug(
"ssn %p: state changed to TCP_CLOSING", ssn);
3998 StreamTcpHandleTimestamp(ssn, p);
4015 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4020 SCLogDebug(
"ssn (%p): SYN pkt on FinWait1", ssn);
4026 if (!StreamTcpValidateTimestamp(ssn, p))
4031 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4032 "%" PRIu32
", ACK %" PRIu32
"",
4034 int retransmission = 0;
4036 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4037 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4042 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4043 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4050 "ssn %p: ACK's older segment as %u < %u", ssn, ack, ssn->
server.
next_seq);
4051 }
else if (!retransmission) {
4055 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
4061 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT2", ssn);
4064 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4065 " != %" PRIu32
" from stream",
4077 StreamTcpHandleTimestamp(ssn, p);
4098 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4104 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4105 "%" PRIu32
", ACK %" PRIu32
"",
4108 int retransmission = 0;
4110 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4111 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4116 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4117 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4122 if (!retransmission) {
4125 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
4131 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT2", ssn);
4134 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4135 " != %" PRIu32
" from stream",
4145 StreamTcpHandleTimestamp(ssn, p);
4166 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4187 static int StreamTcpPacketStateFinWait2(
4191 const TCPHdr *tcph = PacketGetTCP(p);
4197 if (!StreamTcpValidateRst(ssn, p))
4200 StreamTcpCloseSsnWithReset(p, ssn);
4209 StreamTcpHandleTimestamp(ssn, p);
4220 StreamTcpHandleTimestamp(ssn, p);
4228 if (!StreamTcpValidateTimestamp(ssn, p))
4233 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4234 "%" PRIu32
", ACK %" PRIu32
"",
4236 int retransmission = 0;
4242 }
else if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4243 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4249 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ "
4250 "%" PRIu32
" != %" PRIu32
" from stream",
4256 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4257 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4262 if (!retransmission) {
4264 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4274 StreamTcpHandleTimestamp(ssn, p);
4287 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4291 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4292 "%" PRIu32
", ACK %" PRIu32
"",
4294 int retransmission = 0;
4300 }
else if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4301 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4307 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ "
4308 "%" PRIu32
" != %" PRIu32
" from stream",
4314 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4315 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4320 if (!retransmission) {
4322 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4328 StreamTcpHandleTimestamp(ssn, p);
4340 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4346 SCLogDebug(
"ssn (%p): SYN pkt on FinWait2", ssn);
4352 if (!StreamTcpValidateTimestamp(ssn, p))
4357 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4358 "%" PRIu32
", ACK %" PRIu32
"",
4360 int retransmission = 0;
4362 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4363 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4368 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4369 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4374 if (!retransmission) {
4377 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
4382 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4383 " != %" PRIu32
" from stream",
4393 StreamTcpHandleTimestamp(ssn, p);
4409 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4413 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4414 "%" PRIu32
", ACK %" PRIu32
"",
4416 int retransmission = 0;
4418 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4419 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4424 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4425 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4430 if (!retransmission) {
4433 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
4437 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4438 " != %" PRIu32
" from stream",
4448 StreamTcpHandleTimestamp(ssn, p);
4464 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4485 static int StreamTcpPacketStateClosing(
4489 const TCPHdr *tcph = PacketGetTCP(p);
4495 if (!StreamTcpValidateRst(ssn, p))
4498 StreamTcpCloseSsnWithReset(p, ssn);
4507 StreamTcpHandleTimestamp(ssn, p);
4518 StreamTcpHandleTimestamp(ssn, p);
4525 SCLogDebug(
"ssn (%p): SYN pkt on Closing", ssn);
4531 if (!StreamTcpValidateTimestamp(ssn, p))
4536 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4537 "%" PRIu32
", ACK %" PRIu32
"",
4539 int retransmission = 0;
4540 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4541 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4547 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4548 " != %" PRIu32
" from stream",
4554 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4555 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4560 if (!retransmission) {
4562 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4568 StreamTcpHandleTimestamp(ssn, p);
4578 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4582 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4583 "%" PRIu32
", ACK %" PRIu32
"",
4585 int retransmission = 0;
4586 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4587 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4593 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4594 " != %" PRIu32
" from stream",
4600 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4601 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4606 if (!retransmission) {
4608 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4614 StreamTcpHandleTimestamp(ssn, p);
4625 SCLogDebug(
"StreamTcpPacketStateClosing (%p): =+ next SEQ "
4626 "%" PRIu32
", last ACK %" PRIu32
"", ssn,
4646 static int StreamTcpPacketStateCloseWait(
4650 const TCPHdr *tcph = PacketGetTCP(p);
4658 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4659 "%" PRIu32
", ACK %" PRIu32
"",
4662 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4663 "%" PRIu32
", ACK %" PRIu32
"",
4668 if (!StreamTcpValidateRst(ssn, p))
4671 StreamTcpCloseSsnWithReset(p, ssn);
4680 StreamTcpHandleTimestamp(ssn, p);
4691 StreamTcpHandleTimestamp(ssn, p);
4699 if (!StreamTcpValidateTimestamp(ssn, p))
4704 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4705 "%" PRIu32
", ACK %" PRIu32
"",
4708 int retransmission = 0;
4709 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4710 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4715 if (!retransmission) {
4718 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4719 " != %" PRIu32
" from stream",
4726 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4727 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4734 if (!retransmission)
4738 StreamTcpHandleTimestamp(ssn, p);
4750 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4754 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4755 "%" PRIu32
", ACK %" PRIu32
"",
4758 int retransmission = 0;
4759 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4760 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4765 if (!retransmission) {
4768 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4769 " != %" PRIu32
" from stream",
4776 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4777 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4782 if (!retransmission) {
4784 SCLogDebug(
"ssn %p: state changed to TCP_LAST_ACK", ssn);
4790 StreamTcpHandleTimestamp(ssn, p);
4802 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4808 SCLogDebug(
"ssn (%p): SYN pkt on CloseWait", ssn);
4814 if (!StreamTcpValidateTimestamp(ssn, p))
4819 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4820 "%" PRIu32
", ACK %" PRIu32
"",
4823 int retransmission = 0;
4824 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4825 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4831 SCLogDebug(
"ssn %p: -> retransmission", ssn);
4836 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4837 " != %" PRIu32
" from stream",
4843 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4844 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4849 if (!retransmission) {
4854 StreamTcpHandleTimestamp(ssn, p);
4868 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4872 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4873 "%" PRIu32
", ACK %" PRIu32
"",
4875 int retransmission = 0;
4876 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4877 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4883 SCLogDebug(
"ssn %p: -> retransmission", ssn);
4888 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4889 " != %" PRIu32
" from stream",
4895 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4896 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4901 if (!retransmission) {
4906 StreamTcpHandleTimestamp(ssn, p);
4920 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4941 static int StreamTcpPacketStateLastAck(
4945 const TCPHdr *tcph = PacketGetTCP(p);
4951 if (!StreamTcpValidateRst(ssn, p))
4954 StreamTcpCloseSsnWithReset(p, ssn);
4963 StreamTcpHandleTimestamp(ssn, p);
4974 StreamTcpHandleTimestamp(ssn, p);
4982 SCLogDebug(
"ssn (%p): FIN pkt on LastAck", ssn);
4985 SCLogDebug(
"ssn (%p): SYN pkt on LastAck", ssn);
4991 if (!StreamTcpValidateTimestamp(ssn, p))
4996 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4997 "%" PRIu32
", ACK %" PRIu32
"",
5000 int retransmission = 0;
5001 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
5002 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
5007 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
5008 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5013 if (!retransmission) {
5015 SCLogDebug(
"ssn %p: not updating state as packet is before next_seq", ssn);
5017 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5018 " != %" PRIu32
" from stream",
5024 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5030 StreamTcpHandleTimestamp(ssn, p);
5041 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5062 static int StreamTcpPacketStateTimeWait(
5066 const TCPHdr *tcph = PacketGetTCP(p);
5072 if (!StreamTcpValidateRst(ssn, p))
5075 StreamTcpCloseSsnWithReset(p, ssn);
5084 StreamTcpHandleTimestamp(ssn, p);
5095 StreamTcpHandleTimestamp(ssn, p);
5105 SCLogDebug(
"ssn (%p): SYN pkt on TimeWait", ssn);
5111 if (!StreamTcpValidateTimestamp(ssn, p))
5116 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
5117 "%" PRIu32
", ACK %" PRIu32
"",
5119 int retransmission = 0;
5120 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
5121 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
5126 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5127 " != %" PRIu32
" from stream",
5133 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
5134 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5139 if (!retransmission) {
5141 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5147 StreamTcpHandleTimestamp(ssn, p);
5158 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5162 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
5163 "%" PRIu32
", ACK %" PRIu32
"",
5165 int retransmission = 0;
5166 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
5167 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
5172 SCLogDebug(
"ssn %p: -> retransmission", ssn);
5175 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5176 " != %" PRIu32
" from stream",
5183 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
5184 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5189 if (!retransmission) {
5191 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5197 StreamTcpHandleTimestamp(ssn, p);
5208 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5220 static int StreamTcpPacketStateClosed(
5225 const TCPHdr *tcph = PacketGetTCP(p);
5231 TcpStream *stream = NULL, *ostream = NULL;
5248 if (StreamTcpStateDispatch(
tv, p, stt, ssn, ssn->
pstate) < 0)
5263 const TCPHdr *tcph = PacketGetTCP(p);
5277 SCLogDebug(
"regular packet %" PRIu64
" from same sender as "
5278 "the previous RST. Looks like it injected!",
5305 const TCPHdr *tcph = PacketGetTCP(p);
5310 TcpStream *stream = NULL, *ostream = NULL;
5321 if (ack == ostream->last_ack &&
seq == (stream->
next_seq - 1)) {
5337 TcpStream *stream = NULL, *ostream = NULL;
5348 const TCPHdr *tcph = PacketGetTCP(p);
5367 if (pkt_win != ostream->window)
5376 SCLogDebug(
"seq %u (%u), ack %u (%u) FLAG_KEEPALIVE: %s",
seq, stream->
next_seq, ack, ostream->last_ack,
5406 TcpStream *stream = NULL, *ostream = NULL;
5420 const TCPHdr *tcph = PacketGetTCP(p);
5439 if (pkt_win == ostream->window)
5442 if (ack == ostream->last_ack &&
seq == stream->
next_seq) {
5457 TcpStream *stream = NULL, *ostream = NULL;
5465 const TCPHdr *tcph = PacketGetTCP(p);
5482 SCLogDebug(
"%" PRIu64
", seq %u ack %u stream->next_seq %u ostream->next_seq %u",
5510 TcpStream *stream = NULL, *ostream = NULL;
5521 const TCPHdr *tcph = PacketGetTCP(p);
5537 if (pkt_win < ostream->window) {
5538 uint32_t diff = ostream->window - pkt_win;
5540 SEQ_GT(ack, ostream->next_seq) &&
5543 SCLogDebug(
"%" PRIu64
", pkt_win %u, stream win %u, diff %u, dsize %u",
5547 SCLogDebug(
"%" PRIu64
", seq %u ack %u ostream->next_seq %u ostream->last_ack %u, "
5548 "ostream->next_win %u, diff %u (%u)",
5550 ostream->next_win, ostream->next_seq - ostream->last_ack,
5558 uint32_t adiff = ack - ostream->last_ack;
5559 if (((pkt_win > 1024) && (diff > (adiff + 32))) ||
5560 ((pkt_win <= 1024) && (diff > adiff)))
5562 SCLogDebug(
"pkt ACK %u is %u bytes beyond last_ack %u, shrinks window by %u "
5563 "(allowing 32 bytes extra): pkt WIN %u", ack, adiff, ostream->last_ack, diff, pkt_win);
5564 SCLogDebug(
"%u - %u = %u (state %u)", diff, adiff, diff - adiff, ssn->
state);
5579 static inline int StreamTcpStateDispatch(
5587 SCLogDebug(
"packet received on TCP_SYN_SENT state");
5588 if (StreamTcpPacketStateSynSent(
tv, p, stt, ssn)) {
5593 SCLogDebug(
"packet received on TCP_SYN_RECV state");
5594 if (StreamTcpPacketStateSynRecv(
tv, p, stt, ssn)) {
5599 SCLogDebug(
"packet received on TCP_ESTABLISHED state");
5600 if (StreamTcpPacketStateEstablished(
tv, p, stt, ssn)) {
5605 SCLogDebug(
"packet received on TCP_FIN_WAIT1 state");
5606 if (StreamTcpPacketStateFinWait1(
tv, p, stt, ssn)) {
5611 SCLogDebug(
"packet received on TCP_FIN_WAIT2 state");
5612 if (StreamTcpPacketStateFinWait2(
tv, p, stt, ssn)) {
5617 SCLogDebug(
"packet received on TCP_CLOSING state");
5618 if (StreamTcpPacketStateClosing(
tv, p, stt, ssn)) {
5623 SCLogDebug(
"packet received on TCP_CLOSE_WAIT state");
5624 if (StreamTcpPacketStateCloseWait(
tv, p, stt, ssn)) {
5629 SCLogDebug(
"packet received on TCP_LAST_ACK state");
5630 if (StreamTcpPacketStateLastAck(
tv, p, stt, ssn)) {
5635 SCLogDebug(
"packet received on TCP_TIME_WAIT state");
5636 if (StreamTcpPacketStateTimeWait(
tv, p, stt, ssn)) {
5642 SCLogDebug(
"packet received on closed state");
5644 if (StreamTcpPacketStateClosed(
tv, p, stt, ssn)) {
5650 SCLogDebug(
"packet received on default state");
5686 const TCPHdr *tcph = PacketGetTCP(p);
5701 SCLogDebug(
"ssn %p: removing ASYNC flag as we have packets on both sides", ssn);
5721 if (StreamTcpCheckFlowDrops(p) == 1) {
5731 if (StreamTcpPacketStateNone(
tv, p, stt, ssn) == -1) {
5757 if (StreamTcpPacketIsKeepAlive(ssn, p) == 1) {
5760 if (StreamTcpPacketIsKeepAliveACK(ssn, p) == 1) {
5761 StreamTcpClearKeepAliveFlag(ssn, p);
5764 StreamTcpClearKeepAliveFlag(ssn, p);
5766 const bool is_zwp_ack = StreamTcpPacketIsZeroWindowProbeAck(ssn, p);
5777 if (StreamTcpPacketIsDupAck(ssn, p)) {
5784 if (StreamTcpPacketIsFinShutdownAck(ssn, p) == 0) {
5785 if (StreamTcpPacketIsWindowUpdate(ssn, p) == 0) {
5786 if (StreamTcpPacketIsBadWindowUpdate(ssn,p))
5788 if (StreamTcpPacketIsOutdatedAck(ssn, p))
5793 int ret = StreamTcpPacketIsSpuriousRetransmission(ssn, p);
5802 if (StreamTcpStateDispatch(
tv, p, stt, ssn, ssn->
state) < 0)
5806 StreamTcpPacketCheckPostRst(ssn, p);
5851 SCLogDebug(
"bypass as stream is dead and we have no rules");
5864 if (StreamTcpInlineDropInvalid()) {
5868 DecodeSetNoPayloadInspectionFlag(p);
5882 static inline int StreamTcpValidateChecksum(
Packet *p)
5890 const TCPHdr *tcph = PacketGetTCP(p);
5891 if (PacketIsIPv4(p)) {
5892 const IPV4Hdr *ip4h = PacketGetIPv4(p);
5893 p->
l4.
csum = TCPChecksum(ip4h->s_ip_addrs, (uint16_t *)tcph,
5896 }
else if (PacketIsIPv6(p)) {
5897 const IPV6Hdr *ip6h = PacketGetIPv6(p);
5898 p->
l4.
csum = TCPV6Checksum(ip6h->s_ip6_addrs, (uint16_t *)tcph,
5919 static int TcpSessionPacketIsStreamStarter(
const Packet *p)
5921 const TCPHdr *tcph = PacketGetTCP(p);
5934 SCLogDebug(
"packet %" PRIu64
" is a midstream stream starter: %02x",
5945 static bool TcpSessionReuseDoneEnoughSyn(
const Packet *p,
const Flow *f,
const TcpSession *ssn)
5947 const TCPHdr *tcph = PacketGetTCP(p);
5952 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p null. Reuse.",
5958 ", ssn %p. STREAMTCP_FLAG_TFO_DATA_IGNORED set. Reuse.",
5964 ", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.",
5970 ", ssn %p state >= TCP_LAST_ACK (%u). Reuse.",
5974 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.",
5979 ", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.",
5986 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p null. Reuse.",
5992 ", ssn %p state >= TCP_LAST_ACK (%u). Reuse.",
5996 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.",
6001 ", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.",
6015 static bool TcpSessionReuseDoneEnoughSynAck(
const Packet *p,
const Flow *f,
const TcpSession *ssn)
6017 const TCPHdr *tcph = PacketGetTCP(p);
6020 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p null. No reuse.",
6026 ", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.",
6032 ", ssn %p state >= TCP_LAST_ACK (%u). Reuse.",
6036 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.",
6041 ", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.",
6048 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p null. Reuse.",
6054 ", ssn %p state >= TCP_LAST_ACK (%u). Reuse.",
6058 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.",
6063 ", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.",
6080 const TCPHdr *tcph = PacketGetTCP(p);
6082 return TcpSessionReuseDoneEnoughSyn(p, f, ssn);
6087 return TcpSessionReuseDoneEnoughSynAck(p, f, ssn);
6096 if (p->
proto == IPPROTO_TCP && PacketIsTCP(p)) {
6097 if (TcpSessionPacketIsStreamStarter(p) == 1) {
6098 if (TcpSessionReuseDoneEnough(p, f, tcp_ssn) == 1) {
6124 if (!(PacketIsTCP(p))) {
6128 CheckThreadId(
tv, p, stt);
6134 if (StreamTcpValidateChecksum(p) == 0) {
6156 *data = (
void *)stt;
6165 IsStreamTcpSessionMemcapExceptionPolicyStatsValid);
6173 "exception_policy.tcp.midstream.", IsMidstreamExceptionPolicyStatsValid);
6177 "exception_policy.tcp.midstream.", IsMidstreamExceptionPolicyStatsValid);
6193 "exception_policy.tcp.reassembly.", IsReassemblyMemcapExceptionPolicyStatsValid);
6212 SCLogDebug(
"StreamTcp thread specific ctx online at %p, reassembly ctx %p",
6221 StreamTcpSessionPoolAlloc,
6222 StreamTcpSessionPoolInit, NULL,
6223 StreamTcpSessionPoolCleanup, NULL);
6233 SCLogError(
"failed to setup/expand stream session pool. Expand stream.memcap?");
6278 const TCPHdr *tcph = PacketGetTCP(p);
6286 if (!StreamTcpValidateTimestamp(ssn, p)) {
6315 StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
6316 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
6328 StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
6329 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
6342 receiver_stream = &ssn->
server;
6344 receiver_stream = &ssn->
client;
6346 SCLogDebug(
"ssn %p: setting STREAMTCP_STREAM_FLAG_RST_RECV on receiver stream", ssn);
6366 switch (os_policy) {
6373 SCLogDebug(
"reset is not Valid! Packet SEQ: %" PRIu32
" "
6374 "and server SEQ: %" PRIu32
"",
6383 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" "
6384 "and client SEQ: %" PRIu32
"",
6401 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6402 " server SEQ: %" PRIu32
"",
6414 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6415 " client SEQ: %" PRIu32
"",
6436 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" "
6437 "and server SEQ: %" PRIu32
"",
6443 SCLogDebug(
"reset is valid! Packet SEQ: %" PRIu32
" Stream %u",
seq,
6447 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6448 " client SEQ: %" PRIu32
"",
6479 uint8_t check_ts = 1;
6480 const TCPHdr *tcph = PacketGetTCP(p);
6484 sender_stream = &ssn->
client;
6485 receiver_stream = &ssn->
server;
6487 sender_stream = &ssn->
server;
6488 receiver_stream = &ssn->
client;
6499 uint32_t last_pkt_ts = sender_stream->
last_pkt_ts;
6500 uint32_t last_ts = sender_stream->
last_ts;
6550 SCLogDebug(
"ts %"PRIu32
", last_ts %"PRIu32
"",
ts, last_ts);
6554 result = (int32_t) ((
ts - last_ts) + 1);
6556 result = (int32_t) (
ts - last_ts);
6559 SCLogDebug(
"result %" PRIi32
", p->ts(secs) %" PRIuMAX
"", result,
6562 if (last_pkt_ts == 0 &&
6570 "%" PRIu32
" p->tcpvars->ts %" PRIu32
" result "
6571 "%" PRId32
"", last_ts,
ts, result);
6574 }
else if ((sender_stream->
last_ts != 0) &&
6576 SCLogDebug(
"packet is not valid last_pkt_ts "
6577 "%" PRIu32
" p->ts(sec) %" PRIu32
"",
6589 SCLogDebug(
"timestamp considered valid anyway");
6621 uint8_t check_ts = 1;
6622 const TCPHdr *tcph = PacketGetTCP(p);
6626 sender_stream = &ssn->
client;
6627 receiver_stream = &ssn->
server;
6629 sender_stream = &ssn->
server;
6630 receiver_stream = &ssn->
client;
6698 result = (int32_t) ((
ts - sender_stream->
last_ts) + 1);
6700 result = (int32_t) (
ts - sender_stream->
last_ts);
6703 SCLogDebug(
"result %" PRIi32
", p->ts(sec) %" PRIuMAX
"", result,
6713 SCLogDebug(
"timestamp is not valid sender_stream->last_ts "
6714 "%" PRIu32
" p->tcpvars->ts %" PRIu32
" result "
6715 "%" PRId32
"", sender_stream->
last_ts,
ts, result);
6718 }
else if ((sender_stream->
last_ts != 0) &&
6721 SCLogDebug(
"packet is not valid sender_stream->last_pkt_ts "
6722 "%" PRIu32
" p->ts(sec) %" PRIu32
"",
6736 }
else if (ret == 0) {
6746 SCLogDebug(
"timestamp considered valid anyway");
6782 const TCPHdr *tcph = PacketGetTCP(p);
6797 SCLogDebug(
"ssn %p: pkt ACK %" PRIu32
" == stream last ACK %" PRIu32, ssn, ack,
6810 SCLogDebug(
"ACK %"PRIu32
" is before last_ack %"PRIu32
" - window "
6811 "%"PRIu32
" = %"PRIu32, ack, stream->
last_ack,
6834 SCLogDebug(
"default path leading to invalid: ACK %"PRIu32
", last_ack %"PRIu32
6847 const uint32_t progress)
6901 static void StreamTcpPseudoPacketCreateDetectLogFlush(
ThreadVars *
tv,
6924 np->
proto = IPPROTO_TCP;
6925 FlowReference(&np->
flow, f);
6935 DecodeSetNoPacketInspectionFlag(np);
6938 DecodeSetNoPayloadInspectionFlag(np);
6978 ip4h->
ip_len = htons(40);
6984 ip4h->s_ip_src.s_addr = f->
src.addr_data32[0];
6985 ip4h->s_ip_dst.s_addr = f->
dst.addr_data32[0];
6987 ip4h->s_ip_src.s_addr = f->
dst.addr_data32[0];
6988 ip4h->s_ip_dst.s_addr = f->
src.addr_data32[0];
7021 ip6h->s_ip6_vfc = 0x60;
7022 ip6h->s_ip6_flow = 0;
7023 ip6h->s_ip6_nxt = IPPROTO_TCP;
7024 ip6h->s_ip6_plen = htons(20);
7025 ip6h->s_ip6_hlim = 64;
7027 ip6h->s_ip6_src[0] = f->
src.addr_data32[0];
7028 ip6h->s_ip6_src[1] = f->
src.addr_data32[1];
7029 ip6h->s_ip6_src[2] = f->
src.addr_data32[2];
7030 ip6h->s_ip6_src[3] = f->
src.addr_data32[3];
7031 ip6h->s_ip6_dst[0] = f->
dst.addr_data32[0];
7032 ip6h->s_ip6_dst[1] = f->
dst.addr_data32[1];
7033 ip6h->s_ip6_dst[2] = f->
dst.addr_data32[2];
7034 ip6h->s_ip6_dst[3] = f->
dst.addr_data32[3];
7036 ip6h->s_ip6_src[0] = f->
dst.addr_data32[0];
7037 ip6h->s_ip6_src[1] = f->
dst.addr_data32[1];
7038 ip6h->s_ip6_src[2] = f->
dst.addr_data32[2];
7039 ip6h->s_ip6_src[3] = f->
dst.addr_data32[3];
7040 ip6h->s_ip6_dst[0] = f->
src.addr_data32[0];
7041 ip6h->s_ip6_dst[1] = f->
src.addr_data32[1];
7042 ip6h->s_ip6_dst[2] = f->
src.addr_data32[2];
7043 ip6h->s_ip6_dst[3] = f->
src.addr_data32[3];
7075 np->
ts = parent->
ts;
7083 FlowDeReference(&np->
flow);
7102 StreamTcpPseudoPacketCreateDetectLogFlush(
tv, stt, p, ssn, pq,
ts^0);
7103 StreamTcpPseudoPacketCreateDetectLogFlush(
tv, stt, p, ssn, pq,
ts^1);
7123 if (p->
flow == NULL)
7151 const uint8_t *seg_data;
7152 uint32_t seg_datalen;
7155 int ret = CallbackFunc(p, seg, data, seg_data, seg_datalen);
7183 if (p->
flow == NULL)
7197 if (server_node == NULL && client_node == NULL) {
7201 while (server_node != NULL || client_node != NULL) {
7202 const uint8_t *seg_data;
7203 uint32_t seg_datalen;
7204 if (server_node == NULL) {
7211 &client_stream->
sb, &client_node->
sbseg, &seg_data, &seg_datalen);
7212 ret = CallbackFunc(p, client_node, data, seg_data, seg_datalen);
7217 client_node = TCPSEG_RB_NEXT(client_node);
7218 }
else if (client_node == NULL) {
7225 &server_stream->
sb, &server_node->
sbseg, &seg_data, &seg_datalen);
7226 ret = CallbackFunc(p, server_node, data, seg_data, seg_datalen);
7231 server_node = TCPSEG_RB_NEXT(server_node);
7236 &client_stream->
sb, &client_node->
sbseg, &seg_data, &seg_datalen);
7237 ret = CallbackFunc(p, client_node, data, seg_data, seg_datalen);
7242 client_node = TCPSEG_RB_NEXT(client_node);
7245 &server_stream->
sb, &server_node->
sbseg, &seg_data, &seg_datalen);
7246 ret = CallbackFunc(p, server_node, data, seg_data, seg_datalen);
7251 server_node = TCPSEG_RB_NEXT(server_node);
7286 const char *tcp_state = NULL;
7292 tcp_state =
"syn_sent";
7295 tcp_state =
"syn_recv";
7298 tcp_state =
"established";
7301 tcp_state =
"fin_wait1";
7304 tcp_state =
"fin_wait2";
7307 tcp_state =
"time_wait";
7310 tcp_state =
"last_ack";
7313 tcp_state =
"close_wait";
7316 tcp_state =
"closing";
7319 tcp_state =
"closed";