85 #define STREAMTCP_DEFAULT_PREALLOC 2048
86 #define STREAMTCP_DEFAULT_MEMCAP (64 * 1024 * 1024)
87 #define STREAMTCP_DEFAULT_REASSEMBLY_MEMCAP (256 * 1024 * 1024)
88 #define STREAMTCP_DEFAULT_TOSERVER_CHUNK_SIZE 2560
89 #define STREAMTCP_DEFAULT_TOCLIENT_CHUNK_SIZE 2560
90 #define STREAMTCP_DEFAULT_MAX_SYN_QUEUED 10
91 #define STREAMTCP_DEFAULT_MAX_SYNACK_QUEUED 5
107 .valid_settings_ips = {
135 .valid_settings_ips = {
163 .valid_settings_ips = {
191 .valid_settings_ips = {
215 static int StreamTcpStateDispatch(
224 static uint64_t ssn_pool_cnt = 0;
244 #if defined(DEBUG_VALIDATION) && defined(UNITTESTS)
247 BUG_ON(presize > UINT_MAX);
253 #if defined(DEBUG_VALIDATION) && defined(UNITTESTS)
256 BUG_ON(postsize > presize);
277 if (memcapcopy == 0 || size +
SC_ATOMIC_GET(st_memuse) <= memcapcopy)
289 if (size == 0 || (uint64_t)
SC_ATOMIC_GET(st_memuse) < size) {
310 if (stream != NULL) {
317 static void StreamTcp3wsFreeQueue(
TcpSession *ssn)
344 StreamTcp3wsFreeQueue(ssn);
405 static void *StreamTcpSessionPoolAlloc(
void)
419 static int StreamTcpSessionPoolInit(
void *data,
void* initdata)
429 static void StreamTcpSessionPoolCleanup(
void *s)
443 static inline bool StreamTcpInlineDropInvalid(
void)
454 static inline bool StreamTcpInlineDropUrg(
void)
463 static int RandomGetWrap(
void)
469 }
while(r >= ULONG_MAX - (ULONG_MAX % RAND_MAX));
499 uint16_t rdrange = 10;
508 if ((
SCConfGetInt(
"stream.max-sessions", &value)) == 1) {
510 "Number of concurrent sessions is now only limited by Flow and "
511 "TCP stream engine memcaps.");
514 if ((
SCConfGetInt(
"stream.prealloc-sessions", &value)) == 1) {
529 SCLogConfig(
"stream \"prealloc-sessions\": %"PRIu32
" (per thread)",
533 const char *temp_stream_memcap_str;
534 if (
SCConfGet(
"stream.memcap", &temp_stream_memcap_str) == 1) {
535 uint64_t stream_memcap_copy;
538 "from conf file - %s. Killing engine",
539 temp_stream_memcap_str);
570 if ((
SCConfGetBool(
"stream.checksum-validation", &csum)) == 1) {
582 "enabled" :
"disabled");
585 const char *temp_stream_inline_str;
586 if (
SCConfGet(
"stream.inline", &temp_stream_inline_str) == 1) {
591 if (strcmp(temp_stream_inline_str,
"auto") == 0) {
614 ?
"enabled" :
"disabled");
627 ?
"enabled" :
"disabled");
630 int drop_invalid = 0;
631 if ((
SCConfGetBool(
"stream.drop-invalid", &drop_invalid)) == 1) {
632 if (drop_invalid == 1) {
639 const char *temp_urgpol = NULL;
640 if (
SCConfGet(
"stream.reassembly.urgent.policy", &temp_urgpol) == 1 && temp_urgpol != NULL) {
641 if (strcmp(temp_urgpol,
"inline") == 0) {
643 }
else if (strcmp(temp_urgpol,
"drop") == 0) {
645 }
else if (strcmp(temp_urgpol,
"oob") == 0) {
647 }
else if (strcmp(temp_urgpol,
"gap") == 0) {
650 FatalError(
"stream.reassembly.urgent.policy: invalid value '%s'", temp_urgpol);
659 const char *temp_urgoobpol = NULL;
660 if (
SCConfGet(
"stream.reassembly.urgent.oob-limit-policy", &temp_urgoobpol) == 1 &&
661 temp_urgoobpol != NULL) {
662 if (strcmp(temp_urgoobpol,
"inline") == 0) {
664 }
else if (strcmp(temp_urgoobpol,
"drop") == 0) {
666 }
else if (strcmp(temp_urgoobpol,
"gap") == 0) {
669 FatalError(
"stream.reassembly.urgent.oob-limit-policy: invalid value '%s'", temp_urgoobpol);
679 if ((
SCConfGetInt(
"stream.max-syn-queued", &value)) == 1) {
680 if (value >= 0 && value <= 255) {
692 if ((
SCConfGetInt(
"stream.max-synack-queued", &value)) == 1) {
693 if (value >= 0 && value <= 255) {
705 const char *temp_stream_reassembly_memcap_str;
706 if (
SCConfGet(
"stream.reassembly.memcap", &temp_stream_reassembly_memcap_str) == 1) {
707 uint64_t stream_reassembly_memcap_copy;
709 &stream_reassembly_memcap_copy) < 0) {
711 "stream.reassembly.memcap "
712 "from conf file - %s. Killing engine",
713 temp_stream_reassembly_memcap_str);
723 SCLogConfig(
"stream.reassembly \"memcap\": %"PRIu64
"",
727 const char *temp_stream_reassembly_depth_str;
728 if (
SCConfGet(
"stream.reassembly.depth", &temp_stream_reassembly_depth_str) == 1) {
732 "stream.reassembly.depth "
733 "from conf file - %s. Killing engine",
734 temp_stream_reassembly_depth_str);
746 if ((
SCConfGetBool(
"stream.reassembly.randomize-chunk-size", &randomize)) == 0) {
754 const char *temp_rdrange;
755 if (
SCConfGet(
"stream.reassembly.randomize-chunk-range", &temp_rdrange) == 1) {
758 "stream.reassembly.randomize-chunk-range "
759 "from conf file - %s. Killing engine",
762 }
else if (rdrange >= 100) {
763 FatalError(
"stream.reassembly.randomize-chunk-range "
764 "must be lower than 100");
769 const char *temp_stream_reassembly_toserver_chunk_size_str;
770 if (
SCConfGet(
"stream.reassembly.toserver-chunk-size",
771 &temp_stream_reassembly_toserver_chunk_size_str) == 1) {
775 "stream.reassembly.toserver-chunk-size "
776 "from conf file - %s. Killing engine",
777 temp_stream_reassembly_toserver_chunk_size_str);
786 long int r = RandomGetWrap();
791 const char *temp_stream_reassembly_toclient_chunk_size_str;
792 if (
SCConfGet(
"stream.reassembly.toclient-chunk-size",
793 &temp_stream_reassembly_toclient_chunk_size_str) == 1) {
797 "stream.reassembly.toclient-chunk-size "
798 "from conf file - %s. Killing engine",
799 temp_stream_reassembly_toclient_chunk_size_str);
808 long int r = RandomGetWrap();
814 SCLogConfig(
"stream.reassembly \"toserver-chunk-size\": %"PRIu16,
816 SCLogConfig(
"stream.reassembly \"toclient-chunk-size\": %"PRIu16,
821 if (
SCConfGetBool(
"stream.reassembly.raw", &enable_raw) == 1) {
829 SCLogConfig(
"stream.reassembly.raw: %s", enable_raw ?
"enabled" :
"disabled");
833 int liberal_timestamps = 0;
834 if (
SCConfGetBool(
"stream.liberal-timestamps", &liberal_timestamps) == 1) {
838 SCLogConfig(
"stream.liberal-timestamps: %s", liberal_timestamps ?
"enabled" :
"disabled");
858 StreamTcpSessionPoolAlloc,
859 StreamTcpSessionPoolInit, NULL,
860 StreamTcpSessionPoolCleanup, NULL);
879 SCLogDebug(
"ssn_pool_cnt %"PRIu64
"", ssn_pool_cnt);
882 static bool IsReassemblyMemcapExceptionPolicyStatsValid(
enum ExceptionPolicy exception_policy)
890 static bool IsStreamTcpSessionMemcapExceptionPolicyStatsValid(
enum ExceptionPolicy policy)
898 static void StreamTcpSsnMemcapExceptionPolicyStatsIncr(
957 if (
unlikely((g_eps_stream_ssn_memcap != UINT64_MAX &&
958 g_eps_stream_ssn_memcap ==
t_pcapcnt))) {
973 const TCPHdr *tcph = PacketGetTCP(p);
1007 switch(ssn->
state) {
1032 if (PacketIsIPv4(p)) {
1042 }
else if (PacketIsIPv6(p)) {
1068 #define StreamTcpUpdateLastAck(ssn, stream, ack) { \
1069 if (SEQ_GT((ack), (stream)->last_ack)) \
1071 SCLogDebug("ssn %p: last_ack set to %"PRIu32", moved %u forward", (ssn), (ack), (ack) - (stream)->last_ack); \
1072 if ((SEQ_LEQ((stream)->last_ack, (stream)->next_seq) && SEQ_GT((ack),(stream)->next_seq))) { \
1073 SCLogDebug("last_ack just passed next_seq: %u (was %u) > %u", (ack), (stream)->last_ack, (stream)->next_seq); \
1075 SCLogDebug("next_seq (%u) <> last_ack now %d", (stream)->next_seq, (int)(stream)->next_seq - (ack)); \
1077 (stream)->last_ack = (ack); \
1078 StreamTcpSackPruneList((stream)); \
1080 SCLogDebug("ssn %p: no update: ack %u, last_ack %"PRIu32", next_seq %u (state %u)", \
1081 (ssn), (ack), (stream)->last_ack, (stream)->next_seq, (ssn)->state); \
1085 #define StreamTcpAsyncLastAckUpdate(ssn, stream) { \
1086 if ((ssn)->flags & STREAMTCP_FLAG_ASYNC) { \
1087 if (SEQ_GT((stream)->next_seq, (stream)->last_ack)) { \
1088 uint32_t ack_diff = (stream)->next_seq - (stream)->last_ack; \
1089 (stream)->last_ack += ack_diff; \
1090 SCLogDebug("ssn %p: ASYNC last_ack set to %"PRIu32", moved %u forward", \
1091 (ssn), (stream)->next_seq, ack_diff); \
1096 #define StreamTcpUpdateNextSeq(ssn, stream, seq) { \
1097 (stream)->next_seq = seq; \
1098 SCLogDebug("ssn %p: next_seq %" PRIu32, (ssn), (stream)->next_seq); \
1099 StreamTcpAsyncLastAckUpdate((ssn), (stream)); \
1109 #define StreamTcpUpdateNextWin(ssn, stream, win) { \
1110 uint32_t sacked_size__ = StreamTcpSackedSize((stream)); \
1111 if (SEQ_GT(((win) + sacked_size__), (stream)->next_win)) { \
1112 (stream)->next_win = ((win) + sacked_size__); \
1113 SCLogDebug("ssn %p: next_win set to %"PRIu32, (ssn), (stream)->next_win); \
1121 SCLogDebug(
"ssn %p: (state: %s) Reset received and state changed to "
1125 static bool IsMidstreamExceptionPolicyStatsValid(
enum ExceptionPolicy policy)
1139 static void StreamTcpMidstreamExceptionPolicyStatsIncr(
1148 static int StreamTcpPacketIsRetransmission(
TcpStream *stream,
Packet *p)
1153 const TCPHdr *tcph = PacketGetTCP(p);
1191 static int StreamTcpPacketStateNone(
1194 const TCPHdr *tcph = PacketGetTCP(p);
1197 SCLogDebug(
"RST packet received, no session setup");
1207 SCLogDebug(
"FIN packet received, no session setup");
1213 SCLogDebug(
"FIN packet received, no session setup");
1230 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1262 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
", "
1263 "ssn->server.next_win %" PRIu32
"",
1265 SCLogDebug(
"ssn %p: ssn->client.last_ack %" PRIu32
", "
1266 "ssn->server.last_ack %" PRIu32
"",
1274 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1275 "ssn->client.last_ts %" PRIu32
"",
1294 SCLogDebug(
"ssn %p: assuming SACK permitted for both sides", ssn);
1303 SCLogDebug(
"Midstream not enabled, so won't pick up a session");
1308 SCLogDebug(
"Midstream policy not permissive, so won't pick up a session");
1331 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1332 "TCP_SYN_RECV", ssn);
1363 SCLogDebug(
"ssn %p: wscale enabled. client %u server %u",
1367 SCLogDebug(
"ssn %p: ssn->client.isn %"PRIu32
", ssn->client.next_seq"
1368 " %"PRIu32
", ssn->client.last_ack %"PRIu32
"", ssn,
1371 SCLogDebug(
"ssn %p: ssn->server.isn %"PRIu32
", ssn->server.next_seq"
1372 " %"PRIu32
", ssn->server.last_ack %"PRIu32
"", ssn,
1381 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1382 "ssn->client.last_ts %" PRIu32
"", ssn,
1400 SCLogDebug(
"ssn %p: SYN/ACK with SACK permitted, assuming "
1401 "SACK permitted for both sides", ssn);
1419 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_SYN_SENT", ssn);
1452 SCLogDebug(
"ssn %p: SACK permitted on SYN packet", ssn);
1459 SCLogDebug(
"ssn: %p (TFO) isn %u base_seq %u next_seq %u payload len %u", ssn,
1466 SCLogDebug(
"ssn %p: ssn->client.isn %" PRIu32
", "
1467 "ssn->client.next_seq %" PRIu32
", ssn->client.last_ack "
1477 SCLogDebug(
"Midstream not enabled, so won't pick up a session");
1482 SCLogDebug(
"Midstream policy not permissive, so won't pick up a session");
1499 SCLogDebug(
"ssn %p: =~ midstream picked ssn state is now "
1500 "TCP_ESTABLISHED", ssn);
1521 SCLogDebug(
"ssn %p: ssn->client.isn %u, ssn->client.next_seq %u",
1530 SCLogDebug(
"ssn %p: ssn->client.next_win %"PRIu32
", "
1531 "ssn->server.next_win %"PRIu32
"", ssn,
1533 SCLogDebug(
"ssn %p: ssn->client.last_ack %"PRIu32
", "
1534 "ssn->server.last_ack %"PRIu32
"", ssn,
1542 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1543 "ssn->client.last_ts %" PRIu32
"", ssn,
1562 SCLogDebug(
"ssn %p: assuming SACK permitted for both sides", ssn);
1576 const TCPHdr *tcph = PacketGetTCP(p);
1606 StreamTcp3whsSynAckToStateQueue(p, &search);
1614 search.
ts == q->
ts) {
1627 if (StreamTcp3whsFindSynAckBySynAck(ssn, p) != NULL)
1631 SCLogDebug(
"ssn %p: =~ SYN/ACK queue limit reached", ssn);
1637 SCLogDebug(
"ssn %p: =~ SYN/ACK queue failed: stream memcap reached", ssn);
1643 SCLogDebug(
"ssn %p: =~ SYN/ACK queue failed: alloc failed", ssn);
1648 StreamTcp3whsSynAckToStateQueue(p, q);
1662 const TCPHdr *tcph = PacketGetTCP(p);
1697 StreamTcp3whsSynAckToStateQueue(p, &update);
1704 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_SYN_RECV", ssn);
1720 SCLogDebug(
"ssn %p: ssn->server.last_ts %" PRIu32
" "
1721 "ssn->client.last_ts %" PRIu32
"", ssn,
1749 SCLogDebug(
"ssn %p: SACK permitted for session", ssn);
1756 SCLogDebug(
"ssn %p: ssn->server.next_win %" PRIu32
"", ssn,
1758 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
"", ssn,
1760 SCLogDebug(
"ssn %p: ssn->server.isn %" PRIu32
", "
1761 "ssn->server.next_seq %" PRIu32
", "
1762 "ssn->server.last_ack %" PRIu32
" "
1763 "(ssn->client.last_ack %" PRIu32
")", ssn,
1770 SCLogDebug(
"ssn %p: STREAMTCP_FLAG_4WHS unset, normal SYN/ACK"
1771 " so considering 3WHS", ssn);
1782 static inline bool StateSynSentValidateTimestamp(
TcpSession *ssn,
Packet *p)
1792 if (receiver_stream->
last_ts != 0 && ts_echo != 0 &&
1793 ts_echo != receiver_stream->
last_ts)
1795 SCLogDebug(
"%" PRIu64
": ssn %p: BAD TSECR echo %u recv %u", p->
pcap_cnt, ssn, ts_echo,
1800 if (receiver_stream->
last_ts == 0 && ts_echo != 0) {
1801 SCLogDebug(
"%" PRIu64
": ssn %p: BAD TSECR echo %u recv %u", p->
pcap_cnt, ssn, ts_echo,
1812 memset(q, 0,
sizeof(*q));
1833 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1839 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1843 memset(q, 0,
sizeof(*q));
1844 const TCPHdr *tcph = PacketGetTCP(p);
1863 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1870 #if defined(DEBUG_VALIDATION) || defined(DEBUG)
1874 memset(q, 0,
sizeof(*q));
1876 const TCPHdr *tcph = PacketGetTCP(p);
1894 SCLogDebug(
"ssn %p: state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q, q->
seq, q->
win,
1910 SCLogDebug(
"ssn %p: search state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, s, s->
seq, s->
win,
1915 SCLogDebug(
"ssn %p: queue state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u (last:%s)", ssn, q,
1923 }
else if (ignore_ts) {
1943 ssn->
queue = new_head;
1946 tail->next = old_head;
1948 *old_head = *search;
1949 old_head->
next = NULL;
1955 TcpStateQueueInitFromSsnSyn(ssn, &search);
1959 if (ssn->
queue != NULL && StreamTcp3whsFindSyn(ssn, &search, &
tail,
false) != NULL)
1964 SCLogDebug(
"%" PRIu64
": ssn %p: =~ SYN queue limit reached, rotate", p->
pcap_cnt, ssn);
1968 AddAndRotate(ssn,
tail, &search);
1973 SCLogDebug(
"ssn %p: =~ SYN queue failed: stream memcap reached", ssn);
1979 SCLogDebug(
"ssn %p: =~ SYN queue failed: alloc failed", ssn);
1993 SCLogDebug(
"%" PRIu64
": ssn %p: =~ SYN with SEQ %u added (queue_len %u)", p->
pcap_cnt, ssn,
2033 static inline bool StateSynSentCheckSynAck3Whs(
TcpSession *ssn,
Packet *p,
const bool ts_mismatch)
2035 const TCPHdr *tcph = PacketGetTCP(p);
2037 if (seq_match && !ts_mismatch) {
2042 if (ssn->
queue == NULL) {
2047 TcpStateQueueInitFromPktSynAck(p, &search);
2057 SCLogDebug(
"ssn %p: found queued SYN state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q,
2059 StreamTcp3whsStoreSynApplyToSsn(ssn, q);
2064 }
else if (ts_mismatch) {
2078 static inline bool StateSynSentCheckSynAckTFO(
TcpSession *ssn,
Packet *p,
const bool ts_mismatch)
2080 const TCPHdr *tcph = PacketGetTCP(p);
2083 if (seq_match_tfo && !ts_mismatch) {
2085 }
else if (seq_match_nodata && !ts_mismatch) {
2092 if (ssn->
queue == NULL) {
2097 TcpStateQueueInitFromPktSynAck(p, &search);
2107 SCLogDebug(
"ssn %p: found queued SYN state:%p, isn:%u/win:%u/has_ts:%s/tsval:%u", ssn, q,
2109 StreamTcp3whsStoreSynApplyToSsn(ssn, q);
2114 if (!seq_match_tfo && !seq_match_nodata) {
2116 }
else if (ts_mismatch) {
2132 static int StreamTcpPacketStateSynSent(
2136 const TCPHdr *tcph = PacketGetTCP(p);
2142 SCLogDebug(
"%" PRIu64
": ssn %p: SYN/ACK on SYN_SENT state for packet %" PRIu64,
2146 const bool ts_mismatch =
2151 if (StateSynSentCheckSynAck3Whs(ssn, p, ts_mismatch)) {
2152 SCLogDebug(
"ssn %p: ACK match, packet ACK %" PRIu32
" == "
2153 "%" PRIu32
" from stream",
2156 SCLogDebug(
"ssn %p: (3WHS) ACK mismatch, packet ACK %" PRIu32
" != "
2157 "%" PRIu32
" from stream",
2162 if (StateSynSentCheckSynAckTFO(ssn, p, ts_mismatch)) {
2163 SCLogDebug(
"ssn %p: (TFO) ACK matches next_seq, packet ACK %" PRIu32
" == "
2164 "%" PRIu32
" from stream",
2167 SCLogDebug(
"ssn %p: (TFO) ACK mismatch, packet ACK %" PRIu32
" != "
2168 "%" PRIu32
" from stream",
2174 StreamTcp3wsFreeQueue(ssn);
2176 StreamTcp3whsSynAckUpdate(ssn, p, NULL);
2177 SCLogDebug(
"%" PRIu64
": ssn %p: SYN/ACK on SYN_SENT state: accepted", p->
pcap_cnt, ssn);
2184 SCLogDebug(
"ssn %p: SYN/ACK received in the wrong direction", ssn);
2188 SCLogDebug(
"ssn %p: SYN/ACK received on 4WHS session", ssn);
2195 SCLogDebug(
"ssn %p: 4WHS ACK mismatch, packet ACK %" PRIu32
""
2196 " != %" PRIu32
" from stream",
2206 SCLogDebug(
"ssn %p: 4WHS SEQ mismatch, packet SEQ %" PRIu32
""
2207 " != %" PRIu32
" from *first* SYN pkt",
2214 SCLogDebug(
"ssn %p: =~ 4WHS ssn state is now TCP_SYN_RECV", ssn);
2228 SCLogDebug(
"ssn %p: 4WHS ssn->client.last_ts %" PRIu32
" "
2229 "ssn->server.last_ts %" PRIu32
"",
2254 SCLogDebug(
"ssn %p: SACK permitted for 4WHS session", ssn);
2261 SCLogDebug(
"ssn %p: 4WHS ssn->client.isn %" PRIu32
", "
2262 "ssn->client.next_seq %" PRIu32
", "
2263 "ssn->client.last_ack %" PRIu32
" "
2264 "(ssn->server.last_ack %" PRIu32
")",
2273 if (!StateSynSentValidateTimestamp(ssn, p)) {
2281 if (!StreamTcpValidateRst(ssn, p))
2288 SCLogDebug(
"ssn->server.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2290 StreamTcpCloseSsnWithReset(p, ssn);
2291 StreamTcp3wsFreeQueue(ssn);
2295 SCLogDebug(
"ssn->client.flags |= STREAMTCP_STREAM_FLAG_RST_RECV");
2296 StreamTcpCloseSsnWithReset(p, ssn);
2297 StreamTcp3wsFreeQueue(ssn);
2305 SCLogDebug(
"ssn %p: SYN packet on state SYN_SENT... resent", ssn);
2307 SCLogDebug(
"ssn %p: SYN packet on state SYN_SENT... resent of "
2320 SCLogDebug(
"ssn %p: STREAMTCP_FLAG_4WHS flag set", ssn);
2357 SCLogDebug(
"ssn %p: 4WHS ssn->server.isn %" PRIu32
", "
2358 "ssn->server.next_seq %" PRIu32
", "
2359 "ssn->server.last_ack %"PRIu32
"", ssn,
2362 SCLogDebug(
"ssn %p: 4WHS ssn->client.isn %" PRIu32
", "
2363 "ssn->client.next_seq %" PRIu32
", "
2364 "ssn->client.last_ack %"PRIu32
"", ssn,
2373 TcpStateQueueInitFromPktSyn(p, &syn_pkt);
2374 TcpStateQueueInitFromSsnSyn(ssn, &syn_ssn);
2376 if (memcmp(&syn_pkt, &syn_ssn,
sizeof(
TcpStateQueue)) != 0) {
2378 StreamTcp3whsStoreSyn(ssn, p);
2379 SCLogDebug(
"ssn %p: Retransmitted SYN. Updating ssn from packet %" PRIu64
2380 ". Stored previous state",
2383 StreamTcp3whsStoreSynApplyToSsn(ssn, &syn_pkt);
2399 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
2400 "%" PRIu32
" from stream",
2407 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2408 StreamTcp3wsFreeQueue(ssn);
2421 SCLogDebug(
"ssn %p: synsent => Asynchronous stream, packet SEQ"
2422 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2423 "ssn->client.next_seq %" PRIu32
"",
2472 static int StreamTcpPacketStateSynRecv(
2476 const TCPHdr *tcph = PacketGetTCP(p);
2479 if (!StreamTcpValidateRst(ssn, p))
2496 SCLogDebug(
"Detection evasion has been attempted, so"
2497 " not resetting the connection !!");
2505 SCLogDebug(
"Detection evasion has been attempted, so"
2506 " not resetting the connection !!");
2512 StreamTcpCloseSsnWithReset(p, ssn);
2515 StreamTcpHandleTimestamp(ssn, p);
2522 if (!StreamTcpValidateTimestamp(ssn, p))
2526 if ((StreamTcpHandleFin(
tv, stt, ssn, p)) == -1)
2531 SCLogDebug(
"ssn %p: SYN/ACK packet on state SYN_RECV. resent", ssn);
2534 SCLogDebug(
"ssn %p: SYN/ACK-pkt to server in SYN_RECV state", ssn);
2543 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
2544 "%" PRIu32
" from stream",
2554 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
2555 "%" PRIu32
" from stream",
2558 if (StreamTcp3whsQueueSynAck(ssn, p) == -1)
2560 SCLogDebug(
"ssn %p: queued different SYN/ACK", ssn);
2564 SCLogDebug(
"ssn %p: SYN packet on state SYN_RECV... resent", ssn);
2567 SCLogDebug(
"ssn %p: SYN-pkt to client in SYN_RECV state", ssn);
2574 SCLogDebug(
"ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
2582 SCLogDebug(
"ssn %p: checking ACK against queued SYN/ACKs", ssn);
2585 SCLogDebug(
"ssn %p: here we update state against queued SYN/ACK", ssn);
2586 StreamTcp3whsSynAckUpdate(ssn, p, q);
2588 SCLogDebug(
"ssn %p: none found, now checking ACK against original SYN/ACK (state)", ssn);
2598 if (!(StreamTcpValidateTimestamp(ssn, p))) {
2604 SCLogDebug(
"ssn %p: ACK received on 4WHS session",ssn);
2607 SCLogDebug(
"ssn %p: 4WHS wrong seq nr on packet", ssn);
2612 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
2613 SCLogDebug(
"ssn %p: 4WHS invalid ack nr on packet", ssn);
2619 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
2620 "%" PRIu32
", ACK %" PRIu32
"",
2624 StreamTcpHandleTimestamp(ssn, p);
2633 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2637 SCLogDebug(
"ssn %p: ssn->client.next_win %" PRIu32
", "
2638 "ssn->client.last_ack %"PRIu32
"", ssn,
2643 bool ack_indicates_missed_3whs_ack_packet =
false;
2653 SCLogDebug(
"ssn %p: ACK received on midstream SYN/ACK "
2654 "pickup session",ssn);
2657 SCLogDebug(
"ssn %p: ACK received on TFO session",ssn);
2674 SCLogDebug(
"ssn %p: possible data injection", ssn);
2679 SCLogDebug(
"ssn %p: ACK received in the wrong direction",
2684 ack_indicates_missed_3whs_ack_packet =
true;
2688 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ %" PRIu32
""
2689 ", ACK %" PRIu32
"",
2701 StreamTcpHandleTimestamp(ssn, p);
2725 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2751 StreamTcpHandleTimestamp(ssn, p);
2764 SCLogDebug(
"ssn %p: synrecv => Asynchronous stream, packet SEQ"
2765 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2766 "ssn->server.next_seq %" PRIu32,
2771 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2780 SCLogDebug(
"ssn %p: wrong ack nr on packet, possible evasion!!",
2790 SCLogDebug(
"ssn %p: ACK for missing data", ssn);
2793 StreamTcpHandleTimestamp(ssn, p);
2799 SCLogDebug(
"ssn %p: ACK for missing data: ssn->server.next_seq %u", ssn,
2809 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2818 SCLogDebug(
"ssn %p: ACK for missing data", ssn);
2821 StreamTcpHandleTimestamp(ssn, p);
2843 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2848 }
else if ((ack_indicates_missed_3whs_ack_packet ||
2852 if (ack_indicates_missed_3whs_ack_packet) {
2853 SCLogDebug(
"ssn %p: packet fits perfectly after a missed 3whs-ACK", ssn);
2855 SCLogDebug(
"ssn %p: (TFO) expected packet fits perfectly after SYN/ACK", ssn);
2864 SCLogDebug(
"ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn);
2869 SCLogDebug(
"ssn %p: wrong seq nr on packet", ssn);
2875 SCLogDebug(
"ssn %p: ssn->server.next_win %" PRIu32
", "
2876 "ssn->server.last_ack %"PRIu32
"", ssn,
2898 static int HandleEstablishedPacketToServer(
2901 const TCPHdr *tcph = PacketGetTCP(p);
2906 SCLogDebug(
"ssn %p: =+ pkt (%" PRIu32
") is to server: SEQ %" PRIu32
","
2907 "ACK %" PRIu32
", WIN %" PRIu16
"",
2913 SCLogDebug(
"ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
2916 }
else if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
2917 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
2925 SCLogDebug(
"ssn %p: pkt is keep alive", ssn);
2930 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ"
2931 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
2932 " ssn->client.last_ack %" PRIu32
", ssn->client.next_win"
2933 "%" PRIu32
"(%" PRIu32
")",
2943 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ."
2944 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2945 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2946 "%" PRIu32
"(%" PRIu32
")",
2958 SCLogDebug(
"ssn %p: server => Asynchronous stream, packet SEQ"
2959 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2960 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2961 "%" PRIu32
"(%" PRIu32
")",
2976 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
2977 " before last_ack %" PRIu32
", after next_seq %" PRIu32
":"
2978 " acked data that we haven't seen before",
2981 SCLogDebug(
"ssn %p: server => SEQ before last_ack, packet SEQ"
2982 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"), "
2983 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
2984 "%" PRIu32
"(%" PRIu32
")",
2988 SCLogDebug(
"ssn %p: rejecting because pkt before last_ack", ssn);
2994 int zerowindowprobe = 0;
2997 SCLogDebug(
"ssn %p: zero window probe", ssn);
2998 zerowindowprobe = 1;
3008 if (zerowindowprobe) {
3009 SCLogDebug(
"ssn %p: zero window probe, skipping oow check", ssn);
3012 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
3017 SCLogDebug(
"ssn %p: ssn->server.window %"PRIu32
"", ssn,
3034 StreamTcpHandleTimestamp(ssn, p);
3046 SCLogDebug(
"ssn %p: toserver => SEQ out of window, packet SEQ "
3047 "%" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3048 "ssn->client.last_ack %" PRIu32
", ssn->client.next_win "
3049 "%" PRIu32
"(%" PRIu32
")",
3053 StreamTcpSackedSize(&ssn->
client));
3073 static int HandleEstablishedPacketToClient(
3076 const TCPHdr *tcph = PacketGetTCP(p);
3081 SCLogDebug(
"ssn %p: =+ pkt (%" PRIu32
") is to client: SEQ %" PRIu32
","
3082 " ACK %" PRIu32
", WIN %" PRIu16
"",
3088 SCLogDebug(
"ssn %p: accepting ACK as it ACKs the one byte from the ZWP", ssn);
3091 }
else if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3092 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3106 SCLogDebug(
"ssn %p: adjusted midstream ssn->server.next_win to "
3112 SCLogDebug(
"ssn %p: pkt is keep alive", ssn);
3118 SCLogDebug(
"ssn %p: client => Asynchronous stream, packet SEQ"
3119 " %" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3120 " ssn->client.last_ack %" PRIu32
", ssn->client.next_win"
3121 " %" PRIu32
"(%" PRIu32
")",
3132 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
3133 " before last_ack %" PRIu32
", after next_seq %" PRIu32
":"
3134 " acked data that we haven't seen before",
3137 SCLogDebug(
"ssn %p: PKT SEQ %" PRIu32
" payload_len %" PRIu16
3138 " before last_ack %" PRIu32
". next_seq %" PRIu32,
3145 int zerowindowprobe = 0;
3148 SCLogDebug(
"ssn %p: zero window probe", ssn);
3149 zerowindowprobe = 1;
3160 if (zerowindowprobe) {
3161 SCLogDebug(
"ssn %p: zero window probe, skipping oow check", ssn);
3164 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
3168 SCLogDebug(
"ssn %p: ssn->client.window %"PRIu32
"", ssn,
3181 StreamTcpHandleTimestamp(ssn, p);
3190 SCLogDebug(
"ssn %p: client => SEQ out of window, packet SEQ"
3191 "%" PRIu32
", payload size %" PRIu32
" (%" PRIu32
"),"
3192 " ssn->server.last_ack %" PRIu32
", ssn->server.next_win "
3193 "%" PRIu32
"(%" PRIu32
")",
3202 static bool StreamTcpPacketIsZeroWindowProbeAck(
const TcpSession *ssn,
const Packet *p)
3204 const TCPHdr *tcph = PacketGetTCP(p);
3228 if (pkt_win != rcv->
window)
3235 SCLogDebug(
"ssn %p: packet %" PRIu64
" is a Zero Window Probe ACK", ssn, p->
pcap_cnt);
3242 static bool StreamTcpPacketIsDupAck(
const TcpSession *ssn,
const Packet *p)
3244 const TCPHdr *tcph = PacketGetTCP(p);
3262 if (pkt_win == 0 || rcv->
window == 0)
3264 if (pkt_win != rcv->
window)
3272 SCLogDebug(
"ssn %p: packet:%" PRIu64
" seq:%u ack:%u win:%u snd %u:%u:%u rcv %u:%u:%u", ssn,
3296 const TCPHdr *tcph = PacketGetTCP(p);
3347 static int StreamTcpPacketIsSpuriousRetransmission(
const TcpSession *ssn,
Packet *p)
3358 const TCPHdr *tcph = PacketGetTCP(p);
3364 "ssn %p: spurious retransmission; packet entirely before base_seq: SEQ %u(%u) "
3365 "last_ack %u base_seq %u",
3374 SCLogDebug(
"ssn %p: spurious retransmission; packet entirely before last_ack: SEQ %u(%u) "
3382 SCLogDebug(
"ssn %p: NOT spurious retransmission; packet NOT entirely before last_ack: SEQ "
3383 "%u(%u) last_ack %u, base_seq %u",
3400 static int StreamTcpPacketStateEstablished(
3404 const TCPHdr *tcph = PacketGetTCP(p);
3410 if (!StreamTcpValidateRst(ssn, p))
3414 StreamTcpCloseSsnWithReset(p, ssn);
3418 SCLogDebug(
"ssn %p: ssn->server.next_seq %" PRIu32
"", ssn,
3428 StreamTcpHandleTimestamp(ssn, p);
3432 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3440 StreamTcpCloseSsnWithReset(p, ssn);
3445 SCLogDebug(
"ssn %p: ssn->server.next_seq %" PRIu32
"", ssn,
3455 StreamTcpHandleTimestamp(ssn, p);
3459 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3470 if (!StreamTcpValidateTimestamp(ssn, p))
3475 " %" PRIu32
", last ACK %" PRIu32
", next win %"PRIu32
","
3480 if ((StreamTcpHandleFin(
tv, stt, ssn, p)) == -1)
3485 SCLogDebug(
"ssn %p: SYN/ACK packet on state ESTABLISHED... resent",
3489 SCLogDebug(
"ssn %p: SYN/ACK-pkt to server in ESTABLISHED state", ssn);
3498 SCLogDebug(
"ssn %p: ACK mismatch, packet ACK %" PRIu32
" != "
3499 "%" PRIu32
" from stream",
3509 SCLogDebug(
"ssn %p: SEQ mismatch, packet SEQ %" PRIu32
" != "
3510 "%" PRIu32
" from stream",
3523 SCLogDebug(
"ssn %p: SYN/ACK packet on state ESTABLISHED... resent. "
3524 "Likely due server not receiving final ACK in 3whs", ssn);
3528 SCLogDebug(
"ssn %p: SYN packet on state ESTABLISHED... resent", ssn);
3530 SCLogDebug(
"ssn %p: SYN-pkt to client in EST state", ssn);
3537 SCLogDebug(
"ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
3558 if (!StreamTcpValidateTimestamp(ssn, p))
3564 HandleEstablishedPacketToServer(
tv, ssn, p, stt);
3566 SCLogDebug(
"ssn %p: next SEQ %" PRIu32
", last ACK %" PRIu32
","
3567 " next win %" PRIu32
", win %" PRIu32
"", ssn,
3574 SCLogDebug(
"3whs is now confirmed by server");
3578 HandleEstablishedPacketToClient(
tv, ssn, p, stt);
3580 SCLogDebug(
"ssn %p: next SEQ %" PRIu32
", last ACK %" PRIu32
","
3581 " next win %" PRIu32
", win %" PRIu32
"", ssn,
3606 const TCPHdr *tcph = PacketGetTCP(p);
3612 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ %" PRIu32
","
3616 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3617 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3623 SCLogDebug(
"ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn,
seq, pkt_re,
3628 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
" != "
3629 "%" PRIu32
" from stream",
3642 SCLogDebug(
"ssn %p: state changed to TCP_CLOSE_WAIT", ssn);
3647 SCLogDebug(
"ssn %p: ssn->client.next_seq %" PRIu32
"", ssn,
3652 StreamTcpHandleTimestamp(ssn, p);
3665 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK %" PRIu32
"",
3668 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ %" PRIu32
", "
3672 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3673 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3679 SCLogDebug(
"ssn %p: -> SEQ %u, re %u. last_ack %u next_win %u", ssn,
seq, pkt_re,
3684 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
" != "
3685 "%" PRIu32
" from stream (last_ack %u win %u = %u)",
3694 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT1", ssn);
3703 StreamTcpHandleTimestamp(ssn, p);
3716 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK %" PRIu32
"",
3736 static int StreamTcpPacketStateFinWait1(
3740 const TCPHdr *tcph = PacketGetTCP(p);
3746 if (!StreamTcpValidateRst(ssn, p))
3749 StreamTcpCloseSsnWithReset(p, ssn);
3758 StreamTcpHandleTimestamp(ssn, p);
3769 StreamTcpHandleTimestamp(ssn, p);
3777 if (!StreamTcpValidateTimestamp(ssn, p))
3782 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3783 "%" PRIu32
", ACK %" PRIu32
"",
3785 int retransmission = 0;
3787 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
3788 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3794 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3795 " != %" PRIu32
" from stream",
3801 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3802 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3807 if (!retransmission) {
3809 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
3815 StreamTcpHandleTimestamp(ssn, p);
3831 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3835 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3836 "%" PRIu32
", ACK %" PRIu32
"",
3838 int retransmission = 0;
3840 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
3841 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3846 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3852 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3853 " != %" PRIu32
" from stream",
3859 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3860 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3866 StreamTcpHandleTimestamp(ssn, p);
3869 if (!retransmission) {
3871 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
3889 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3896 if (!StreamTcpValidateTimestamp(ssn, p))
3901 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
3902 "%" PRIu32
", ACK %" PRIu32
"",
3904 int retransmission = 0;
3906 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
3907 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3913 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3914 " != %" PRIu32
" from stream",
3920 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
3921 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3926 if (!retransmission) {
3928 SCLogDebug(
"ssn %p: state changed to TCP_CLOSING", ssn);
3934 StreamTcpHandleTimestamp(ssn, p);
3951 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
3955 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
3956 "%" PRIu32
", ACK %" PRIu32
"",
3959 int retransmission = 0;
3961 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
3962 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
3968 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
3969 " != %" PRIu32
" from stream",
3975 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
3976 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
3981 if (!retransmission) {
3983 SCLogDebug(
"ssn %p: state changed to TCP_CLOSING", ssn);
3989 StreamTcpHandleTimestamp(ssn, p);
4006 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4011 SCLogDebug(
"ssn (%p): SYN pkt on FinWait1", ssn);
4017 if (!StreamTcpValidateTimestamp(ssn, p))
4022 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4023 "%" PRIu32
", ACK %" PRIu32
"",
4025 int retransmission = 0;
4027 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4028 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4033 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4034 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4041 "ssn %p: ACK's older segment as %u < %u", ssn, ack, ssn->
server.
next_seq);
4042 }
else if (!retransmission) {
4046 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
4052 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT2", ssn);
4055 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4056 " != %" PRIu32
" from stream",
4068 StreamTcpHandleTimestamp(ssn, p);
4089 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4095 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4096 "%" PRIu32
", ACK %" PRIu32
"",
4099 int retransmission = 0;
4101 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4102 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4107 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4108 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4113 if (!retransmission) {
4116 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
4122 SCLogDebug(
"ssn %p: state changed to TCP_FIN_WAIT2", ssn);
4125 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4126 " != %" PRIu32
" from stream",
4136 StreamTcpHandleTimestamp(ssn, p);
4157 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4178 static int StreamTcpPacketStateFinWait2(
4182 const TCPHdr *tcph = PacketGetTCP(p);
4188 if (!StreamTcpValidateRst(ssn, p))
4191 StreamTcpCloseSsnWithReset(p, ssn);
4200 StreamTcpHandleTimestamp(ssn, p);
4211 StreamTcpHandleTimestamp(ssn, p);
4219 if (!StreamTcpValidateTimestamp(ssn, p))
4224 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4225 "%" PRIu32
", ACK %" PRIu32
"",
4227 int retransmission = 0;
4233 }
else if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4234 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4240 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ "
4241 "%" PRIu32
" != %" PRIu32
" from stream",
4247 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4248 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4253 if (!retransmission) {
4255 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4265 StreamTcpHandleTimestamp(ssn, p);
4278 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4282 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4283 "%" PRIu32
", ACK %" PRIu32
"",
4285 int retransmission = 0;
4291 }
else if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4292 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4298 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ "
4299 "%" PRIu32
" != %" PRIu32
" from stream",
4305 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4306 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4311 if (!retransmission) {
4313 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4319 StreamTcpHandleTimestamp(ssn, p);
4331 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4337 SCLogDebug(
"ssn (%p): SYN pkt on FinWait2", ssn);
4343 if (!StreamTcpValidateTimestamp(ssn, p))
4348 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4349 "%" PRIu32
", ACK %" PRIu32
"",
4351 int retransmission = 0;
4353 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4354 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4359 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4360 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4365 if (!retransmission) {
4368 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->client.next_win "
4373 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4374 " != %" PRIu32
" from stream",
4384 StreamTcpHandleTimestamp(ssn, p);
4400 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4404 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4405 "%" PRIu32
", ACK %" PRIu32
"",
4407 int retransmission = 0;
4409 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4410 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4415 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4416 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4421 if (!retransmission) {
4424 SCLogDebug(
"ssn %p: seq %" PRIu32
" in window, ssn->server.next_win "
4428 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4429 " != %" PRIu32
" from stream",
4439 StreamTcpHandleTimestamp(ssn, p);
4455 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4476 static int StreamTcpPacketStateClosing(
4480 const TCPHdr *tcph = PacketGetTCP(p);
4486 if (!StreamTcpValidateRst(ssn, p))
4489 StreamTcpCloseSsnWithReset(p, ssn);
4498 StreamTcpHandleTimestamp(ssn, p);
4509 StreamTcpHandleTimestamp(ssn, p);
4516 SCLogDebug(
"ssn (%p): SYN pkt on Closing", ssn);
4522 if (!StreamTcpValidateTimestamp(ssn, p))
4527 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4528 "%" PRIu32
", ACK %" PRIu32
"",
4530 int retransmission = 0;
4531 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4532 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4538 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4539 " != %" PRIu32
" from stream",
4545 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4546 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4551 if (!retransmission) {
4553 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4559 StreamTcpHandleTimestamp(ssn, p);
4569 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4573 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4574 "%" PRIu32
", ACK %" PRIu32
"",
4576 int retransmission = 0;
4577 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4578 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4584 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4585 " != %" PRIu32
" from stream",
4591 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4592 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4597 if (!retransmission) {
4599 SCLogDebug(
"ssn %p: state changed to TCP_TIME_WAIT", ssn);
4605 StreamTcpHandleTimestamp(ssn, p);
4616 SCLogDebug(
"StreamTcpPacketStateClosing (%p): =+ next SEQ "
4617 "%" PRIu32
", last ACK %" PRIu32
"", ssn,
4637 static int StreamTcpPacketStateCloseWait(
4641 const TCPHdr *tcph = PacketGetTCP(p);
4649 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4650 "%" PRIu32
", ACK %" PRIu32
"",
4653 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4654 "%" PRIu32
", ACK %" PRIu32
"",
4659 if (!StreamTcpValidateRst(ssn, p))
4662 StreamTcpCloseSsnWithReset(p, ssn);
4671 StreamTcpHandleTimestamp(ssn, p);
4682 StreamTcpHandleTimestamp(ssn, p);
4690 if (!StreamTcpValidateTimestamp(ssn, p))
4695 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4696 "%" PRIu32
", ACK %" PRIu32
"",
4699 int retransmission = 0;
4700 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4701 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4706 if (!retransmission) {
4709 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4710 " != %" PRIu32
" from stream",
4717 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4718 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4725 if (!retransmission)
4729 StreamTcpHandleTimestamp(ssn, p);
4741 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4745 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4746 "%" PRIu32
", ACK %" PRIu32
"",
4749 int retransmission = 0;
4750 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4751 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4756 if (!retransmission) {
4759 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4760 " != %" PRIu32
" from stream",
4767 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4768 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4773 if (!retransmission) {
4775 SCLogDebug(
"ssn %p: state changed to TCP_LAST_ACK", ssn);
4781 StreamTcpHandleTimestamp(ssn, p);
4793 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4799 SCLogDebug(
"ssn (%p): SYN pkt on CloseWait", ssn);
4805 if (!StreamTcpValidateTimestamp(ssn, p))
4810 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4811 "%" PRIu32
", ACK %" PRIu32
"",
4814 int retransmission = 0;
4815 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4816 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4822 SCLogDebug(
"ssn %p: -> retransmission", ssn);
4827 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4828 " != %" PRIu32
" from stream",
4834 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4835 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4840 if (!retransmission) {
4845 StreamTcpHandleTimestamp(ssn, p);
4859 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4863 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
4864 "%" PRIu32
", ACK %" PRIu32
"",
4866 int retransmission = 0;
4867 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
4868 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4874 SCLogDebug(
"ssn %p: -> retransmission", ssn);
4879 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
4880 " != %" PRIu32
" from stream",
4886 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
4887 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
4892 if (!retransmission) {
4897 StreamTcpHandleTimestamp(ssn, p);
4911 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
4932 static int StreamTcpPacketStateLastAck(
4936 const TCPHdr *tcph = PacketGetTCP(p);
4942 if (!StreamTcpValidateRst(ssn, p))
4945 StreamTcpCloseSsnWithReset(p, ssn);
4954 StreamTcpHandleTimestamp(ssn, p);
4965 StreamTcpHandleTimestamp(ssn, p);
4973 SCLogDebug(
"ssn (%p): FIN pkt on LastAck", ssn);
4976 SCLogDebug(
"ssn (%p): SYN pkt on LastAck", ssn);
4982 if (!StreamTcpValidateTimestamp(ssn, p))
4987 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
4988 "%" PRIu32
", ACK %" PRIu32
"",
4991 int retransmission = 0;
4992 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
4993 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
4998 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
4999 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5004 if (!retransmission) {
5006 SCLogDebug(
"ssn %p: not updating state as packet is before next_seq", ssn);
5008 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5009 " != %" PRIu32
" from stream",
5015 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5021 StreamTcpHandleTimestamp(ssn, p);
5032 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5053 static int StreamTcpPacketStateTimeWait(
5057 const TCPHdr *tcph = PacketGetTCP(p);
5063 if (!StreamTcpValidateRst(ssn, p))
5066 StreamTcpCloseSsnWithReset(p, ssn);
5075 StreamTcpHandleTimestamp(ssn, p);
5086 StreamTcpHandleTimestamp(ssn, p);
5096 SCLogDebug(
"ssn (%p): SYN pkt on TimeWait", ssn);
5102 if (!StreamTcpValidateTimestamp(ssn, p))
5107 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to server: SEQ "
5108 "%" PRIu32
", ACK %" PRIu32
"",
5110 int retransmission = 0;
5111 if (StreamTcpPacketIsRetransmission(&ssn->
client, p)) {
5112 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
5117 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5118 " != %" PRIu32
" from stream",
5124 if (StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
5125 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5130 if (!retransmission) {
5132 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5138 StreamTcpHandleTimestamp(ssn, p);
5149 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5153 SCLogDebug(
"ssn %p: pkt (%" PRIu32
") is to client: SEQ "
5154 "%" PRIu32
", ACK %" PRIu32
"",
5156 int retransmission = 0;
5157 if (StreamTcpPacketIsRetransmission(&ssn->
server, p)) {
5158 SCLogDebug(
"ssn %p: packet is retransmission", ssn);
5163 SCLogDebug(
"ssn %p: -> retransmission", ssn);
5166 SCLogDebug(
"ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32
""
5167 " != %" PRIu32
" from stream",
5174 if (StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
5175 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
5180 if (!retransmission) {
5182 SCLogDebug(
"ssn %p: state changed to TCP_CLOSED", ssn);
5188 StreamTcpHandleTimestamp(ssn, p);
5199 SCLogDebug(
"ssn %p: =+ next SEQ %" PRIu32
", last ACK "
5211 static int StreamTcpPacketStateClosed(
5216 const TCPHdr *tcph = PacketGetTCP(p);
5222 TcpStream *stream = NULL, *ostream = NULL;
5239 if (StreamTcpStateDispatch(
tv, p, stt, ssn, ssn->
pstate) < 0)
5254 const TCPHdr *tcph = PacketGetTCP(p);
5268 SCLogDebug(
"regular packet %"PRIu64
" from same sender as "
5269 "the previous RST. Looks like it injected!", p->
pcap_cnt);
5295 const TCPHdr *tcph = PacketGetTCP(p);
5300 TcpStream *stream = NULL, *ostream = NULL;
5311 if (ack == ostream->last_ack &&
seq == (stream->
next_seq - 1)) {
5327 TcpStream *stream = NULL, *ostream = NULL;
5338 const TCPHdr *tcph = PacketGetTCP(p);
5357 if (pkt_win != ostream->window)
5366 SCLogDebug(
"seq %u (%u), ack %u (%u) FLAG_KEEPALIVE: %s",
seq, stream->
next_seq, ack, ostream->last_ack,
5396 TcpStream *stream = NULL, *ostream = NULL;
5410 const TCPHdr *tcph = PacketGetTCP(p);
5429 if (pkt_win == ostream->window)
5432 if (ack == ostream->last_ack &&
seq == stream->
next_seq) {
5447 TcpStream *stream = NULL, *ostream = NULL;
5455 const TCPHdr *tcph = PacketGetTCP(p);
5472 SCLogDebug(
"%"PRIu64
", seq %u ack %u stream->next_seq %u ostream->next_seq %u",
5500 TcpStream *stream = NULL, *ostream = NULL;
5511 const TCPHdr *tcph = PacketGetTCP(p);
5527 if (pkt_win < ostream->window) {
5528 uint32_t diff = ostream->window - pkt_win;
5530 SEQ_GT(ack, ostream->next_seq) &&
5533 SCLogDebug(
"%"PRIu64
", pkt_win %u, stream win %u, diff %u, dsize %u",
5535 SCLogDebug(
"%"PRIu64
", pkt_win %u, stream win %u",
5536 p->
pcap_cnt, pkt_win, ostream->window);
5537 SCLogDebug(
"%"PRIu64
", seq %u ack %u ostream->next_seq %u ostream->last_ack %u, ostream->next_win %u, diff %u (%u)",
5538 p->
pcap_cnt,
seq, ack, ostream->next_seq, ostream->last_ack, ostream->next_win,
5539 ostream->next_seq - ostream->last_ack, stream->
next_seq - stream->
last_ack);
5546 uint32_t adiff = ack - ostream->last_ack;
5547 if (((pkt_win > 1024) && (diff > (adiff + 32))) ||
5548 ((pkt_win <= 1024) && (diff > adiff)))
5550 SCLogDebug(
"pkt ACK %u is %u bytes beyond last_ack %u, shrinks window by %u "
5551 "(allowing 32 bytes extra): pkt WIN %u", ack, adiff, ostream->last_ack, diff, pkt_win);
5552 SCLogDebug(
"%u - %u = %u (state %u)", diff, adiff, diff - adiff, ssn->
state);
5567 static inline int StreamTcpStateDispatch(
5575 SCLogDebug(
"packet received on TCP_SYN_SENT state");
5576 if (StreamTcpPacketStateSynSent(
tv, p, stt, ssn)) {
5581 SCLogDebug(
"packet received on TCP_SYN_RECV state");
5582 if (StreamTcpPacketStateSynRecv(
tv, p, stt, ssn)) {
5587 SCLogDebug(
"packet received on TCP_ESTABLISHED state");
5588 if (StreamTcpPacketStateEstablished(
tv, p, stt, ssn)) {
5593 SCLogDebug(
"packet received on TCP_FIN_WAIT1 state");
5594 if (StreamTcpPacketStateFinWait1(
tv, p, stt, ssn)) {
5599 SCLogDebug(
"packet received on TCP_FIN_WAIT2 state");
5600 if (StreamTcpPacketStateFinWait2(
tv, p, stt, ssn)) {
5605 SCLogDebug(
"packet received on TCP_CLOSING state");
5606 if (StreamTcpPacketStateClosing(
tv, p, stt, ssn)) {
5611 SCLogDebug(
"packet received on TCP_CLOSE_WAIT state");
5612 if (StreamTcpPacketStateCloseWait(
tv, p, stt, ssn)) {
5617 SCLogDebug(
"packet received on TCP_LAST_ACK state");
5618 if (StreamTcpPacketStateLastAck(
tv, p, stt, ssn)) {
5623 SCLogDebug(
"packet received on TCP_TIME_WAIT state");
5624 if (StreamTcpPacketStateTimeWait(
tv, p, stt, ssn)) {
5630 SCLogDebug(
"packet received on closed state");
5632 if (StreamTcpPacketStateClosed(
tv, p, stt, ssn)) {
5638 SCLogDebug(
"packet received on default state");
5674 const TCPHdr *tcph = PacketGetTCP(p);
5689 SCLogDebug(
"ssn %p: removing ASYNC flag as we have packets on both sides", ssn);
5709 if (StreamTcpCheckFlowDrops(p) == 1) {
5719 if (StreamTcpPacketStateNone(
tv, p, stt, ssn) == -1) {
5745 if (StreamTcpPacketIsKeepAlive(ssn, p) == 1) {
5748 if (StreamTcpPacketIsKeepAliveACK(ssn, p) == 1) {
5749 StreamTcpClearKeepAliveFlag(ssn, p);
5752 StreamTcpClearKeepAliveFlag(ssn, p);
5754 const bool is_zwp_ack = StreamTcpPacketIsZeroWindowProbeAck(ssn, p);
5765 if (StreamTcpPacketIsDupAck(ssn, p)) {
5772 if (StreamTcpPacketIsFinShutdownAck(ssn, p) == 0) {
5773 if (StreamTcpPacketIsWindowUpdate(ssn, p) == 0) {
5774 if (StreamTcpPacketIsBadWindowUpdate(ssn,p))
5776 if (StreamTcpPacketIsOutdatedAck(ssn, p))
5781 int ret = StreamTcpPacketIsSpuriousRetransmission(ssn, p);
5790 if (StreamTcpStateDispatch(
tv, p, stt, ssn, ssn->
state) < 0)
5794 StreamTcpPacketCheckPostRst(ssn, p);
5839 SCLogDebug(
"bypass as stream is dead and we have no rules");
5852 if (StreamTcpInlineDropInvalid()) {
5856 DecodeSetNoPayloadInspectionFlag(p);
5870 static inline int StreamTcpValidateChecksum(
Packet *p)
5878 const TCPHdr *tcph = PacketGetTCP(p);
5879 if (PacketIsIPv4(p)) {
5880 const IPV4Hdr *ip4h = PacketGetIPv4(p);
5881 p->
l4.
csum = TCPChecksum(ip4h->s_ip_addrs, (uint16_t *)tcph,
5884 }
else if (PacketIsIPv6(p)) {
5885 const IPV6Hdr *ip6h = PacketGetIPv6(p);
5886 p->
l4.
csum = TCPV6Checksum(ip6h->s_ip6_addrs, (uint16_t *)tcph,
5907 static int TcpSessionPacketIsStreamStarter(
const Packet *p)
5909 const TCPHdr *tcph = PacketGetTCP(p);
5932 static bool TcpSessionReuseDoneEnoughSyn(
const Packet *p,
const Flow *f,
const TcpSession *ssn)
5934 const TCPHdr *tcph = PacketGetTCP(p);
5939 SCLogDebug(
"steam starter packet %" PRIu64
", ssn %p null. Reuse.", p->
pcap_cnt, ssn);
5944 ", ssn %p. STREAMTCP_FLAG_TFO_DATA_IGNORED set. Reuse.",
5949 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.", p->
pcap_cnt, ssn);
5953 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5956 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5959 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
5969 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5972 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
5975 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
5988 static bool TcpSessionReuseDoneEnoughSynAck(
const Packet *p,
const Flow *f,
const TcpSession *ssn)
5990 const TCPHdr *tcph = PacketGetTCP(p);
5993 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p null. No reuse.", p->
pcap_cnt, ssn);
5997 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p. Packet SEQ == Stream ISN. Retransmission. Don't reuse.", p->
pcap_cnt, ssn);
6001 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
6004 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
6007 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
6017 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state >= TCP_LAST_ACK (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
6020 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state == TCP_NONE (%u). Reuse.", p->
pcap_cnt, ssn, ssn->
state);
6023 SCLogDebug(
"steam starter packet %"PRIu64
", ssn %p state < TCP_LAST_ACK (%u). Don't reuse.", p->
pcap_cnt, ssn, ssn->
state);
6039 const TCPHdr *tcph = PacketGetTCP(p);
6041 return TcpSessionReuseDoneEnoughSyn(p, f, ssn);
6046 return TcpSessionReuseDoneEnoughSynAck(p, f, ssn);
6055 if (p->
proto == IPPROTO_TCP && PacketIsTCP(p)) {
6056 if (TcpSessionPacketIsStreamStarter(p) == 1) {
6057 if (TcpSessionReuseDoneEnough(p, f, tcp_ssn) == 1) {
6080 if (!(PacketIsTCP(p))) {
6084 CheckThreadId(
tv, p, stt);
6090 if (StreamTcpValidateChecksum(p) == 0) {
6112 *data = (
void *)stt;
6121 IsStreamTcpSessionMemcapExceptionPolicyStatsValid);
6129 "exception_policy.tcp.midstream.", IsMidstreamExceptionPolicyStatsValid);
6133 "exception_policy.tcp.midstream.", IsMidstreamExceptionPolicyStatsValid);
6148 "exception_policy.tcp.reassembly.", IsReassemblyMemcapExceptionPolicyStatsValid);
6162 SCLogDebug(
"StreamTcp thread specific ctx online at %p, reassembly ctx %p",
6171 StreamTcpSessionPoolAlloc,
6172 StreamTcpSessionPoolInit, NULL,
6173 StreamTcpSessionPoolCleanup, NULL);
6183 SCLogError(
"failed to setup/expand stream session pool. Expand stream.memcap?");
6228 const TCPHdr *tcph = PacketGetTCP(p);
6236 if (!StreamTcpValidateTimestamp(ssn, p)) {
6265 StreamTcpValidateAck(ssn, &ssn->
server, p) == -1) {
6266 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
6278 StreamTcpValidateAck(ssn, &ssn->
client, p) == -1) {
6279 SCLogDebug(
"ssn %p: rejecting because of invalid ack value", ssn);
6292 receiver_stream = &ssn->
server;
6294 receiver_stream = &ssn->
client;
6296 SCLogDebug(
"ssn %p: setting STREAMTCP_STREAM_FLAG_RST_RECV on receiver stream", ssn);
6316 switch (os_policy) {
6323 SCLogDebug(
"reset is not Valid! Packet SEQ: %" PRIu32
" "
6324 "and server SEQ: %" PRIu32
"",
6333 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" "
6334 "and client SEQ: %" PRIu32
"",
6351 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6352 " server SEQ: %" PRIu32
"",
6364 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6365 " client SEQ: %" PRIu32
"",
6386 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" "
6387 "and server SEQ: %" PRIu32
"",
6393 SCLogDebug(
"reset is valid! Packet SEQ: %" PRIu32
" Stream %u",
seq,
6397 SCLogDebug(
"reset is not valid! Packet SEQ: %" PRIu32
" and"
6398 " client SEQ: %" PRIu32
"",
6429 uint8_t check_ts = 1;
6430 const TCPHdr *tcph = PacketGetTCP(p);
6434 sender_stream = &ssn->
client;
6435 receiver_stream = &ssn->
server;
6437 sender_stream = &ssn->
server;
6438 receiver_stream = &ssn->
client;
6449 uint32_t last_pkt_ts = sender_stream->
last_pkt_ts;
6450 uint32_t last_ts = sender_stream->
last_ts;
6500 SCLogDebug(
"ts %"PRIu32
", last_ts %"PRIu32
"",
ts, last_ts);
6504 result = (int32_t) ((
ts - last_ts) + 1);
6506 result = (int32_t) (
ts - last_ts);
6509 SCLogDebug(
"result %" PRIi32
", p->ts(secs) %" PRIuMAX
"", result,
6512 if (last_pkt_ts == 0 &&
6520 "%" PRIu32
" p->tcpvars->ts %" PRIu32
" result "
6521 "%" PRId32
"", last_ts,
ts, result);
6524 }
else if ((sender_stream->
last_ts != 0) &&
6526 SCLogDebug(
"packet is not valid last_pkt_ts "
6527 "%" PRIu32
" p->ts(sec) %" PRIu32
"",
6539 SCLogDebug(
"timestamp considered valid anyway");
6571 uint8_t check_ts = 1;
6572 const TCPHdr *tcph = PacketGetTCP(p);
6576 sender_stream = &ssn->
client;
6577 receiver_stream = &ssn->
server;
6579 sender_stream = &ssn->
server;
6580 receiver_stream = &ssn->
client;
6648 result = (int32_t) ((
ts - sender_stream->
last_ts) + 1);
6650 result = (int32_t) (
ts - sender_stream->
last_ts);
6653 SCLogDebug(
"result %" PRIi32
", p->ts(sec) %" PRIuMAX
"", result,
6663 SCLogDebug(
"timestamp is not valid sender_stream->last_ts "
6664 "%" PRIu32
" p->tcpvars->ts %" PRIu32
" result "
6665 "%" PRId32
"", sender_stream->
last_ts,
ts, result);
6668 }
else if ((sender_stream->
last_ts != 0) &&
6671 SCLogDebug(
"packet is not valid sender_stream->last_pkt_ts "
6672 "%" PRIu32
" p->ts(sec) %" PRIu32
"",
6686 }
else if (ret == 0) {
6696 SCLogDebug(
"timestamp considered valid anyway");
6732 const TCPHdr *tcph = PacketGetTCP(p);
6747 SCLogDebug(
"ssn %p: pkt ACK %" PRIu32
" == stream last ACK %" PRIu32, ssn, ack,
6760 SCLogDebug(
"ACK %"PRIu32
" is before last_ack %"PRIu32
" - window "
6761 "%"PRIu32
" = %"PRIu32, ack, stream->
last_ack,
6784 SCLogDebug(
"default path leading to invalid: ACK %"PRIu32
", last_ack %"PRIu32
6797 const uint32_t progress)
6851 static void StreamTcpPseudoPacketCreateDetectLogFlush(
ThreadVars *
tv,
6874 np->
proto = IPPROTO_TCP;
6875 FlowReference(&np->
flow, f);
6885 DecodeSetNoPacketInspectionFlag(np);
6888 DecodeSetNoPayloadInspectionFlag(np);
6928 ip4h->
ip_len = htons(40);
6934 ip4h->s_ip_src.s_addr = f->
src.addr_data32[0];
6935 ip4h->s_ip_dst.s_addr = f->
dst.addr_data32[0];
6937 ip4h->s_ip_src.s_addr = f->
dst.addr_data32[0];
6938 ip4h->s_ip_dst.s_addr = f->
src.addr_data32[0];
6971 ip6h->s_ip6_vfc = 0x60;
6972 ip6h->s_ip6_flow = 0;
6973 ip6h->s_ip6_nxt = IPPROTO_TCP;
6974 ip6h->s_ip6_plen = htons(20);
6975 ip6h->s_ip6_hlim = 64;
6977 ip6h->s_ip6_src[0] = f->
src.addr_data32[0];
6978 ip6h->s_ip6_src[1] = f->
src.addr_data32[1];
6979 ip6h->s_ip6_src[2] = f->
src.addr_data32[2];
6980 ip6h->s_ip6_src[3] = f->
src.addr_data32[3];
6981 ip6h->s_ip6_dst[0] = f->
dst.addr_data32[0];
6982 ip6h->s_ip6_dst[1] = f->
dst.addr_data32[1];
6983 ip6h->s_ip6_dst[2] = f->
dst.addr_data32[2];
6984 ip6h->s_ip6_dst[3] = f->
dst.addr_data32[3];
6986 ip6h->s_ip6_src[0] = f->
dst.addr_data32[0];
6987 ip6h->s_ip6_src[1] = f->
dst.addr_data32[1];
6988 ip6h->s_ip6_src[2] = f->
dst.addr_data32[2];
6989 ip6h->s_ip6_src[3] = f->
dst.addr_data32[3];
6990 ip6h->s_ip6_dst[0] = f->
src.addr_data32[0];
6991 ip6h->s_ip6_dst[1] = f->
src.addr_data32[1];
6992 ip6h->s_ip6_dst[2] = f->
src.addr_data32[2];
6993 ip6h->s_ip6_dst[3] = f->
src.addr_data32[3];
7025 np->
ts = parent->
ts;
7033 FlowDeReference(&np->
flow);
7052 StreamTcpPseudoPacketCreateDetectLogFlush(
tv, stt, p, ssn, pq,
ts^0);
7053 StreamTcpPseudoPacketCreateDetectLogFlush(
tv, stt, p, ssn, pq,
ts^1);
7073 if (p->
flow == NULL)
7101 const uint8_t *seg_data;
7102 uint32_t seg_datalen;
7105 int ret = CallbackFunc(p, seg, data, seg_data, seg_datalen);
7133 if (p->
flow == NULL)
7147 if (server_node == NULL && client_node == NULL) {
7151 while (server_node != NULL || client_node != NULL) {
7152 const uint8_t *seg_data;
7153 uint32_t seg_datalen;
7154 if (server_node == NULL) {
7161 &client_stream->
sb, &client_node->
sbseg, &seg_data, &seg_datalen);
7162 ret = CallbackFunc(p, client_node, data, seg_data, seg_datalen);
7167 client_node = TCPSEG_RB_NEXT(client_node);
7168 }
else if (client_node == NULL) {
7175 &server_stream->
sb, &server_node->
sbseg, &seg_data, &seg_datalen);
7176 ret = CallbackFunc(p, server_node, data, seg_data, seg_datalen);
7181 server_node = TCPSEG_RB_NEXT(server_node);
7186 &client_stream->
sb, &client_node->
sbseg, &seg_data, &seg_datalen);
7187 ret = CallbackFunc(p, client_node, data, seg_data, seg_datalen);
7192 client_node = TCPSEG_RB_NEXT(client_node);
7195 &server_stream->
sb, &server_node->
sbseg, &seg_data, &seg_datalen);
7196 ret = CallbackFunc(p, server_node, data, seg_data, seg_datalen);
7201 server_node = TCPSEG_RB_NEXT(server_node);
7236 const char *tcp_state = NULL;
7242 tcp_state =
"syn_sent";
7245 tcp_state =
"syn_recv";
7248 tcp_state =
"established";
7251 tcp_state =
"fin_wait1";
7254 tcp_state =
"fin_wait2";
7257 tcp_state =
"time_wait";
7260 tcp_state =
"last_ack";
7263 tcp_state =
"close_wait";
7266 tcp_state =
"closing";
7269 tcp_state =
"closed";