Go to the documentation of this file.
83 #define STREAMTCP_DEFAULT_PREALLOC 2048
84 #define STREAMTCP_DEFAULT_MEMCAP (64 * 1024 * 1024)
85 #define STREAMTCP_DEFAULT_REASSEMBLY_MEMCAP (256 * 1024 * 1024)
86 #define STREAMTCP_DEFAULT_TOSERVER_CHUNK_SIZE 2560
87 #define STREAMTCP_DEFAULT_TOCLIENT_CHUNK_SIZE 2560
88 #define STREAMTCP_DEFAULT_MAX_SYN_QUEUED 10
89 #define STREAMTCP_DEFAULT_MAX_SYNACK_QUEUED 5
91 #define STREAM_DEPTH_DEFAULT 1024 * 1024
107 .valid_settings_ips = {
135 .valid_settings_ips = {
163 .valid_settings_ips = {
191 .valid_settings_ips = {
215 static int StreamTcpStateDispatch(
222 #if defined(DEBUG) || defined(QA_SIMULATION)
223 static uint64_t ssn_pool_cnt = 0;
224 extern thread_local uint64_t t_pcapcnt;
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) {
344 StreamTcp3wsFreeQueue(
ssn);
405 static void *StreamTcpSessionPoolAlloc(
void)
419 static int StreamTcpSessionPoolInit(
void *data)
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;
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;
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 (
SCConfGetNonNull(
"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 (
SCConfGetNonNull(
"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 (
SCConfGetNonNull(
"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;
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;
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");
857 StreamTcpSessionPoolInit, StreamTcpSessionPoolCleanup);
876 SCLogDebug(
"ssn_pool_cnt %"PRIu64
"", ssn_pool_cnt);
879 static bool IsReassemblyMemcapExceptionPolicyStatsValid(
enum ExceptionPolicy exception_policy)
887 static bool IsStreamTcpSessionMemcapExceptionPolicyStatsValid(
enum ExceptionPolicy policy)
895 static void StreamTcpSsnMemcapExceptionPolicyStatsIncr(
948 #if defined(DEBUG) || defined(QA_SIMULATION)
954 if (
unlikely((g_eps_stream_ssn_memcap != UINT64_MAX &&
955 g_eps_stream_ssn_memcap == t_pcapcnt))) {
956 SCLogNotice(
"simulating memcap reached condition for packet %" PRIu64, t_pcapcnt);
971 const TCPHdr *tcph = PacketGetTCP(
p);
1030 if (PacketIsIPv4(
p)) {
1040 }
else if (PacketIsIPv6(
p)) {
1077 static inline bool StreamTcpBaseSeqBoundsAck(
const TcpStream *stream)
1079 return (stream->
flags &
1090 #define StreamTcpUpdateLastAck(ssn, stream, ack) \
1092 if (SEQ_GT((ack), (stream)->last_ack) && \
1093 (!StreamTcpBaseSeqBoundsAck(stream) || SEQ_GT(ack, (stream)->base_seq))) { \
1094 SCLogDebug("ssn %p: last_ack set to %" PRIu32 ", moved %u forward", (ssn), (ack), \
1095 (ack) - (stream)->last_ack); \
1096 if ((SEQ_LEQ((stream)->last_ack, (stream)->next_seq) && \
1097 SEQ_GT((ack), (stream)->next_seq))) { \
1098 SCLogDebug("last_ack just passed next_seq: %u (was %u) > %u", (ack), \
1099 (stream)->last_ack, (stream)->next_seq); \
1101 SCLogDebug("next_seq (%u) <> last_ack now %d", (stream)->next_seq, \
1102 (int)(stream)->next_seq - (ack)); \
1104 (stream)->last_ack = (ack); \
1105 StreamTcpSackPruneList((stream)); \
1107 SCLogDebug("ssn %p: no update: ack %u, last_ack %" PRIu32 ", next_seq %u (state %u)", \
1108 (ssn), (ack), (stream)->last_ack, (stream)->next_seq, (ssn)->state); \
1112 #define StreamTcpAsyncLastAckUpdate(ssn, stream) { \
1113 if ((ssn)->flags & STREAMTCP_FLAG_ASYNC) { \
1114 if (SEQ_GT((stream)->next_seq, (stream)->last_ack)) { \
1115 uint32_t ack_diff = (stream)->next_seq - (stream)->last_ack; \
1116 (stream)->last_ack += ack_diff; \
1117 SCLogDebug("ssn %p: ASYNC last_ack set to %"PRIu32", moved %u forward", \
1118 (ssn), (stream)->next_seq, ack_diff); \
1123 #define StreamTcpUpdateNextSeq(ssn, stream, seq) { \
1124 (stream)->next_seq = seq; \
1125 SCLogDebug("ssn %p: next_seq %" PRIu32, (ssn), (stream)->next_seq); \
1126 StreamTcpAsyncLastAckUpdate((ssn), (stream)); \
1136 #define StreamTcpUpdateNextWin(ssn, stream, win) { \
1137 uint32_t sacked_size__ = StreamTcpSackedSize((stream)); \
1138 if (SEQ_GT(((win) + sacked_size__), (stream)->next_win)) { \
1139 (stream)->next_win = ((win) + sacked_size__); \
1140 SCLogDebug("ssn %p: next_win set to %"PRIu32, (ssn), (stream)->next_win); \
1148 SCLogDebug(
"ssn %p: (state: %s) Reset received and state changed to "
1152 static bool IsMidstreamExceptionPolicyStatsValid(
enum ExceptionPolicy policy)
1166 static void StreamTcpMidstreamExceptionPolicyStatsIncr(
1180 const TCPHdr *tcph = PacketGetTCP(
p);
1218 static int StreamTcpPacketStateNone(
1221 const TCPHdr *tcph = PacketGetTCP(
p);
1224 SCLogDebug(
"RST packet received, no session setup");
1234 SCLogDebug(
"FIN packet received, no session setup");
1240 SCLogDebug(
"FIN packet received, no session setup");
1257 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1289 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
", "
1290 "ssn->server.next_win %" PRIu32
"",
1292 SCLogDebug(
"ssn %p: ssn->client.last_ack %" PRIu32
", "
1293 "ssn->server.last_ack %" PRIu32
"",
1301 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1302 "ssn->client.last_ts %" PRIu32
"",
1321 SCLogDebug(
"ssn %p: assuming SACK permitted for both sides",
ssn);
1330 SCLogDebug(
"Midstream not enabled, so won't pick up a session");
1335 SCLogDebug(
"Midstream policy not permissive, so won't pick up a session");
1358 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1359 "TCP_SYN_RECV",
ssn);
1390 SCLogDebug(
"ssn %p: wscale enabled. client %u server %u",
1394 SCLogDebug(
"ssn %p: ssn->client.isn %"PRIu32
", ssn->client.next_seq"
1395 " %"PRIu32
", ssn->client.last_ack %"PRIu32
"",
ssn,
1398 SCLogDebug(
"ssn %p: ssn->server.isn %"PRIu32
", ssn->server.next_seq"
1399 " %"PRIu32
", ssn->server.last_ack %"PRIu32
"",
ssn,
1408 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1409 "ssn->client.last_ts %" PRIu32
"",
ssn,
1427 SCLogDebug(
"ssn %p: SYN/ACK with SACK permitted, assuming "
1428 "SACK permitted for both sides",
ssn);
1446 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_SYN_SENT",
ssn);
1486 SCLogDebug(
"ssn: %p (TFO) isn %u base_seq %u next_seq %u payload len %u",
ssn,
1494 SCLogDebug(
"ssn %p: ssn->client.isn %" PRIu32
", "
1495 "ssn->client.next_seq %" PRIu32
", ssn->client.last_ack "
1505 SCLogDebug(
"Midstream not enabled, so won't pick up a session");
1510 SCLogDebug(
"Midstream policy not permissive, so won't pick up a session");
1527 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1528 "TCP_ESTABLISHED",
ssn);
1549 SCLogDebug(
"ssn %p: ssn->client.isn %u, ssn->client.next_seq %u",
1558 SCLogDebug(
"ssn %p: ssn->client.next_win %"PRIu32
", "
1559 "ssn->server.next_win %"PRIu32
"",
ssn,
1561 SCLogDebug(
"ssn %p: ssn->client.last_ack %"PRIu32
", "
1562 "ssn->server.last_ack %"PRIu32
"",
ssn,
1570 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1571 "ssn->client.last_ts %" PRIu32
"",
ssn,
1590 SCLogDebug(
"ssn %p: assuming SACK permitted for both sides",
ssn);
1604 const TCPHdr *tcph = PacketGetTCP(
p);
1634 StreamTcp3whsSynAckToStateQueue(
p, &search);
1642 search.
ts == q->
ts) {
1655 if (StreamTcp3whsFindSynAckBySynAck(
ssn,
p) != NULL)
1665 SCLogDebug(
"ssn %p: =~ SYN/ACK queue failed: stream memcap reached",
ssn);
1671 SCLogDebug(
"ssn %p: =~ SYN/ACK queue failed: alloc failed",
ssn);
1676 StreamTcp3whsSynAckToStateQueue(
p, q);
1690 const TCPHdr *tcph = PacketGetTCP(
p);
1725 StreamTcp3whsSynAckToStateQueue(
p, &update);
1732 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_SYN_RECV",
ssn);
1748 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1749 "ssn->client.last_ts %" PRIu32
"",
ssn,
1788 SCLogDebug(
"ssn %p: ssn->server.isn %" PRIu32
", "
1789 "ssn->server.next_seq %" PRIu32
", "
1790 "ssn->server.last_ack %" PRIu32
" "
1791 "(ssn->client.last_ack %" PRIu32
")",
ssn,
1798 SCLogDebug(
"ssn %p: STREAMTCP_FLAG_4WHS unset, normal SYN/ACK"
1799 " so considering 3WHS",
ssn);
1820 if (receiver_stream->
last_ts != 0 && ts_echo != 0 &&
1821 ts_echo != receiver_stream->
last_ts)
1824 ts_echo, receiver_stream->
last_ts);
1828 if (receiver_stream->
last_ts == 0 && ts_echo != 0) {
1830 ts_echo, receiver_stream->
last_ts);
1840 memset(q, 0,
sizeof(*q));
1867 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1871 memset(q, 0,
sizeof(*q));
1872 const TCPHdr *tcph = PacketGetTCP(
p);
1898 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1902 memset(q, 0,
sizeof(*q));
1904 const TCPHdr *tcph = PacketGetTCP(
p);
1938 SCLogDebug(
"ssn %p: search state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u",
ssn, s, s->
seq, s->
win,
1943 SCLogDebug(
"ssn %p: queue state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u (last:%s)",
ssn, q,
1951 }
else if (ignore_ts) {
1970 if (
tail == old_head) {
1972 *old_head = *search;
1973 old_head->
next = NULL;
1979 tail->next = old_head;
1981 *old_head = *search;
1982 old_head->
next = NULL;
1988 TcpStateQueueInitFromSsnSyn(
ssn, &search);
1992 if (
ssn->
queue != NULL && StreamTcp3whsFindSyn(
ssn, &search, &
tail,
false) != NULL)
2001 AddAndRotate(
ssn,
tail, &search);
2006 SCLogDebug(
"ssn %p: =~ SYN queue failed: stream memcap reached",
ssn);
2012 SCLogDebug(
"ssn %p: =~ SYN queue failed: alloc failed",
ssn);
2066 static inline bool StateSynSentCheckSynAck3Whs(
TcpSession *
ssn,
Packet *
p,
const bool ts_mismatch)
2068 const TCPHdr *tcph = PacketGetTCP(
p);
2070 if (seq_match && !ts_mismatch) {
2080 TcpStateQueueInitFromPktSynAck(
p, &search);
2091 SCLogDebug(
"ssn %p: found queued SYN state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u",
ssn, q,
2093 StreamTcp3whsStoreSynApplyToSsn(
ssn, q);
2098 }
else if (ts_mismatch) {
2112 static inline bool StateSynSentCheckSynAckTFO(
TcpSession *
ssn,
Packet *
p,
const bool ts_mismatch)
2114 const TCPHdr *tcph = PacketGetTCP(
p);
2117 if (seq_match_tfo && !ts_mismatch) {
2119 }
else if (seq_match_nodata && !ts_mismatch) {
2131 TcpStateQueueInitFromPktSynAck(
p, &search);
2142 SCLogDebug(
"ssn %p: found queued SYN state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u",
ssn, q,
2144 StreamTcp3whsStoreSynApplyToSsn(
ssn, q);
2149 if (!seq_match_tfo && !seq_match_nodata) {
2151 }
else if (ts_mismatch) {
2167 static int StreamTcpPacketStateSynSent(
2171 const TCPHdr *tcph = PacketGetTCP(
p);
2177 SCLogDebug(
"%" PRIu64
": ssn %p: SYN/ACK on SYN_SENT state for packet %" PRIu64,
2181 const bool ts_mismatch =
2186 if (StateSynSentCheckSynAck3Whs(
ssn,
p, ts_mismatch)) {
2187 SCLogDebug(
"ssn %p: ACK match, packet ACK %" PRIu32
" == "
2188 "%" PRIu32
" from stream",
2191 SCLogDebug(
"ssn %p: (3WHS) ACK mismatch, packet ACK %" PRIu32
" != "
2192 "%" PRIu32
" from stream",
2197 if (StateSynSentCheckSynAckTFO(
ssn,
p, ts_mismatch)) {
2198 SCLogDebug(
"ssn %p: (TFO) ACK matches next_seq, packet ACK %" PRIu32
" == "
2199 "%" PRIu32
" from stream",
2202 SCLogDebug(
"ssn %p: (TFO) ACK mismatch, packet ACK %" PRIu32
" != "
2203 "%" PRIu32
" from stream",
2209 StreamTcp3wsFreeQueue(
ssn);
2211 StreamTcp3whsSynAckUpdate(
ssn,
p, NULL);
2220 SCLogDebug(
"ssn %p: SYN/ACK received in the wrong direction",
ssn);
2224 SCLogDebug(
"ssn %p: SYN/ACK received on 4WHS session",
ssn);
2231 SCLogDebug(
"ssn %p: 4WHS ACK mismatch, packet ACK %" PRIu32
""
2232 " != %" PRIu32
" from stream",
2242 SCLogDebug(
"ssn %p: 4WHS SEQ mismatch, packet SEQ %" PRIu32
""
2243 " != %" PRIu32
" from *first* SYN pkt",
2250 SCLogDebug(
"ssn %p: =~ 4WHS ssn state is now TCP_SYN_RECV",
ssn);
2264 SCLogDebug(
"ssn %p: 4WHS ssn->client.last_ts %" PRIu32
" "
2265 "ssn->server.last_ts %" PRIu32
"",
2297 SCLogDebug(
"ssn %p: 4WHS ssn->client.isn %" PRIu32
", "
2298 "ssn->client.next_seq %" PRIu32
", "
2299 "ssn->client.last_ack %" PRIu32
" "
2300 "(ssn->server.last_ack %" PRIu32
")",
2309 if (!StateSynSentValidateTimestamp(
ssn,
p)) {
2317 if (!StreamTcpValidateRst(
ssn,
p))
2324 SCLogDebug(
"ssn->server.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2326 StreamTcpCloseSsnWithReset(
p,
ssn);
2327 StreamTcp3wsFreeQueue(
ssn);
2331 SCLogDebug(
"ssn->client.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2332 StreamTcpCloseSsnWithReset(
p,
ssn);
2333 StreamTcp3wsFreeQueue(
ssn);
2341 SCLogDebug(
"ssn %p: SYN packet on state SYN_SENT... resent",
ssn);
2343 SCLogDebug(
"ssn %p: SYN packet on state SYN_SENT... resent of "
2393 SCLogDebug(
"ssn %p: 4WHS ssn->server.isn %" PRIu32
", "
2394 "ssn->server.next_seq %" PRIu32
", "
2395 "ssn->server.last_ack %"PRIu32
"",
ssn,
2398 SCLogDebug(
"ssn %p: 4WHS ssn->client.isn %" PRIu32
", "
2399 "ssn->client.next_seq %" PRIu32
", "
2400 "ssn->client.last_ack %"PRIu32
"",
ssn,
2409 TcpStateQueueInitFromPktSyn(
p, &syn_pkt);
2410 TcpStateQueueInitFromSsnSyn(
ssn, &syn_ssn);
2412 if (memcmp(&syn_pkt, &syn_ssn,
sizeof(
TcpStateQueue)) != 0) {
2414 StreamTcp3whsStoreSyn(
ssn,
p);
2415 SCLogDebug(
"ssn %p: Retransmitted SYN. Updating ssn from packet %" PRIu64
2416 ". Stored previous state",
2419 StreamTcp3whsStoreSynApplyToSsn(
ssn, &syn_pkt);
2435 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
2436 "%" PRIu32
" from stream",
2443 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED",
ssn);
2444 StreamTcp3wsFreeQueue(
ssn);
2457 SCLogDebug(
"ssn %p: synsent => Asynchronous stream, packet SEQ"
2458 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2459 "ssn->client.next_seq %" PRIu32
"",
2508 static int StreamTcpPacketStateSynRecv(
2512 const TCPHdr *tcph = PacketGetTCP(
p);
2515 if (!StreamTcpValidateRst(
ssn,
p))
2532 SCLogDebug(
"Detection evasion has been attempted, so"
2533 " not resetting the connection !!");
2541 SCLogDebug(
"Detection evasion has been attempted, so"
2542 " not resetting the connection !!");
2548 StreamTcpCloseSsnWithReset(
p,
ssn);
2551 StreamTcpHandleTimestamp(
ssn,
p);
2558 if (!StreamTcpValidateTimestamp(
ssn,
p))
2562 if ((StreamTcpHandleFin(
tv, stt,
ssn,
p)) == -1)
2567 SCLogDebug(
"ssn %p: SYN/ACK packet on state SYN_RECV. resent",
ssn);
2570 SCLogDebug(
"ssn %p: SYN/ACK-pkt to server in SYN_RECV state",
ssn);
2579 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
2580 "%" PRIu32
" from stream",
2590 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
2591 "%" PRIu32
" from stream",
2594 if (StreamTcp3whsQueueSynAck(
ssn,
p) == -1)
2600 SCLogDebug(
"ssn %p: SYN packet on state SYN_RECV... resent",
ssn);
2603 SCLogDebug(
"ssn %p: SYN-pkt to client in SYN_RECV state",
ssn);
2610 SCLogDebug(
"ssn %p: SYN with different SEQ on SYN_RECV state",
ssn);
2618 SCLogDebug(
"ssn %p: checking ACK against queued SYN/ACKs",
ssn);
2621 SCLogDebug(
"ssn %p: here we update state against queued SYN/ACK",
ssn);
2622 StreamTcp3whsSynAckUpdate(
ssn,
p, q);
2624 SCLogDebug(
"ssn %p: none found, now checking ACK against original SYN/ACK (state)",
ssn);
2634 if (!(StreamTcpValidateTimestamp(
ssn,
p))) {
2655 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
2656 "%" PRIu32
", ACK %" PRIu32
"",
2660 StreamTcpHandleTimestamp(
ssn,
p);
2669 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED",
ssn);
2673 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
", "
2674 "ssn->client.last_ack %"PRIu32
"",
ssn,
2679 bool ack_indicates_missed_3whs_ack_packet =
false;
2689 SCLogDebug(
"ssn %p: ACK received on midstream SYN/ACK "
2690 "pickup session",
ssn);
2715 SCLogDebug(
"ssn %p: ACK received in the wrong direction",
2720 ack_indicates_missed_3whs_ack_packet =
true;
2724 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ %" PRIu32
""
2725 ", ACK %" PRIu32
"",
2737 StreamTcpHandleTimestamp(
ssn,
p);
2761 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED",
ssn);
2787 StreamTcpHandleTimestamp(
ssn,
p);
2800 SCLogDebug(
"ssn %p: synrecv => Asynchronous stream, packet SEQ"
2801 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2802 "ssn->server.next_seq %" PRIu32,
2807 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED",
ssn);
2816 SCLogDebug(
"ssn %p: wrong ack nr on packet, possible evasion!!",
2829 StreamTcpHandleTimestamp(
ssn,
p);
2835 SCLogDebug(
"ssn %p: ACK for missing data: ssn->server.next_seq %u",
ssn,
2845 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED",
ssn);
2857 StreamTcpHandleTimestamp(
ssn,
p);
2879 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED",
ssn);
2884 }
else if ((ack_indicates_missed_3whs_ack_packet ||
2888 if (ack_indicates_missed_3whs_ack_packet) {
2889 SCLogDebug(
"ssn %p: packet fits perfectly after a missed 3whs-ACK",
ssn);
2891 SCLogDebug(
"ssn %p: (TFO) expected packet fits perfectly after SYN/ACK",
ssn);
2900 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED",
ssn);
2911 SCLogDebug(
"ssn %p: ssn->server.next_win %" PRIu32
", "
2912 "ssn->server.last_ack %"PRIu32
"",
ssn,
2934 static int HandleEstablishedPacketToServer(
2937 const TCPHdr *tcph = PacketGetTCP(
p);
2942 SCLogDebug(
"ssn %p: =+ pkt (%" PRIu32
") is to server: SEQ %" PRIu32
","
2943 "ACK %" PRIu32
", WIN %" PRIu16
"",
2949 SCLogDebug(
"ssn %p: accepting ACK as it ACKs the one byte from the ZWP",
ssn);
2952 }
else if (StreamTcpValidateAck(
ssn, &
ssn->
server,
p) == -1) {
2953 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
2966 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ"
2967 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
2968 " ssn->client.last_ack %" PRIu32
", ssn->client.next_win"
2969 "%" PRIu32
"(%" PRIu32
")",
2979 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ."
2980 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2981 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2982 "%" PRIu32
"(%" PRIu32
")",
2994 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ"
2995 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2996 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2997 "%" PRIu32
"(%" PRIu32
")",
3012 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
3013 " before last_ack %" PRIu32
", after next_seq %" PRIu32
":"
3014 " acked data that we haven't seen before",
3017 SCLogDebug(
"ssn %p: server => SEQ before last_ack, packet SEQ"
3018 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
3019 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
3020 "%" PRIu32
"(%" PRIu32
")",
3024 SCLogDebug(
"ssn %p: rejecting because pkt before last_ack",
ssn);
3030 int zerowindowprobe = 0;
3034 zerowindowprobe = 1;
3044 if (zerowindowprobe) {
3045 SCLogDebug(
"ssn %p: zero window probe, skipping oow check",
ssn);
3048 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
3070 StreamTcpHandleTimestamp(
ssn,
p);
3082 SCLogDebug(
"ssn %p: toserver => SEQ out of window, packet SEQ "
3083 "%" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3084 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
3085 "%" PRIu32
"(%" PRIu32
")",
3109 static int HandleEstablishedPacketToClient(
3112 const TCPHdr *tcph = PacketGetTCP(
p);
3117 SCLogDebug(
"ssn %p: =+ pkt (%" PRIu32
") is to client: SEQ %" PRIu32
","
3118 " ACK %" PRIu32
", WIN %" PRIu16
"",
3124 SCLogDebug(
"ssn %p: accepting ACK as it ACKs the one byte from the ZWP",
ssn);
3127 }
else if (StreamTcpValidateAck(
ssn, &
ssn->
client,
p) == -1) {
3128 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
3142 SCLogDebug(
"ssn %p: adjusted midstream ssn->server.next_win to "
3154 SCLogDebug(
"ssn %p: client => Asynchronous stream, packet SEQ"
3155 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3156 " ssn->client.last_ack %" PRIu32
", ssn->client.next_win"
3157 " %" PRIu32
"(%" PRIu32
")",
3168 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
3169 " before last_ack %" PRIu32
", after next_seq %" PRIu32
":"
3170 " acked data that we haven't seen before",
3173 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
3174 " before last_ack %" PRIu32
". next_seq %" PRIu32,
3181 int zerowindowprobe = 0;
3185 zerowindowprobe = 1;
3196 if (zerowindowprobe) {
3197 SCLogDebug(
"ssn %p: zero window probe, skipping oow check",
ssn);
3200 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
3217 StreamTcpHandleTimestamp(
ssn,
p);
3226 SCLogDebug(
"ssn %p: client => SEQ out of window, packet SEQ"
3227 "%" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3228 " ssn->server.last_ack %" PRIu32
", ssn->server.next_win "
3229 "%" PRIu32
"(%" PRIu32
")",
3240 const TCPHdr *tcph = PacketGetTCP(
p);
3264 if (pkt_win != rcv->
window)
3280 const TCPHdr *tcph = PacketGetTCP(
p);
3298 if (pkt_win == 0 || rcv->
window == 0)
3300 if (pkt_win != rcv->
window)
3308 SCLogDebug(
"ssn %p: packet:%" PRIu64
" seq:%u ack:%u win:%u snd %u:%u:%u rcv %u:%u:%u",
ssn,
3332 const TCPHdr *tcph = PacketGetTCP(
p);
3394 const TCPHdr *tcph = PacketGetTCP(
p);
3400 "ssn %p: spurious retransmission; packet entirely before base_seq: SEQ %u(%u) "
3401 "last_ack %u base_seq %u",
3410 SCLogDebug(
"ssn %p: spurious retransmission; packet entirely before last_ack: SEQ %u(%u) "
3418 SCLogDebug(
"ssn %p: NOT spurious retransmission; packet NOT entirely before last_ack: SEQ "
3419 "%u(%u) last_ack %u, base_seq %u",
3436 static int StreamTcpPacketStateEstablished(
3440 const TCPHdr *tcph = PacketGetTCP(
p);
3446 if (!StreamTcpValidateRst(
ssn,
p))
3450 StreamTcpCloseSsnWithReset(
p,
ssn);
3464 StreamTcpHandleTimestamp(
ssn,
p);
3468 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3476 StreamTcpCloseSsnWithReset(
p,
ssn);
3491 StreamTcpHandleTimestamp(
ssn,
p);
3495 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3506 if (!StreamTcpValidateTimestamp(
ssn,
p))
3511 " %" PRIu32
", last ACK %" PRIu32
", next win %"PRIu32
","
3516 if ((StreamTcpHandleFin(
tv, stt,
ssn,
p)) == -1)
3521 SCLogDebug(
"ssn %p: SYN/ACK packet on state ESTABLISHED... resent",
3525 SCLogDebug(
"ssn %p: SYN/ACK-pkt to server in ESTABLISHED state",
ssn);
3534 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
3535 "%" PRIu32
" from stream",
3545 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
3546 "%" PRIu32
" from stream",
3559 SCLogDebug(
"ssn %p: SYN/ACK packet on state ESTABLISHED... resent. "
3560 "Likely due server not receiving final ACK in 3whs",
ssn);
3564 SCLogDebug(
"ssn %p: SYN packet on state ESTABLISHED... resent",
ssn);
3573 SCLogDebug(
"ssn %p: SYN with different SEQ on SYN_RECV state",
ssn);
3594 if (!StreamTcpValidateTimestamp(
ssn,
p))
3600 HandleEstablishedPacketToServer(
tv,
ssn,
p, stt);
3602 SCLogDebug(
"ssn %p: next SEQ %" PRIu32
", last ACK %" PRIu32
","
3603 " next win %" PRIu32
", win %" PRIu32
"",
ssn,
3610 SCLogDebug(
"3whs is now confirmed by server");
3614 HandleEstablishedPacketToClient(
tv,
ssn,
p, stt);
3616 SCLogDebug(
"ssn %p: next SEQ %" PRIu32
", last ACK %" PRIu32
","
3617 " next win %" PRIu32
", win %" PRIu32
"",
ssn,
3642 const TCPHdr *tcph = PacketGetTCP(
p);
3648 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ %" PRIu32
","
3653 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
3659 SCLogDebug(
"ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u",
ssn,
seq, pkt_re,
3664 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
" != "
3665 "%" PRIu32
" from stream",
3688 StreamTcpHandleTimestamp(
ssn,
p);
3701 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK %" PRIu32
"",
3704 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ %" PRIu32
", "
3709 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
3715 SCLogDebug(
"ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u",
ssn,
seq, pkt_re,
3720 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
" != "
3721 "%" PRIu32
" from stream (last_ack %u win %u = %u)",
3739 StreamTcpHandleTimestamp(
ssn,
p);
3752 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK %" PRIu32
"",
3772 static int StreamTcpPacketStateFinWait1(
3776 const TCPHdr *tcph = PacketGetTCP(
p);
3782 if (!StreamTcpValidateRst(
ssn,
p))
3785 StreamTcpCloseSsnWithReset(
p,
ssn);
3794 StreamTcpHandleTimestamp(
ssn,
p);
3805 StreamTcpHandleTimestamp(
ssn,
p);
3813 if (!StreamTcpValidateTimestamp(
ssn,
p))
3818 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3819 "%" PRIu32
", ACK %" PRIu32
"",
3821 int retransmission = 0;
3823 if (StreamTcpPacketIsRetransmission(&
ssn->
client,
p)) {
3830 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3831 " != %" PRIu32
" from stream",
3838 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
3843 if (!retransmission) {
3851 StreamTcpHandleTimestamp(
ssn,
p);
3867 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3871 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3872 "%" PRIu32
", ACK %" PRIu32
"",
3874 int retransmission = 0;
3876 if (StreamTcpPacketIsRetransmission(&
ssn->
server,
p)) {
3888 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3889 " != %" PRIu32
" from stream",
3896 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
3902 StreamTcpHandleTimestamp(
ssn,
p);
3905 if (!retransmission) {
3925 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3932 if (!StreamTcpValidateTimestamp(
ssn,
p))
3937 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3938 "%" PRIu32
", ACK %" PRIu32
"",
3940 int retransmission = 0;
3942 if (StreamTcpPacketIsRetransmission(&
ssn->
client,
p)) {
3949 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3950 " != %" PRIu32
" from stream",
3957 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
3962 if (!retransmission) {
3970 StreamTcpHandleTimestamp(
ssn,
p);
3987 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3991 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3992 "%" PRIu32
", ACK %" PRIu32
"",
3995 int retransmission = 0;
3997 if (StreamTcpPacketIsRetransmission(&
ssn->
server,
p)) {
4004 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4005 " != %" PRIu32
" from stream",
4012 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
4017 if (!retransmission) {
4025 StreamTcpHandleTimestamp(
ssn,
p);
4042 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4053 if (!StreamTcpValidateTimestamp(
ssn,
p))
4058 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4059 "%" PRIu32
", ACK %" PRIu32
"",
4061 int retransmission = 0;
4063 if (StreamTcpPacketIsRetransmission(&
ssn->
client,
p)) {
4070 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
4078 }
else if (!retransmission) {
4082 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
4091 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4092 " != %" PRIu32
" from stream",
4104 StreamTcpHandleTimestamp(
ssn,
p);
4125 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4131 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4132 "%" PRIu32
", ACK %" PRIu32
"",
4135 int retransmission = 0;
4137 if (StreamTcpPacketIsRetransmission(&
ssn->
server,
p)) {
4144 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
4149 if (!retransmission) {
4152 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
4161 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4162 " != %" PRIu32
" from stream",
4172 StreamTcpHandleTimestamp(
ssn,
p);
4193 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4214 static int StreamTcpPacketStateFinWait2(
4218 const TCPHdr *tcph = PacketGetTCP(
p);
4224 if (!StreamTcpValidateRst(
ssn,
p))
4227 StreamTcpCloseSsnWithReset(
p,
ssn);
4236 StreamTcpHandleTimestamp(
ssn,
p);
4247 StreamTcpHandleTimestamp(
ssn,
p);
4255 if (!StreamTcpValidateTimestamp(
ssn,
p))
4260 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4261 "%" PRIu32
", ACK %" PRIu32
"",
4263 int retransmission = 0;
4269 }
else if (StreamTcpPacketIsRetransmission(&
ssn->
client,
p)) {
4276 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ "
4277 "%" PRIu32
" != %" PRIu32
" from stream",
4284 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
4289 if (!retransmission) {
4301 StreamTcpHandleTimestamp(
ssn,
p);
4314 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4318 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4319 "%" PRIu32
", ACK %" PRIu32
"",
4321 int retransmission = 0;
4327 }
else if (StreamTcpPacketIsRetransmission(&
ssn->
server,
p)) {
4334 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ "
4335 "%" PRIu32
" != %" PRIu32
" from stream",
4342 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
4347 if (!retransmission) {
4355 StreamTcpHandleTimestamp(
ssn,
p);
4367 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4379 if (!StreamTcpValidateTimestamp(
ssn,
p))
4384 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4385 "%" PRIu32
", ACK %" PRIu32
"",
4387 int retransmission = 0;
4389 if (StreamTcpPacketIsRetransmission(&
ssn->
client,
p)) {
4396 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
4401 if (!retransmission) {
4404 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
4409 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4410 " != %" PRIu32
" from stream",
4420 StreamTcpHandleTimestamp(
ssn,
p);
4436 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4440 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4441 "%" PRIu32
", ACK %" PRIu32
"",
4443 int retransmission = 0;
4445 if (StreamTcpPacketIsRetransmission(&
ssn->
server,
p)) {
4452 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
4457 if (!retransmission) {
4460 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
4464 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4465 " != %" PRIu32
" from stream",
4475 StreamTcpHandleTimestamp(
ssn,
p);
4491 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4512 static int StreamTcpPacketStateClosing(
4516 const TCPHdr *tcph = PacketGetTCP(
p);
4522 if (!StreamTcpValidateRst(
ssn,
p))
4525 StreamTcpCloseSsnWithReset(
p,
ssn);
4534 StreamTcpHandleTimestamp(
ssn,
p);
4545 StreamTcpHandleTimestamp(
ssn,
p);
4558 if (!StreamTcpValidateTimestamp(
ssn,
p))
4563 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4564 "%" PRIu32
", ACK %" PRIu32
"",
4566 int retransmission = 0;
4567 if (StreamTcpPacketIsRetransmission(&
ssn->
client,
p)) {
4574 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4575 " != %" PRIu32
" from stream",
4582 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
4587 if (!retransmission) {
4595 StreamTcpHandleTimestamp(
ssn,
p);
4605 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4609 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4610 "%" PRIu32
", ACK %" PRIu32
"",
4612 int retransmission = 0;
4613 if (StreamTcpPacketIsRetransmission(&
ssn->
server,
p)) {
4620 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4621 " != %" PRIu32
" from stream",
4628 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
4633 if (!retransmission) {
4641 StreamTcpHandleTimestamp(
ssn,
p);
4652 SCLogDebug(
"StreamTcpPacketStateClosing (%p): =+ next SEQ "
4653 "%" PRIu32
", last ACK %" PRIu32
"",
ssn,
4673 static int StreamTcpPacketStateCloseWait(
4677 const TCPHdr *tcph = PacketGetTCP(
p);
4685 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4686 "%" PRIu32
", ACK %" PRIu32
"",
4689 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4690 "%" PRIu32
", ACK %" PRIu32
"",
4695 if (!StreamTcpValidateRst(
ssn,
p))
4698 StreamTcpCloseSsnWithReset(
p,
ssn);
4707 StreamTcpHandleTimestamp(
ssn,
p);
4718 StreamTcpHandleTimestamp(
ssn,
p);
4726 if (!StreamTcpValidateTimestamp(
ssn,
p))
4731 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4732 "%" PRIu32
", ACK %" PRIu32
"",
4735 int retransmission = 0;
4736 if (StreamTcpPacketIsRetransmission(&
ssn->
client,
p)) {
4742 if (!retransmission) {
4745 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4746 " != %" PRIu32
" from stream",
4754 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
4761 if (!retransmission)
4765 StreamTcpHandleTimestamp(
ssn,
p);
4777 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4781 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4782 "%" PRIu32
", ACK %" PRIu32
"",
4785 int retransmission = 0;
4786 if (StreamTcpPacketIsRetransmission(&
ssn->
server,
p)) {
4792 if (!retransmission) {
4795 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4796 " != %" PRIu32
" from stream",
4804 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
4809 if (!retransmission) {
4817 StreamTcpHandleTimestamp(
ssn,
p);
4829 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4841 if (!StreamTcpValidateTimestamp(
ssn,
p))
4846 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4847 "%" PRIu32
", ACK %" PRIu32
"",
4850 int retransmission = 0;
4851 if (StreamTcpPacketIsRetransmission(&
ssn->
client,
p)) {
4863 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4864 " != %" PRIu32
" from stream",
4871 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
4876 if (!retransmission) {
4881 StreamTcpHandleTimestamp(
ssn,
p);
4895 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4899 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4900 "%" PRIu32
", ACK %" PRIu32
"",
4902 int retransmission = 0;
4903 if (StreamTcpPacketIsRetransmission(&
ssn->
server,
p)) {
4915 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4916 " != %" PRIu32
" from stream",
4923 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
4928 if (!retransmission) {
4933 StreamTcpHandleTimestamp(
ssn,
p);
4947 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4968 static int StreamTcpPacketStateLastAck(
4972 const TCPHdr *tcph = PacketGetTCP(
p);
4978 if (!StreamTcpValidateRst(
ssn,
p))
4981 StreamTcpCloseSsnWithReset(
p,
ssn);
4990 StreamTcpHandleTimestamp(
ssn,
p);
5001 StreamTcpHandleTimestamp(
ssn,
p);
5018 if (!StreamTcpValidateTimestamp(
ssn,
p))
5023 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
5024 "%" PRIu32
", ACK %" PRIu32
"",
5027 int retransmission = 0;
5028 if (StreamTcpPacketIsRetransmission(&
ssn->
client,
p)) {
5035 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
5040 if (!retransmission) {
5042 SCLogDebug(
"ssn %p: not updating state as packet is before next_seq",
ssn);
5044 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5045 " != %" PRIu32
" from stream",
5057 StreamTcpHandleTimestamp(
ssn,
p);
5068 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5089 static int StreamTcpPacketStateTimeWait(
5093 const TCPHdr *tcph = PacketGetTCP(
p);
5099 if (!StreamTcpValidateRst(
ssn,
p))
5102 StreamTcpCloseSsnWithReset(
p,
ssn);
5111 StreamTcpHandleTimestamp(
ssn,
p);
5122 StreamTcpHandleTimestamp(
ssn,
p);
5138 if (!StreamTcpValidateTimestamp(
ssn,
p))
5143 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
5144 "%" PRIu32
", ACK %" PRIu32
"",
5146 int retransmission = 0;
5147 if (StreamTcpPacketIsRetransmission(&
ssn->
client,
p)) {
5153 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5154 " != %" PRIu32
" from stream",
5161 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
5166 if (!retransmission) {
5174 StreamTcpHandleTimestamp(
ssn,
p);
5185 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5189 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
5190 "%" PRIu32
", ACK %" PRIu32
"",
5192 int retransmission = 0;
5193 if (StreamTcpPacketIsRetransmission(&
ssn->
server,
p)) {
5202 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5203 " != %" PRIu32
" from stream",
5211 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
5216 if (!retransmission) {
5224 StreamTcpHandleTimestamp(
ssn,
p);
5235 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5247 static int StreamTcpPacketStateClosed(
5252 const TCPHdr *tcph = PacketGetTCP(
p);
5258 TcpStream *stream = NULL, *ostream = NULL;
5290 const TCPHdr *tcph = PacketGetTCP(
p);
5304 SCLogDebug(
"regular packet %" PRIu64
" from same sender as "
5305 "the previous RST. Looks like it injected!",
5332 const TCPHdr *tcph = PacketGetTCP(
p);
5337 TcpStream *stream = NULL, *ostream = NULL;
5348 if (ack == ostream->last_ack &&
seq == (stream->
next_seq - 1)) {
5364 TcpStream *stream = NULL, *ostream = NULL;
5375 const TCPHdr *tcph = PacketGetTCP(
p);
5394 if (pkt_win != ostream->window)
5403 SCLogDebug(
"seq %u (%u), ack %u (%u) FLAG_KEEPALIVE: %s",
seq, stream->
next_seq, ack, ostream->last_ack,
5433 TcpStream *stream = NULL, *ostream = NULL;
5447 const TCPHdr *tcph = PacketGetTCP(
p);
5466 if (pkt_win == ostream->window)
5469 if (ack == ostream->last_ack &&
seq == stream->
next_seq) {
5484 TcpStream *stream = NULL, *ostream = NULL;
5492 const TCPHdr *tcph = PacketGetTCP(
p);
5509 SCLogDebug(
"%" PRIu64
", seq %u ack %u stream->next_seq %u ostream->next_seq %u",
5537 TcpStream *stream = NULL, *ostream = NULL;
5548 const TCPHdr *tcph = PacketGetTCP(
p);
5564 if (pkt_win < ostream->window) {
5565 uint32_t diff = ostream->window - pkt_win;
5567 SEQ_GT(ack, ostream->next_seq) &&
5570 SCLogDebug(
"%" PRIu64
", pkt_win %u, stream win %u, diff %u, dsize %u",
5574 SCLogDebug(
"%" PRIu64
", seq %u ack %u ostream->next_seq %u ostream->last_ack %u, "
5575 "ostream->next_win %u, diff %u (%u)",
5577 ostream->next_win, ostream->next_seq - ostream->last_ack,
5585 uint32_t adiff = ack - ostream->last_ack;
5586 if (((pkt_win > 1024) && (diff > (adiff + 32))) ||
5587 ((pkt_win <= 1024) && (diff > adiff)))
5589 SCLogDebug(
"pkt ACK %u is %u bytes beyond last_ack %u, shrinks window by %u "
5590 "(allowing 32 bytes extra): pkt WIN %u", ack, adiff, ostream->last_ack, diff, pkt_win);
5606 static inline int StreamTcpStateDispatch(
5614 SCLogDebug(
"packet received on TCP_SYN_SENT state");
5615 if (StreamTcpPacketStateSynSent(
tv,
p, stt,
ssn)) {
5620 SCLogDebug(
"packet received on TCP_SYN_RECV state");
5621 if (StreamTcpPacketStateSynRecv(
tv,
p, stt,
ssn)) {
5626 SCLogDebug(
"packet received on TCP_ESTABLISHED state");
5627 if (StreamTcpPacketStateEstablished(
tv,
p, stt,
ssn)) {
5632 SCLogDebug(
"packet received on TCP_FIN_WAIT1 state");
5633 if (StreamTcpPacketStateFinWait1(
tv,
p, stt,
ssn)) {
5638 SCLogDebug(
"packet received on TCP_FIN_WAIT2 state");
5639 if (StreamTcpPacketStateFinWait2(
tv,
p, stt,
ssn)) {
5644 SCLogDebug(
"packet received on TCP_CLOSING state");
5645 if (StreamTcpPacketStateClosing(
tv,
p, stt,
ssn)) {
5650 SCLogDebug(
"packet received on TCP_CLOSE_WAIT state");
5651 if (StreamTcpPacketStateCloseWait(
tv,
p, stt,
ssn)) {
5656 SCLogDebug(
"packet received on TCP_LAST_ACK state");
5657 if (StreamTcpPacketStateLastAck(
tv,
p, stt,
ssn)) {
5662 SCLogDebug(
"packet received on TCP_TIME_WAIT state");
5663 if (StreamTcpPacketStateTimeWait(
tv,
p, stt,
ssn)) {
5669 SCLogDebug(
"packet received on closed state");
5671 if (StreamTcpPacketStateClosed(
tv,
p, stt,
ssn)) {
5677 SCLogDebug(
"packet received on default state");
5713 const TCPHdr *tcph = PacketGetTCP(
p);
5728 SCLogDebug(
"ssn %p: removing ASYNC flag as we have packets on both sides",
ssn);
5748 if (StreamTcpCheckFlowDrops(
p) == 1) {
5758 if (StreamTcpPacketStateNone(
tv,
p, stt,
ssn) == -1) {
5785 if (StreamTcpPacketIsKeepAlive(
ssn,
p) == 1) {
5788 if (StreamTcpPacketIsKeepAliveACK(
ssn,
p) == 1) {
5789 StreamTcpClearKeepAliveFlag(
ssn,
p);
5792 StreamTcpClearKeepAliveFlag(
ssn,
p);
5794 const bool is_zwp_ack = StreamTcpPacketIsZeroWindowProbeAck(
ssn,
p);
5805 if (StreamTcpPacketIsDupAck(
ssn,
p)) {
5812 if (StreamTcpPacketIsFinShutdownAck(
ssn,
p) == 0) {
5813 if (StreamTcpPacketIsWindowUpdate(
ssn,
p) == 0) {
5814 if (StreamTcpPacketIsBadWindowUpdate(
ssn,
p))
5816 if (StreamTcpPacketIsOutdatedAck(
ssn,
p))
5821 int ret = StreamTcpPacketIsSpuriousRetransmission(
ssn,
p);
5834 StreamTcpPacketCheckPostRst(
ssn,
p);
5881 SCLogDebug(
"bypass as stream is dead and we have no rules");
5894 if (StreamTcpInlineDropInvalid()) {
5898 DecodeSetNoPayloadInspectionFlag(
p);
5912 static inline int StreamTcpValidateChecksum(
Packet *
p)
5920 const TCPHdr *tcph = PacketGetTCP(
p);
5921 if (PacketIsIPv4(
p)) {
5922 const IPV4Hdr *ip4h = PacketGetIPv4(
p);
5923 p->
l4.
csum = TCPChecksum(ip4h->s_ip_addrs, (uint16_t *)tcph,
5926 }
else if (PacketIsIPv6(
p)) {
5927 const IPV6Hdr *ip6h = PacketGetIPv6(
p);
5928 p->
l4.
csum = TCPV6Checksum(ip6h->s_ip6_addrs, (uint16_t *)tcph,
5950 static int TcpSessionPacketIsStreamStarter(
const Packet *
p)
5952 const TCPHdr *tcph = PacketGetTCP(
p);
5965 SCLogDebug(
"packet %" PRIu64
" is a midstream stream starter: %02x",
5978 const TCPHdr *tcph = PacketGetTCP(
p);
5983 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p null. Reuse.",
5989 ", ssn %p. STREAMTCP_FLAG_TFO_DATA_IGNORED set. Reuse.",
5995 ", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.",
6001 ", ssn %p state >= TCP_LAST_ACK (%u). Reuse.",
6005 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.",
6010 ", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.",
6017 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p null. Reuse.",
6023 ", ssn %p state >= TCP_LAST_ACK (%u). Reuse.",
6027 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.",
6032 ", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.",
6048 const TCPHdr *tcph = PacketGetTCP(
p);
6051 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p null. No reuse.",
6057 ", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.",
6063 ", ssn %p state >= TCP_LAST_ACK (%u). Reuse.",
6067 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.",
6072 ", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.",
6079 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p null. Reuse.",
6085 ", ssn %p state >= TCP_LAST_ACK (%u). Reuse.",
6089 SCLogDebug(
"stream starter packet %" PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.",
6094 ", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.",
6111 const TCPHdr *tcph = PacketGetTCP(
p);
6113 return TcpSessionReuseDoneEnoughSyn(
p,
f,
ssn);
6118 return TcpSessionReuseDoneEnoughSynAck(
p,
f,
ssn);
6127 if (
p->
proto == IPPROTO_TCP && PacketIsTCP(
p)) {
6128 if (TcpSessionPacketIsStreamStarter(
p) == 1) {
6129 if (TcpSessionReuseDoneEnough(
p,
f, tcp_ssn) == 1) {
6151 #ifdef QA_SIMULATION
6155 if (!(PacketIsTCP(
p))) {
6159 CheckThreadId(
tv,
p, stt);
6165 if (StreamTcpValidateChecksum(
p) == 0) {
6187 *data = (
void *)stt;
6196 IsStreamTcpSessionMemcapExceptionPolicyStatsValid);
6204 "exception_policy.tcp.midstream.", IsMidstreamExceptionPolicyStatsValid);
6208 "exception_policy.tcp.midstream.", IsMidstreamExceptionPolicyStatsValid);
6224 "exception_policy.tcp.reassembly.", IsReassemblyMemcapExceptionPolicyStatsValid);
6243 SCLogDebug(
"StreamTcp thread specific ctx online at %p, reassembly ctx %p",
6251 StreamTcpSessionPoolInit, StreamTcpSessionPoolCleanup);
6261 SCLogError(
"failed to setup/expand stream session pool. Expand stream.memcap?");
6306 const TCPHdr *tcph = PacketGetTCP(
p);
6314 if (!StreamTcpValidateTimestamp(
ssn,
p)) {
6344 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
6357 SCLogDebug(
"ssn %p: rejecting because of invalid ack value",
ssn);
6374 SCLogDebug(
"ssn %p: setting STREAMTCP_STREAM_FLAG_RST_RECV on receiver stream",
ssn);
6394 switch (os_policy) {
6401 SCLogDebug(
"reset is not Valid! Packet SEQ: %" PRIu32
" "
6402 "and server SEQ: %" PRIu32
"",
6411 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" "
6412 "and client SEQ: %" PRIu32
"",
6429 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6430 " server SEQ: %" PRIu32
"",
6442 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6443 " client SEQ: %" PRIu32
"",
6464 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" "
6465 "and server SEQ: %" PRIu32
"",
6471 SCLogDebug(
"reset is valid! Packet SEQ: %" PRIu32
" Stream %u",
seq,
6475 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6476 " client SEQ: %" PRIu32
"",
6507 uint8_t check_ts = 1;
6508 const TCPHdr *tcph = PacketGetTCP(
p);
6527 uint32_t last_pkt_ts = sender_stream->
last_pkt_ts;
6528 uint32_t last_ts = sender_stream->
last_ts;
6578 SCLogDebug(
"ts %"PRIu32
", last_ts %"PRIu32
"",
ts, last_ts);
6582 result = (int32_t) ((
ts - last_ts) + 1);
6584 result = (int32_t) (
ts - last_ts);
6587 SCLogDebug(
"result %" PRIi32
", p->ts(secs) %" PRIuMAX
"", result,
6590 if (last_pkt_ts == 0 &&
6598 "%" PRIu32
" p->tcpvars->ts %" PRIu32
" result "
6599 "%" PRId32
"", last_ts,
ts, result);
6602 }
else if ((sender_stream->
last_ts != 0) &&
6604 SCLogDebug(
"packet is not valid last_pkt_ts "
6605 "%" PRIu32
" p->ts(sec) %" PRIu32
"",
6617 SCLogDebug(
"timestamp considered valid anyway");
6649 uint8_t check_ts = 1;
6650 const TCPHdr *tcph = PacketGetTCP(
p);
6726 result = (int32_t) ((
ts - sender_stream->
last_ts) + 1);
6728 result = (int32_t) (
ts - sender_stream->
last_ts);
6731 SCLogDebug(
"result %" PRIi32
", p->ts(sec) %" PRIuMAX
"", result,
6741 SCLogDebug(
"timestamp is not valid sender_stream->last_ts "
6742 "%" PRIu32
" p->tcpvars->ts %" PRIu32
" result "
6743 "%" PRId32
"", sender_stream->
last_ts,
ts, result);
6746 }
else if ((sender_stream->
last_ts != 0) &&
6749 SCLogDebug(
"packet is not valid sender_stream->last_pkt_ts "
6750 "%" PRIu32
" p->ts(sec) %" PRIu32
"",
6764 }
else if (ret == 0) {
6774 SCLogDebug(
"timestamp considered valid anyway");
6810 const TCPHdr *tcph = PacketGetTCP(
p);
6825 SCLogDebug(
"ssn %p: pkt ACK %" PRIu32
" == stream last ACK %" PRIu32,
ssn, ack,
6838 SCLogDebug(
"ACK %"PRIu32
" is before last_ack %"PRIu32
" - window "
6839 "%"PRIu32
" = %"PRIu32, ack, stream->
last_ack,
6862 SCLogDebug(
"default path leading to invalid: ACK %"PRIu32
", last_ack %"PRIu32
6875 const uint32_t progress)
6929 static void StreamTcpPseudoPacketCreateDetectLogFlush(
ThreadVars *
tv,
6952 np->
proto = IPPROTO_TCP;
6953 FlowReference(&np->
flow,
f);
6963 DecodeSetNoPacketInspectionFlag(np);
6966 DecodeSetNoPayloadInspectionFlag(np);
7006 ip4h->
ip_len = htons(40);
7012 ip4h->s_ip_src.s_addr =
f->
src.addr_data32[0];
7013 ip4h->s_ip_dst.s_addr =
f->
dst.addr_data32[0];
7015 ip4h->s_ip_src.s_addr =
f->
dst.addr_data32[0];
7016 ip4h->s_ip_dst.s_addr =
f->
src.addr_data32[0];
7049 ip6h->s_ip6_vfc = 0x60;
7050 ip6h->s_ip6_flow = 0;
7051 ip6h->s_ip6_nxt = IPPROTO_TCP;
7052 ip6h->s_ip6_plen = htons(20);
7053 ip6h->s_ip6_hlim = 64;
7055 ip6h->s_ip6_src[0] =
f->
src.addr_data32[0];
7056 ip6h->s_ip6_src[1] =
f->
src.addr_data32[1];
7057 ip6h->s_ip6_src[2] =
f->
src.addr_data32[2];
7058 ip6h->s_ip6_src[3] =
f->
src.addr_data32[3];
7059 ip6h->s_ip6_dst[0] =
f->
dst.addr_data32[0];
7060 ip6h->s_ip6_dst[1] =
f->
dst.addr_data32[1];
7061 ip6h->s_ip6_dst[2] =
f->
dst.addr_data32[2];
7062 ip6h->s_ip6_dst[3] =
f->
dst.addr_data32[3];
7064 ip6h->s_ip6_src[0] =
f->
dst.addr_data32[0];
7065 ip6h->s_ip6_src[1] =
f->
dst.addr_data32[1];
7066 ip6h->s_ip6_src[2] =
f->
dst.addr_data32[2];
7067 ip6h->s_ip6_src[3] =
f->
dst.addr_data32[3];
7068 ip6h->s_ip6_dst[0] =
f->
src.addr_data32[0];
7069 ip6h->s_ip6_dst[1] =
f->
src.addr_data32[1];
7070 ip6h->s_ip6_dst[2] =
f->
src.addr_data32[2];
7071 ip6h->s_ip6_dst[3] =
f->
src.addr_data32[3];
7103 np->
ts = parent->
ts;
7111 FlowDeReference(&np->
flow);
7130 StreamTcpPseudoPacketCreateDetectLogFlush(
tv, stt,
p,
ssn, pq,
ts^1);
7131 StreamTcpPseudoPacketCreateDetectLogFlush(
tv, stt,
p,
ssn, pq,
ts ^ 0);
7151 if (
p->
flow == NULL)
7179 const uint8_t *seg_data;
7180 uint32_t seg_datalen;
7183 int ret = CallbackFunc(
p, seg, data, seg_data, seg_datalen);
7211 if (
p->
flow == NULL)
7225 if (server_node == NULL && client_node == NULL) {
7229 while (server_node != NULL || client_node != NULL) {
7230 const uint8_t *seg_data;
7231 uint32_t seg_datalen;
7232 if (server_node == NULL) {
7239 &client_stream->
sb, &client_node->
sbseg, &seg_data, &seg_datalen);
7240 ret = CallbackFunc(
p, client_node, data, seg_data, seg_datalen);
7245 client_node = TCPSEG_RB_NEXT(client_node);
7246 }
else if (client_node == NULL) {
7253 &server_stream->
sb, &server_node->
sbseg, &seg_data, &seg_datalen);
7254 ret = CallbackFunc(
p, server_node, data, seg_data, seg_datalen);
7259 server_node = TCPSEG_RB_NEXT(server_node);
7264 &client_stream->
sb, &client_node->
sbseg, &seg_data, &seg_datalen);
7265 ret = CallbackFunc(
p, client_node, data, seg_data, seg_datalen);
7270 client_node = TCPSEG_RB_NEXT(client_node);
7273 &server_stream->
sb, &server_node->
sbseg, &seg_data, &seg_datalen);
7274 ret = CallbackFunc(
p, server_node, data, seg_data, seg_datalen);
7279 server_node = TCPSEG_RB_NEXT(server_node);
7314 const char *tcp_state = NULL;
7320 tcp_state =
"syn_sent";
7323 tcp_state =
"syn_recv";
7326 tcp_state =
"established";
7329 tcp_state =
"fin_wait1";
7332 tcp_state =
"fin_wait2";
7335 tcp_state =
"time_wait";
7338 tcp_state =
"last_ack";
7341 tcp_state =
"close_wait";
7344 tcp_state =
"closing";
7347 tcp_state =
"closed";
#define PKT_IS_TOCLIENT(p)
@ STREAM_EST_SYN_RESEND_DIFF_SEQ
#define StreamTcpSetEvent(p, e)
#define TCP_GET_RAW_SEQ(tcph)
bool PacketCheckAction(const Packet *p, const uint8_t a)
void StreamTcpIncrMemuse(uint64_t size)
#define STREAMTCP_QUEUE_FLAG_WS
struct TcpStateQueue_ * next
int(* StreamSegmentCallback)(const Packet *, TcpSegment *, void *, const uint8_t *, uint32_t)
StatsCounterId counter_tcp_reass_data_normal_fail
StatsCounterGlobalId StatsRegisterGlobalCounter(const char *name, uint64_t(*Func)(void))
Registers a counter, which represents a global value.
uint8_t ao_option_present
void ExceptionPolicyApply(Packet *p, enum ExceptionPolicy policy, enum PacketDropReason drop_reason)
#define STREAMTCP_FLAG_CLIENT_SACKOK
void StreamTcpSessionPktFree(Packet *p)
Function to return the stream segments back to the pool.
@ EXCEPTION_POLICY_PASS_FLOW
ExceptionPolicyCounters counter_tcp_reas_eps
#define TCP_STREAM_URGENT_DEFAULT
StatsCounterId counter_tcp_segment_from_pool
int PoolThreadExpand(PoolThread *pt)
expand pool by one for a new thread
StatsCounterId counter_tcp_reass_data_overlap_fail
#define STREAM_DUMP_TOSERVER
#define StreamTcpUpdateNextSeq(ssn, stream, seq)
int FlowGetPacketDirection(const Flow *f, const Packet *p)
determine the direction of the packet compared to the flow
@ STREAM_FIN1_ACK_WRONG_SEQ
StatsCounterId counter_tcp_ssn_from_pool
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
@ STREAM_LASTACK_INVALID_ACK
#define STREAMTCP_FLAG_DETECTION_EVASION_ATTEMPT
@ STREAM_3WHS_ACK_IN_WRONG_DIR
#define STREAMTCP_FLAG_SACKOK
void PacketBypassCallback(Packet *p)
#define PKT_IS_PSEUDOPKT(p)
return 1 if the packet is a pseudo packet
bool TcpSessionPacketSsnReuse(const Packet *p, const Flow *f, const void *tcp_ssn)
int ParseSizeStringU16(const char *size, uint16_t *res)
bool StreamTcpInlineMode(void)
See if stream engine is operating in inline mode.
TcpSession * StreamTcpThreadCacheGetSession(void)
StatsCounterId counter_tcp_segment_memcap
@ PKT_DROP_REASON_STREAM_MEMCAP
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
@ STREAM_PKT_INVALID_TIMESTAMP
#define PKT_STREAM_MODIFIED
uint64_t PcapPacketCntGet(const Packet *p)
int ParseSizeStringU64(const char *size, uint64_t *res)
StatsCounterId StatsRegisterCounter(const char *name, StatsThreadContext *stats)
Registers a normal, unqualified counter.
void StreamTcpSetSessionNoReassemblyFlag(TcpSession *ssn, char direction)
disable reassembly
void StreamTcpThreadCacheReturnSession(TcpSession *ssn)
void StreamTcpSackFreeList(TcpStream *stream)
Free SACK tree from a stream.
StatsCounterId counter_tcp_reass_gap
int StreamTcpGetFlowState(void *)
#define STREAM_PKT_FLAG_DUP_ACK
@ STREAM_FIN_BUT_NO_SESSION
#define STREAM_PKT_FLAG_KEEPALIVEACK
void StreamTcpSetOSPolicy(TcpStream *, Packet *)
Function to set the OS policy for the given stream based on the destination of the received packet.
void StreamTcpInitMemuse(void)
@ STREAM_EST_ACK_ZWP_DATA
#define STREAMTCP_DEFAULT_MAX_SYN_QUEUED
@ STREAM_4WHS_SYNACK_WITH_WRONG_SYN
uint32_t reassembly_depth
StreamingBufferSegment sbseg
#define STREAMTCP_FLAG_ZWP_TC
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
@ STREAM_EST_PACKET_OUT_OF_WINDOW
int SCConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
@ STREAM_EST_SYNACK_RESEND_WITH_DIFFERENT_ACK
#define STREAM_DEPTH_DEFAULT
StreamingBufferConfig sbcnf
LiveDevice * LiveDeviceGetById(const int id)
@ STREAM_CLOSING_ACK_WRONG_SEQ
#define TCP_GET_RAW_HLEN(tcph)
#define STREAM_PKT_FLAG_RETRANSMISSION
TmEcode StreamTcpThreadInit(ThreadVars *tv, void *initdata, void **data)
SC_ATOMIC_DECLARE(uint64_t, st_memuse)
@ STREAM_3WHS_SYNACK_WITH_WRONG_ACK
#define FLOW_PKT_TOSERVER
@ STREAM_3WHS_SYNACK_FLOOD
void StreamTcpUpdateAppLayerProgress(TcpSession *ssn, char direction, const uint32_t progress)
update reassembly progress
int SCConfGetBool(const char *name, int *val)
Retrieve a configuration value as a boolean.
@ STREAM_TIMEWAIT_INVALID_ACK
#define STREAMTCP_FLAG_MIDSTREAM_ESTABLISHED
@ STREAM_3WHS_ASYNC_WRONG_SEQ
#define SCMUTEX_INITIALIZER
@ STREAM_RST_BUT_NO_SESSION
#define STREAMTCP_STREAM_FLAG_KEEPALIVE
void StreamTcpStreamCleanup(TcpStream *stream)
void PoolThreadFree(PoolThread *pt)
destroy the thread pool
#define PKT_STREAM_NO_EVENTS
#define PKT_NOPAYLOAD_INSPECTION
#define TCP_GET_SACKOK(p)
enum ExceptionPolicy midstream_policy
StatsCounterId counter_tcp_active_sessions
#define STREAMTCP_INIT_FLAG_DROP_INVALID
#define TCP_GET_RAW_WINDOW(tcph)
@ EXCEPTION_POLICY_NOT_SET
enum ExceptionPolicy ExceptionPolicyParse(const char *option, bool support_flow)
#define GET_PKT_DIRECT_MAX_SIZE(p)
simple fifo queue for packets
#define STREAMTCP_STREAM_FLAG_DEPTH_REACHED
#define GET_IPV6_DST_ADDR(p)
@ STREAM_3WHS_SYN_RESEND_DIFF_SEQ_ON_SYN_RECV
@ STREAM_FIN1_FIN_WRONG_SEQ
#define STREAMTCP_FLAG_TFO_DATA_IGNORED
#define TCP_GET_WSCALE(p)
#define FLOW_COPY_IPV6_ADDR_TO_PACKET(fa, pa)
int StreamTcpReassembleInit(bool quiet)
@ PKT_DROP_REASON_STREAM_URG
@ STREAM_FIN_OUT_OF_WINDOW
#define STREAMTCP_FLAG_MIDSTREAM
#define STREAMTCP_FLAG_LOSSY_BE_LIBERAL
#define StreamTcpUpdateLastAck(ssn, stream, ack)
macro to update last_ack only if the new value is higher
@ STREAM_FIN2_FIN_WRONG_SEQ
#define PKT_SET_SRC(p, src_val)
StatsCounterId counter_tcp_ssn_memcap
#define SET_PKT_LEN(p, len)
TcpReassemblyThreadCtx * StreamTcpReassembleInitThreadCtx(ThreadVars *tv)
void StreamTcpInitConfig(bool)
To initialize the stream global configuration data.
@ STREAM_CLOSEWAIT_FIN_OUT_OF_WINDOW
uint32_t reassembly_depth
StatsCounterId counter_tcp_reass_overlap
@ STREAM_EST_SYNACK_RESEND_WITH_DIFF_SEQ
enum ExceptionPolicy ssn_memcap_policy
int SCHInfoGetIPv6HostOSFlavour(uint8_t *addr)
Retrieves the host os flavour, given an ipv6 address in the raw address format.
int StreamTcpCheckMemcap(uint64_t size)
Check if alloc'ing "size" would mean we're over memcap.
@ STREAM_SHUTDOWN_SYN_RESEND
#define GET_IPV4_DST_ADDR_PTR(p)
#define PKT_IS_TOSERVER(p)
@ STREAM_4WHS_SYNACK_WITH_WRONG_ACK
#define STREAMTCP_FLAG_ASYNC
#define STREAMTCP_FLAG_BYPASS
enum TcpStreamUrgentHandling urgent_policy
int StreamTcpSegmentForSession(const Packet *p, uint8_t flag, StreamSegmentCallback CallbackFunc, void *data)
Run callback function on each TCP segment in both directions of a session.
#define SCMutexUnlock(mut)
#define PKT_PSEUDO_STREAM_END
void PacketSwap(Packet *p)
switch direction of a packet
int SCConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
#define STREAMTCP_STREAM_FLAG_RST_RECV
#define STREAMTCP_DEFAULT_TOCLIENT_CHUNK_SIZE
@ STREAM_3WHS_WRONG_SEQ_WRONG_ACK
void ExceptionPolicySetStatsCounters(ThreadVars *tv, ExceptionPolicyCounters *counter, ExceptionPolicyStatsSetts *setting, enum ExceptionPolicy conf_policy, const char *default_str, bool(*isExceptionPolicyValid)(enum ExceptionPolicy))
int SCConfGetNonNull(const char *name, const char **vptr)
Retrieve the non-null value of a configuration node.
Per thread variable structure.
@ STREAM_3WHS_SYN_TOCLIENT_ON_SYN_RECV
TmEcode StreamTcp(ThreadVars *tv, Packet *p, void *data, PacketQueueNoLock *pq)
ExceptionPolicyStatsSetts stream_memcap_eps_stats
void StreamingBufferClear(StreamingBuffer *sb, const StreamingBufferConfig *cfg)
int StreamTcpPacket(ThreadVars *tv, Packet *p, StreamTcpThread *stt, PacketQueueNoLock *pq)
@ STREAM_3WHS_SYNACK_IN_WRONG_DIRECTION
void StatsCounterIncr(StatsThreadContext *stats, StatsCounterId id)
Increments the local counter.
@ STREAM_LASTACK_ACK_WRONG_SEQ
#define FLOW_WRONG_THREAD
const char * PktSrcToString(enum PktSrcEnum pkt_src)
bool valid_settings_ids[EXCEPTION_POLICY_MAX]
#define STREAM_PKT_FLAG_TCP_ZERO_WIN_PROBE_ACK
int StreamTcpSegmentForEach(const Packet *p, uint8_t flag, StreamSegmentCallback CallbackFunc, void *data)
#define SCLogWarning(...)
Macro used to log WARNING messages.
#define STREAM_PKT_FLAG_STATE_UPDATE
#define STREAMTCP_STREAM_FLAG_TIMESTAMP
@ STREAM_FIN2_INVALID_ACK
TcpStreamCnf stream_config
#define RB_FOREACH(x, name, head)
enum ExceptionPolicy ExceptionPolicyMidstreamParse(bool midstream_enabled)
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
int PacketCallocExtPkt(Packet *p, int datalen)
void StreamTcpSessionClear(void *ssnptr)
Function to return the stream back to the pool. It returns the segments in the stream to the segment ...
@ STREAM_FIN1_INVALID_ACK
@ PKT_SRC_STREAM_TCP_DETECTLOG_FLUSH
#define STREAMTCP_QUEUE_FLAG_SACK
uint8_t max_synack_queued
int StreamTcpSackUpdatePacket(TcpStream *stream, Packet *p)
Update stream with SACK records from a TCP packet.
#define DEBUG_ASSERT_FLOW_LOCKED(f)
@ PKT_DROP_REASON_STREAM_ERROR
#define PKT_IGNORE_CHECKSUM
StatsCounterId counter_tcp_ack_unseen_data
void StreamTcpReassembleFreeThreadCtx(TcpReassemblyThreadCtx *ra_ctx)
void PcapIncreaseInvalidChecksum(void)
#define STREAM_PKT_FLAG_KEEPALIVE
#define STREAMTCP_DEFAULT_MEMCAP
StatsCounterId counter_tcp_pseudo
@ STREAM_EST_SYNACK_RESEND
#define FLOW_PKT_TOCLIENT
enum ExceptionPolicy reassembly_memcap_policy
int RunmodeIsUnittests(void)
#define STREAMING_BUFFER_INITIALIZER
void StreamTcpReassembleFree(bool quiet)
#define WarnInvalidConfEntry(param_name, format, value)
Generic API that can be used by all to log an invalid conf entry.
void FlowUpdateState(Flow *f, const enum FlowState s)
@ STREAM_PKT_BAD_WINDOW_UPDATE
StatsCounterId counter_tcp_urgent_oob
StatsCounterId counter_tcp_midstream_pickups
@ STREAM_CLOSEWAIT_ACK_OUT_OF_WINDOW
int ReCalculateChecksum(Packet *p)
enum ExceptionPolicy StreamTcpReassemblyMemcapGetExceptionPolicy(void)
#define SCTIME_CMP_LT(a, b)
@ STREAM_EST_PKT_BEFORE_LAST_ACK
PoolThread * PoolThreadInit(int threads, uint32_t size, uint32_t prealloc_size, uint32_t elt_size, void *(*Alloc)(void), int(*Init)(void *), void(*Cleanup)(void *))
per thread Pool, initialization function
@ STREAM_3WHS_SYNACK_TFO_DATA_IGNORED
ExceptionPolicyStatsSetts stream_midstream_disabled_eps_stats
@ STREAM_3WHS_RIGHT_SEQ_WRONG_ACK_EVASION
void PacketEnqueueNoLock(PacketQueueNoLock *qnl, Packet *p)
@ STREAM_SUSPECTED_RST_INJECT
int StreamTcpSetMemcap(uint64_t size)
Update memcap value.
#define STREAMTCP_FLAG_CLOSED_BY_RST
StatsCounterId counter_tcp_reass_overlap_diff_data
#define STREAMTCP_FLAG_TIMESTAMP
int FlowSetProtoFreeFunc(uint8_t, void(*Free)(void *))
Function to set the function to get protocol specific flow state.
void StreamTcpFreeConfig(bool quiet)
@ STREAM_4WHS_INVALID_ACK
bool StreamTcpSackPacketIsOutdated(TcpStream *stream, Packet *p)
@ STREAM_CLOSEWAIT_PKT_BEFORE_LAST_ACK
StatsCounterId counter_tcp_wrong_thread
#define STREAM_PKT_FLAG_TCP_ZERO_WIN_PROBE
#define STREAMTCP_SET_RA_BASE_SEQ(stream, seq)
void StreamTcpDisableAppLayer(Flow *f)
enum TcpStreamUrgentHandling urgent_oob_limit_policy
#define PKT_STREAM_NOPCAPLOG
#define STREAMTCP_DEFAULT_REASSEMBLY_MEMCAP
@ STREAM_PKT_SPURIOUS_RETRANSMISSION
uint32_t prealloc_sessions
@ STREAM_3WHS_SYNACK_TOSERVER_ON_SYN_RECV
#define STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED
uint8_t md5_option_present
#define STREAMTCP_FLAG_MIDSTREAM_SYNACK
StatsCounterId counter_tcp_segment_from_cache
int StreamTcpReassembleHandleSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, TcpSession *ssn, TcpStream *stream, Packet *p)
int ParseSizeStringU32(const char *size, uint32_t *res)
uint16_t reassembly_toclient_chunk_size
void FlowSwap(Flow *f)
swap the flow's direction
void StreamTcpDetectLogFlush(ThreadVars *tv, StreamTcpThread *stt, Flow *f, Packet *p, PacketQueueNoLock *pq)
create packets in both directions to flush out logging and detection before switching protocols....
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
@ STREAM_CLOSEWAIT_INVALID_ACK
ExceptionPolicyStatsSetts stream_midstream_enabled_eps_stats
StatsCounterId counter_tcp_stream_depth
StatsCounterId counter_tcp_sessions
#define STREAM_PKT_FLAG_ACK_UNSEEN_DATA
#define PKT_PSEUDO_DETECTLOG_FLUSH
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
#define SCLogError(...)
Macro used to log ERROR messages.
#define STREAMTCP_QUEUE_FLAG_TS
#define STREAMTCP_DEFAULT_MAX_SYNACK_QUEUED
TcpSegmentPcapHdrStorage * pcap_hdr_storage
enum ExceptionPolicy StreamMidstreamGetExceptionPolicy(void)
bool valid_settings_ips[EXCEPTION_POLICY_MAX]
void TcpSessionSetReassemblyDepth(TcpSession *ssn, uint32_t size)
StatsCounterId counter_tcp_ssn_from_cache
#define STREAM_PKT_FLAG_SPURIOUS_RETRANSMISSION
uint32_t app_progress_rel
void StreamTcpSessionCleanup(TcpSession *ssn)
Session cleanup function. Does not free the ssn.
ExceptionPolicyStatsSetts stream_reassembly_memcap_eps_stats
uint64_t StreamTcpMemuseCounter(void)
#define StreamTcpUpdateNextWin(ssn, stream, win)
macro to update next_win only if the new value is higher
enum ExceptionPolicy StreamTcpSsnMemcapGetExceptionPolicy(void)
@ STREAM_PKT_RETRANSMISSION
Packet * PacketPoolGetPacket(void)
Get a new packet from the packet pool.
void StreamTcpThreadCacheEnable(void)
enable segment cache. Should only be done for worker threads
#define FLOW_PKT_ESTABLISHED
int SCHInfoGetIPv4HostOSFlavour(uint8_t *addr)
Retrieves the host os flavour, given an ipv4 address in the raw address format.
uint64_t StreamTcpGetMemcap(void)
Return memcap value.
TcpReassemblyThreadCtx * ra_ctx
uint16_t stream_init_flags
void StreamTcpReturnStreamSegments(TcpStream *)
return all segments in this stream into the pool(s)
#define STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP
void PacketDrop(Packet *p, const uint8_t action, enum PacketDropReason r)
issue drop action
void * PoolThreadGetById(PoolThread *pt, uint16_t id)
get data from thread pool by thread id
ExceptionPolicyCounters counter_tcp_ssn_memcap_eps
#define AppLayerProfilingReset(app_tctx)
int EngineModeIsIPS(void)
StatsCounterId counter_tcp_invalid_checksum
#define STREAM_PKT_FLAG_SET(p, f)
#define STREAMTCP_FLAG_APP_LAYER_DISABLED
#define STREAMTCP_STREAM_FLAG_NOREASSEMBLY
#define STREAMTCP_DEFAULT_TOSERVER_CHUNK_SIZE
@ STREAM_CLOSING_INVALID_ACK
const char * StreamTcpStateAsString(const enum TcpState state)
uint16_t vlan_id[VLAN_MAX_LAYERS]
#define STREAMTCP_FLAG_3WHS_CONFIRMED
#define STREAMTCP_INIT_FLAG_CHECKSUM_VALIDATION
#define PKT_NOPACKET_INSPECTION
#define TCP_HAS_WSCALE(p)
#define STREAMTCP_STREAM_FLAG_DISABLE_RAW
uint16_t vlan_id[VLAN_MAX_LAYERS]
@ TCP_STREAM_URGENT_INLINE
#define STREAM_APP_PROGRESS(stream)
#define STREAMTCP_FLAG_ZWP_TS
#define OS_POLICY_DEFAULT
@ STREAM_TIMEWAIT_ACK_WRONG_SEQ
@ STREAM_EST_SYN_TOCLIENT
@ STREAM_3WHS_ACK_DATA_INJECT
#define STREAMTCP_FLAG_4WHS
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
@ STREAM_FIN2_ACK_WRONG_SEQ
@ PKT_DROP_REASON_STREAM_MIDSTREAM
@ STREAM_EST_SYNACK_TOSERVER
#define SCLogNotice(...)
Macro used to log NOTICE messages.
void StreamingBufferSegmentGetData(const StreamingBuffer *sb, const StreamingBufferSegment *seg, const uint8_t **data, uint32_t *data_len)
AppProto alproto
application level protocol
#define STREAMTCP_STREAM_FLAG_TRIGGER_RAW
int PoolThreadSize(PoolThread *pt)
get size of PoolThread (number of 'threads', so array elements)
#define TCP_GET_RAW_ACK(tcph)
void StreamTcpDecrMemuse(uint64_t size)
uint64_t StreamTcpReassembleMemuseGlobalCounter(void)
#define STREAMTCP_INIT_FLAG_BYPASS
ExceptionPolicyCounters counter_tcp_midstream_eps
StatsCounterId eps_id[EXCEPTION_POLICY_MAX]
uint16_t reassembly_toserver_chunk_size
#define DEBUG_VALIDATE_BUG_ON(exp)
#define STREAM_PKT_FLAG_WINDOWUPDATE
union PacketL4::L4Vars vars
#define STREAMTCP_FLAG_TCP_FAST_OPEN
#define STREAMTCP_INIT_FLAG_INLINE
TmEcode StreamTcpThreadDeinit(ThreadVars *tv, void *data)
#define STREAMTCP_DEFAULT_PREALLOC
@ STREAM_3WHS_SYNACK_RESEND_WITH_DIFFERENT_ACK
FlowThreadId thread_id[2]
#define STREAMTCP_FLAG_SERVER_WSCALE
#define FLOW_COPY_IPV4_ADDR_TO_PACKET(fa, pa)
void StreamTcpSetDisableRawReassemblyFlag(TcpSession *ssn, char direction)
Set the No reassembly flag for the given direction in given TCP session.
void StreamTcpSetSessionBypassFlag(TcpSession *ssn)
enable bypass
int StreamTcpBypassEnabled(void)