75 static SCMutex segment_pool_memuse_mutex;
76 static uint64_t segment_pool_memuse = 0;
77 static uint64_t segment_pool_memcnt = 0;
89 static int g_tcp_session_dump_enabled = 0;
93 return g_tcp_session_dump_enabled == 1;
98 g_tcp_session_dump_enabled = 1;
116 static void StreamTcpReassembleIncrMemuse(uint64_t size)
129 static void StreamTcpReassembleDecrMemuse(uint64_t size)
134 BUG_ON(presize > UINT_MAX);
143 BUG_ON(postsize > presize);
167 if (
unlikely((g_eps_stream_reassembly_memcap != UINT64_MAX &&
168 g_eps_stream_reassembly_memcap ==
t_pcapcnt))) {
174 if (memcapcopy == 0 ||
175 (uint64_t)((uint64_t)size +
SC_ATOMIC_GET(ra_memuse)) <= memcapcopy)
187 if (size == 0 || (uint64_t)
SC_ATOMIC_GET(ra_memuse) < size) {
211 static void *ReassembleCalloc(
size_t n,
size_t size)
222 StreamTcpReassembleIncrMemuse(n * size);
231 if (size > orig_size) {
244 if (size > orig_size) {
245 StreamTcpReassembleIncrMemuse(size - orig_size);
247 StreamTcpReassembleDecrMemuse(orig_size - size);
255 static void ReassembleFree(
void *ptr,
size_t size)
258 StreamTcpReassembleDecrMemuse(size);
262 static void *TcpSegmentPoolAlloc(
void)
286 "TcpSegmentPcapHdrStorage");
295 "packet header data within "
296 "TcpSegmentPcapHdrStorage");
303 StreamTcpReassembleIncrMemuse(memuse);
311 static int TcpSegmentPoolInit(
void *data,
void *initdata)
329 StreamTcpReassembleIncrMemuse(memuse);
339 segment_pool_memcnt++;
340 SCLogDebug(
"segment_pool_memcnt %"PRIu64
"", segment_pool_memcnt);
344 StreamTcpReassembleIncrMemuse((uint32_t)
sizeof(
TcpSegment));
349 static void TcpSegmentPoolCleanup(
void *ptr)
365 StreamTcpReassembleDecrMemuse((uint32_t)
sizeof(
TcpSegment));
370 segment_pool_memcnt--;
371 SCLogDebug(
"segment_pool_memcnt %"PRIu64
"", segment_pool_memcnt);
408 static inline uint64_t GetAbsLastAck(
const TcpStream *stream)
410 if (STREAM_LASTACK_GT_BASESEQ(stream)) {
421 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
428 uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
430 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
472 static int StreamTcpReassemblyConfig(
bool quiet)
474 uint32_t segment_prealloc = 2048;
477 uint32_t prealloc = 0;
484 segment_prealloc = prealloc;
487 SCLogConfig(
"stream.reassembly \"segment-prealloc\": %u", segment_prealloc);
490 int overlap_diff_data = 0;
491 (void)
SCConfGetBool(
"stream.reassembly.check-overlap-different-data", &overlap_diff_data);
492 if (overlap_diff_data) {
499 uint16_t max_regions = 8;
510 SCLogConfig(
"stream.reassembly \"max-regions\": %u", max_regions);
528 if (StreamTcpReassemblyConfig(quiet) < 0)
550 if (segment_pool_memuse > 0)
551 SCLogDebug(
"segment_pool_memuse %" PRIu64
" segment_pool_memcnt %" PRIu64
"",
552 segment_pool_memuse, segment_pool_memcnt);
573 TcpSegmentPoolInit, NULL,
574 TcpSegmentPoolCleanup, NULL);
576 SCLogDebug(
"pool size %d, thread segment_thread_pool_id %d",
582 SCLogDebug(
"pool size %d, thread segment_thread_pool_id %d",
588 SCLogError(
"failed to setup/expand stream segment pool. Expand stream.reassembly.memcap?");
608 static void StreamTcpReassembleExceptionPolicyStatsIncr(
654 uint32_t
seq, uint32_t size)
672 SCLogDebug(
"segment entirely before base_seq, weird: base %u, seq %u, re %u",
686 SCLogDebug(
"seq + size %u, base %u, seg_depth %"PRIu64
" limit %u", (
seq + size),
691 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
695 SCLogDebug(
"NOT STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
698 SCLogDebug(
"full depth not yet reached: %"PRIu64
" <= %"PRIu32,
699 (stream->base_seq_offset + stream->
base_seq + size),
766 SCLogDebug(
"ssn %p: both app and raw reassembly disabled, not reassembling", ssn);
770 uint16_t *urg_offset;
777 const TCPHdr *tcph = PacketGetTCP(p);
781 uint8_t urg_data = 0;
791 if ((*urg_offset) < UINT16_MAX) {
795 if ((*urg_offset) == UINT16_MAX) {
812 (*urg_offset) == UINT16_MAX &&
828 uint32_t size = StreamTcpReassembleCheckDepth(ssn, stream, seg_seq,
payload_len);
829 SCLogDebug(
"ssn %p: check depth returned %"PRIu32, ssn, size);
838 SCLogDebug(
"ssn %p: depth reached, not reassembling", ssn);
876 SCLogDebug(
"StreamTcpReassembleInsertSegment failed");
888 flag |= STREAM_START;
896 flag |= STREAM_MIDSTREAM;
903 if (&ssn->
client == stream) {
904 flag |= STREAM_TOSERVER;
906 flag |= STREAM_TOCLIENT;
909 flag |= STREAM_DEPTH;
920 static bool StreamTcpReassembleRawCheckLimit(
926 #define STREAMTCP_STREAM_FLAG_FLUSH_FLAGS \
927 ( STREAMTCP_STREAM_FLAG_DEPTH_REACHED \
928 | STREAMTCP_STREAM_FLAG_TRIGGER_RAW \
929 | STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED)
933 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_DEPTH_REACHED "
934 "is set, so not expecting any new data segments");
937 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_TRIGGER_RAW is set");
940 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED is set, "
941 "so no new segments will be considered");
945 #undef STREAMTCP_STREAM_FLAG_FLUSH_FLAGS
954 const uint64_t last_ack_abs = GetAbsLastAck(stream);
960 if (chunk_size <= diff) {
963 SCLogDebug(
"%s min chunk len not yet reached: "
964 "last_ack %" PRIu32
", ra_raw_base_seq %" PRIu32
", %" PRIu32
" < "
981 const char *dirstr = NULL;
983 if (direction == STREAM_TOSERVER) {
1007 const uint64_t right_edge =
1009 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
1010 " (use: %s). Stream right edge: %" PRIu64,
1014 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
1019 const uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
1020 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
1021 " (use: %s). Stream right edge: %" PRIu64,
1025 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
1030 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NONE", dirstr);
1035 static uint64_t GetStreamSize(
TcpStream *stream)
1040 uint64_t last_ack_abs = GetAbsLastAck(stream);
1041 uint64_t last_re = 0;
1047 const uint64_t seg_abs =
1049 if (last_re != 0 && last_re < seg_abs) {
1050 const char *gacked = NULL;
1051 if (last_ack_abs >= seg_abs) {
1052 gacked =
"fully ack'd";
1053 }
else if (last_ack_abs > last_re) {
1054 gacked =
"partly ack'd";
1056 gacked =
"not yet ack'd";
1058 SCLogDebug(
" -> gap of size %" PRIu64
", ack:%s", seg_abs - last_re, gacked);
1061 const char *acked = NULL;
1062 if (last_ack_abs >= seg_abs + (uint64_t)
TCP_SEG_LEN(seg)) {
1063 acked =
"fully ack'd";
1064 }
else if (last_ack_abs > seg_abs) {
1065 acked =
"partly ack'd";
1067 acked =
"not yet ack'd";
1070 SCLogDebug(
"%u -> seg %p seq %u abs %" PRIu64
" size %u abs %" PRIu64
" (%" PRIu64
1089 size = GetStreamSize(&ssn->
client);
1090 size += GetStreamSize(&ssn->
server);
1105 GetAbsLastAck(stream) > (cur_blk->
offset + cur_blk->
len)) {
1120 static bool GetAppBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1121 uint64_t
offset,
const bool check_for_gap)
1123 const uint8_t *mydata;
1124 uint32_t mydata_len;
1125 bool gap_ahead =
false;
1133 *data_len = mydata_len;
1152 gap_ahead = check_for_gap && GapAhead(stream, blk);
1156 SCLogDebug(
"gap, want data at offset %"PRIu64
", "
1157 "got data at %"PRIu64
". GAP of size %"PRIu64,
1164 SCLogDebug(
"get data from offset %"PRIu64
". SBB %"PRIu64
"/%u",
1167 SCLogDebug(
"data %p, data_len %u", *data, *data_len);
1169 gap_ahead = check_for_gap && GapAhead(stream, blk);
1188 const uint64_t last_ack_abs = GetAbsLastAck(stream) - (uint64_t)ackadded;
1195 if (last_ack_abs > app_progress) {
1202 "next_seq %u < last_ack %u, but no data in list",
1206 const uint64_t next_seq_abs =
1209 if (blk->
offset > next_seq_abs && blk->
offset < last_ack_abs) {
1212 "next_seq %u < last_ack %u, but ACK'd data beyond gap.",
1219 "last_ack_abs %" PRIu64
" > app_progress %" PRIu64
", "
1220 "but we have no data.",
1221 p->
pcap_cnt, last_ack_abs, app_progress);
1225 "last_ack_abs %"PRIu64
" <= app_progress %"PRIu64,
1226 p->
pcap_cnt, last_ack_abs, app_progress);
1230 static inline uint32_t AdjustToAcked(
const Packet *p,
1232 const uint64_t app_progress,
const uint32_t data_len)
1234 uint32_t adjusted = data_len;
1245 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1249 if (app_progress <= last_ack_abs && app_progress + data_len > last_ack_abs) {
1250 uint32_t check = data_len;
1251 adjusted = (uint32_t)(last_ack_abs - app_progress);
1252 BUG_ON(adjusted > check);
1253 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1254 "data is considered", adjusted);
1271 SCLogDebug(
"app progress %"PRIu64, app_progress);
1273 uint64_t last_ack_abs = GetAbsLastAck(*stream);
1274 SCLogDebug(
"last_ack %u (abs %" PRIu64
"), base_seq %u", (*stream)->last_ack, last_ack_abs,
1275 (*stream)->base_seq);
1277 const uint8_t *mydata;
1278 uint32_t mydata_len;
1279 bool last_was_gap =
false;
1282 const uint8_t
flags = StreamGetAppLayerFlags(ssn, *stream, p);
1283 bool check_for_gap_ahead = ((*stream)->data_required > 0);
1285 GetAppBuffer(*stream, &mydata, &mydata_len, app_progress, check_for_gap_ahead);
1287 if (last_was_gap && mydata_len == 0) {
1290 last_was_gap =
false;
1293 mydata_len = AdjustToAcked(p, ssn, *stream, app_progress, mydata_len);
1295 if (mydata == NULL && mydata_len > 0 && CheckGap(ssn, *stream, p)) {
1296 SCLogDebug(
"sending GAP to app-layer (size: %u)", mydata_len);
1299 StreamGetAppLayerFlags(ssn, *stream, p) | STREAM_GAP, app_update_dir);
1313 if ((*stream)->data_required > 0) {
1314 if ((*stream)->data_required > mydata_len) {
1315 (*stream)->data_required -= mydata_len;
1317 (*stream)->data_required = 0;
1322 if (no_progress_update)
1324 last_was_gap =
true;
1327 }
else if (
flags & STREAM_DEPTH) {
1330 if (mydata == NULL && mydata_len > 0) {
1333 }
else if (mydata == NULL || (mydata_len == 0 && ((
flags & STREAM_EOF) == 0))) {
1346 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1347 *stream, &(*stream)->sb, mydata_len, app_progress);
1351 if (mydata_len < (*stream)->data_required) {
1354 SCLogDebug(
"GAP while expecting more data (expect %u, gap size %u)",
1355 (*stream)->data_required, mydata_len);
1356 (*stream)->app_progress_rel += mydata_len;
1357 (*stream)->data_required -= mydata_len;
1367 (*stream)->data_required = 0;
1372 mydata_len,
flags, app_update_dir);
1378 app_progress = new_app_progress;
1379 if (
flags & STREAM_DEPTH)
1407 SCLogDebug(
"stream no reassembly flag set or app-layer disabled.");
1413 GetSessionSize(ssn, p);
1424 uint8_t stream_flags = StreamGetAppLayerFlags(ssn, stream, p);
1427 tv, ra_ctx, p, p->
flow, ssn, &stream, NULL, 0, stream_flags, app_update_dir);
1435 return ReassembleUpdateAppLayer(
tv, ra_ctx, ssn, &stream, p, app_update_dir);
1441 static int GetRawBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1444 const uint8_t *mydata;
1445 uint32_t mydata_len;
1450 uint64_t roffset =
offset;
1458 *data_len = mydata_len;
1459 *data_offset = roffset;
1461 SCLogDebug(
"multiblob %s. Want offset %"PRIu64,
1462 *iter == NULL ?
"starting" :
"continuing",
offset);
1463 if (*iter == NULL) {
1468 if (*iter == NULL) {
1475 SCLogDebug(
"getting multiple blobs. Iter %p, %"PRIu64
"/%u", *iter, (*iter)->offset, (*iter)->len);
1480 if ((*iter)->offset <
offset) {
1481 uint64_t delta =
offset - (*iter)->offset;
1482 if (delta < mydata_len) {
1483 *data = mydata + delta;
1484 *data_len = (uint32_t)(mydata_len - delta);
1495 *data_len = mydata_len;
1496 *data_offset = (*iter)->offset;
1499 *iter = SBB_RB_NEXT(*iter);
1530 const uint64_t segs_re_abs =
1535 if (StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 1) {
1573 }
else if (progress == 0) {
1578 target = GetAbsLastAck(stream);
1588 SCLogDebug(
"p->pcap_cnt %"PRIu64
": progress %"PRIu64
" app %"PRIu64
" raw %"PRIu64
" tcp win %"PRIu32,
1597 SCLogDebug(
"ssn %p: STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED set, "
1598 "now that detect ran also set STREAMTCP_STREAM_FLAG_DISABLE_RAW", ssn);
1645 "packet payload len %u, so chunk_size adjusted to %u", p->
payload_len, chunk_size);
1648 const TCPHdr *tcph = PacketGetTCP(p);
1649 uint64_t packet_leftedge_abs =
1651 uint64_t packet_rightedge_abs = packet_leftedge_abs + p->
payload_len;
1652 SCLogDebug(
"packet_leftedge_abs %"PRIu64
", rightedge %"PRIu64,
1653 packet_leftedge_abs, packet_rightedge_abs);
1655 const uint8_t *mydata = NULL;
1656 uint32_t mydata_len = 0;
1657 uint64_t mydata_offset = 0;
1659 bool return_progress =
false;
1664 return_progress =
true;
1667 SCLogDebug(
"finding our SBB from offset %"PRIu64, packet_leftedge_abs);
1674 mydata_offset = sbb->
offset;
1679 uint64_t mydata_rightedge_abs = mydata_offset + mydata_len;
1680 if ((mydata == NULL || mydata_len == 0) ||
1681 (mydata_offset >= packet_rightedge_abs ||
1682 packet_leftedge_abs >= mydata_rightedge_abs) ||
1683 (packet_leftedge_abs < mydata_offset ||
1684 packet_rightedge_abs > mydata_rightedge_abs))
1689 mydata_offset = packet_leftedge_abs;
1693 SCLogDebug(
"chunk_size %u mydata_len %u", chunk_size, mydata_len);
1694 if (mydata_len > chunk_size) {
1695 uint32_t excess = mydata_len - chunk_size;
1696 SCLogDebug(
"chunk_size %u mydata_len %u excess %u", chunk_size, mydata_len, excess);
1698 if (mydata_rightedge_abs == packet_rightedge_abs) {
1700 mydata_len -= excess;
1701 mydata_offset += excess;
1702 SCLogDebug(
"cutting front of the buffer with %u", excess);
1703 }
else if (mydata_offset == packet_leftedge_abs) {
1704 mydata_len -= excess;
1705 SCLogDebug(
"cutting tail of the buffer with %u", excess);
1708 uint32_t abs_before = (uint32_t)(packet_leftedge_abs - mydata_offset);
1710 uint32_t abs_after = (uint32_t)(mydata_rightedge_abs - packet_rightedge_abs);
1711 uint32_t before = abs_before;
1712 uint32_t after = abs_after;
1713 SCLogDebug(
"before %u after %u", before, after);
1718 if (before >= (chunk_size - p->
payload_len) / 2) {
1720 before = after = (chunk_size - p->
payload_len) / 2;
1729 if (before >= (chunk_size - p->
payload_len) / 2) {
1738 uint32_t skip = abs_before - before;
1740 uint32_t cut = abs_after - after;
1745 mydata_len -= (skip + cut);
1746 mydata_offset += skip;
1752 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1755 if (return_progress) {
1756 *progress_out = (mydata_offset + mydata_len);
1763 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1764 SCLogDebug(
"last_ack_abs %"PRIu64, last_ack_abs);
1767 if (mydata_offset > last_ack_abs) {
1769 *progress_out = last_ack_abs;
1771 *progress_out = (mydata_offset + mydata_len);
1814 const uint64_t re, uint64_t *progress_out,
bool eof,
bool respect_inspect_depth)
1820 uint64_t progress = progress_in;
1825 const uint8_t *mydata;
1826 uint32_t mydata_len;
1827 uint64_t mydata_offset = 0;
1829 GetRawBuffer(stream, &mydata, &mydata_len, &iter, progress, &mydata_offset);
1830 if (mydata_len == 0) {
1836 SCLogDebug(
"raw progress %"PRIu64, progress);
1837 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1838 stream, &stream->
sb, mydata_len, progress);
1843 if (re < progress) {
1848 SCLogDebug(
"re %" PRIu64
", raw_progress %" PRIu64, re, progress);
1849 SCLogDebug(
"raw_progress + mydata_len %" PRIu64
", re %" PRIu64, progress + mydata_len,
1853 if (progress + mydata_len > re) {
1854 uint32_t check = mydata_len;
1855 mydata_len = (uint32_t)(re - progress);
1856 BUG_ON(check < mydata_len);
1857 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1858 "data is considered", mydata_len);
1861 if (mydata_len == 0)
1864 SCLogDebug(
"data %p len %u", mydata, mydata_len);
1867 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1870 if (mydata_offset == progress) {
1871 SCLogDebug(
"progress %"PRIu64
" increasing with data len %u to %"PRIu64,
1872 progress, mydata_len, progress_in + mydata_len);
1874 progress += mydata_len;
1875 SCLogDebug(
"raw progress now %"PRIu64, progress);
1878 }
else if (mydata_offset > progress && mydata_offset < re) {
1879 SCLogDebug(
"GAP: data is missing from %"PRIu64
" (%u bytes), setting to first data we have: %"PRIu64, progress, (uint32_t)(mydata_offset - progress), mydata_offset);
1881 progress = mydata_offset;
1882 SCLogDebug(
"raw progress now %"PRIu64, progress);
1885 SCLogDebug(
"not increasing progress, data gap => mydata_offset "
1886 "%"PRIu64
" != progress %"PRIu64, mydata_offset, progress);
1889 if (iter == NULL || r == 1)
1893 *progress_out = progress;
1898 void *cb_data,
const uint64_t
offset,
const bool eof)
1902 SCLogDebug(
"app_progress %" PRIu64, app_progress);
1904 uint64_t unused = 0;
1905 return StreamReassembleRawDo(
1906 ssn, stream, Callback, cb_data,
offset, app_progress, &unused, eof,
false);
1911 uint64_t *progress_out,
bool respect_inspect_depth)
1915 return StreamReassembleRawInline(ssn, p, Callback, cb_data, progress_out);
1926 StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 0)
1938 SCLogDebug(
"respect_inspect_depth %s STREAMTCP_STREAM_FLAG_TRIGGER_RAW %s "
1939 "stream->min_inspect_depth %u",
1940 respect_inspect_depth ?
"true" :
"false",
1957 SCLogDebug(
"applied min inspect depth due to STREAMTCP_STREAM_FLAG_TRIGGER_RAW: progress "
1967 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1968 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1970 return StreamReassembleRawDo(ssn, stream, Callback, cb_data, progress, last_ack_abs,
1976 uint64_t *progress_out,
const bool eof)
1982 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1983 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1985 return StreamReassembleRawDo(
1986 ssn, stream, Callback, cb_data, progress_in, last_ack_abs, progress_out, eof,
false);
1994 static int StreamTcpReassembleHandleSegmentUpdateACK (
ThreadVars *
tv,
2011 const TCPHdr *tcph = PacketGetTCP(p);
2013 SCLogDebug(
"ssn %p, stream %p, p %p, p->payload_len %"PRIu16
"",
2043 if (stream == &ssn->
client) {
2044 opposing_stream = &ssn->
server;
2046 opposing_stream = &ssn->
client;
2051 if (StreamTcpReassembleHandleSegmentUpdateACK(
tv, ra_ctx, ssn, opposing_stream, p) != 0) {
2052 SCLogDebug(
"StreamTcpReassembleHandleSegmentUpdateACK error");
2060 if (reversed_before_ack_handling != reversed_after_ack_handling) {
2062 stream = opposing_stream;
2068 SCLogDebug(
"calling StreamTcpReassembleHandleSegmentHandleData");
2071 SCLogDebug(
"StreamTcpReassembleHandleSegmentHandleData error");
2075 StreamTcpReassembleExceptionPolicyStatsIncr(
2083 SCLogDebug(
"ssn %p / stream %p: not calling StreamTcpReassembleHandleSegmentHandleData:"
2084 " p->payload_len %u, STREAMTCP_STREAM_FLAG_NOREASSEMBLY %s",
2094 if ((stream->
flags &
2098 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED, truncate applayer");
2100 SCLogDebug(
"override: direction now UPDATE_DIR_PACKET so we "
2101 "can trigger Truncate");
2109 SCLogDebug(
"inline (%s) or PKT_PSEUDO_STREAM_END (%s)",
2168 if (direction == STREAM_TOSERVER) {
2174 SCLogDebug(
"flagged ssn %p for immediate raw reassembly", ssn);
2185 if (direction == STREAM_TOSERVER) {
2187 SCLogDebug(
"ssn %p: set client.min_inspect_depth to %u", ssn, depth);
2190 SCLogDebug(
"ssn %p: set server.min_inspect_depth to %u", ssn, depth);
2198 #define SET_ISN(stream, setseq) \
2199 (stream)->isn = (setseq); \
2200 (stream)->base_seq = (setseq) + 1
2218 for (; i <
len; i++)
2232 data, data_len) == 0)
2241 #define MISSED_START(isn) \
2242 TcpReassemblyThreadCtx *ra_ctx = NULL; \
2245 memset(&tv, 0, sizeof(tv)); \
2247 StreamTcpUTInit(&ra_ctx); \
2249 StreamTcpUTSetupSession(&ssn); \
2250 StreamTcpUTSetupStream(&ssn.server, (isn)); \
2251 StreamTcpUTSetupStream(&ssn.client, (isn)); \
2253 TcpStream *stream = &ssn.client;
2255 #define MISSED_END \
2256 StreamTcpUTClearSession(&ssn); \
2257 StreamTcpUTDeinit(ra_ctx); \
2260 #define MISSED_STEP(seq, seg, seglen, buf, buflen) \
2261 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen)); \
2262 FAIL_IF(!(VALIDATE(stream, (uint8_t *)(buf), (buflen))));
2264 #define MISSED_ADD_PAYLOAD(seq, seg, seglen) \
2265 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen));
2272 uint64_t last_re = 0;
2276 if (sbb->
offset != last_re) {
2296 uint64_t last_re = 0;
2300 if (sbb->
offset != last_re) {
2306 const uint8_t *buf = NULL;
2307 uint32_t buf_len = 0;
2310 if (
len == buf_len) {
2311 return (memcmp(data, buf,
len) == 0);
2328 static int StreamTcpReassembleTest25 (
void)
2349 static int StreamTcpReassembleTest26 (
void)
2368 static int StreamTcpReassembleTest27 (
void)
2385 static int StreamTcpReassembleTest28 (
void)
2409 static int StreamTcpReassembleTest29 (
void)
2421 static int StreamTcpReassembleTest33(
void)
2430 uint8_t packet[1460] =
"";
2435 memset(&f, 0,
sizeof (
Flow));
2436 memset(&tcph, 0,
sizeof (
TCPHdr));
2441 f.
proto = IPPROTO_TCP;
2444 p->
proto = IPPROTO_TCP;
2482 static int StreamTcpReassembleTest34(
void)
2491 uint8_t packet[1460] =
"";
2495 memset(&f, 0,
sizeof (
Flow));
2496 memset(&tcph, 0,
sizeof (
TCPHdr));
2501 f.
proto = IPPROTO_TCP;
2504 p->
proto = IPPROTO_TCP;
2513 tcph.
th_seq = htonl(857961230);
2519 tcph.
th_seq = htonl(857961534);
2525 tcph.
th_seq = htonl(857963582);
2531 tcph.
th_seq = htonl(857960946);
2551 static int StreamTcpReassembleTest39 (
void)
2561 memset (&f, 0,
sizeof(
Flow));
2563 memset(&stt, 0,
sizeof (stt));
2564 memset(&tcph, 0,
sizeof (
TCPHdr));
2568 f.
proto = IPPROTO_TCP;
2575 tcph.
th_win = htons(5480);
2643 uint8_t request1[] = { 0x47, 0x45, };
2690 uint8_t request2[] = {
2691 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
2692 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
2693 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
2694 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
2695 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
2696 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
2697 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
2698 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
2699 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
2700 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
2701 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
2726 uint8_t response[] = {
2727 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
2728 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
2729 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
2730 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
2731 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
2732 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
2733 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
2734 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
2735 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
2736 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
2737 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
2738 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
2739 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
2740 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
2741 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
2742 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
2743 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
2744 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
2745 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
2746 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
2747 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
2748 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
2749 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
2750 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
2751 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
2752 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
2753 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
2754 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
2755 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
2756 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
2757 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
2758 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
2759 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
2760 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
2761 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
2762 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
2763 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
2764 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
2765 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
2766 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
2767 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
2793 tcph.
th_ack = htonl(328);
2819 tcph.
th_seq = htonl(328);
2843 tcph.
th_ack = htonl(328);
2868 tcph.
th_seq = htonl(328);
2893 tcph.
th_ack = htonl(328);
2919 tcph.
th_seq = htonl(328);
2944 tcph.
th_ack = htonl(328);
2970 tcph.
th_ack = htonl(175);
2971 tcph.
th_seq = htonl(328);
2997 tcph.
th_ack = htonl(175);
2998 tcph.
th_seq = htonl(328);
3014 tcph.
th_ack = htonl(328);
3015 tcph.
th_seq = htonl(175);
3035 static int StreamTcpReassembleTest40 (
void)
3042 memset(&tcph, 0,
sizeof (
TCPHdr));
3052 uint8_t httpbuf1[] =
"P";
3053 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3054 uint8_t httpbuf3[] =
"O";
3055 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
3056 uint8_t httpbuf4[] =
"S";
3057 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
3058 uint8_t httpbuf5[] =
"T \r\n";
3059 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
3061 uint8_t httpbuf2[] =
"HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
3062 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3069 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3072 f->
proto = IPPROTO_TCP;
3075 tcph.
th_win = htons(5480);
3127 tcph.
th_ack = htonl(100);
3136 tcph.
th_seq = htonl(100);
3147 tcph.
th_ack = htonl(145);
3156 tcph.
th_seq = htonl(145);
3173 static int StreamTcpReassembleTest44(
void)
3177 StreamTcpReassembleIncrMemuse(500);
3179 StreamTcpReassembleDecrMemuse(500);
3194 static int StreamTcpReassembleTest45 (
void)
3199 memset(&
tv, 0,
sizeof(
tv));
3200 uint8_t payload[100] = {0};
3201 uint16_t payload_size = 100;
3232 static int StreamTcpReassembleTest46 (
void)
3238 memset(&
tv, 0,
sizeof(
tv));
3239 uint8_t payload[100] = {0};
3240 uint16_t payload_size = 100;
3253 printf(
"STREAMTCP_STREAM_FLAG_NOREASSEMBLY set: ");
3261 printf(
"STREAMTCP_STREAM_FLAG_NOREASSEMBLY set: ");
3281 static int StreamTcpReassembleTest47 (
void)
3289 memset(&tcph, 0,
sizeof (
TCPHdr));
3296 uint8_t httpbuf1[] =
"GET /EVILSUFF HTTP/1.1\r\n\r\n";
3297 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3305 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3308 f->
proto = IPPROTO_TCP;
3311 tcph.
th_win = htons(5480);
3318 tcph.
th_ack = htonl(572799782UL);
3330 tcph.
th_seq = htonl(572799782UL);
3349 static int StreamTcpReassembleInlineTest01(
void)
3357 memset(&
tv, 0x00,
sizeof(
tv));
3365 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3368 printf(
"couldn't get a packet: ");
3375 printf(
"failed to add segment 1: ");
3379 printf(
"failed to add segment 2: ");
3383 printf(
"failed to add segment 3: ");
3399 static int StreamTcpReassembleInlineTest02(
void)
3407 memset(&
tv, 0x00,
sizeof(
tv));
3415 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3418 printf(
"couldn't get a packet: ");
3425 printf(
"failed to add segment 1: ");
3429 printf(
"failed to add segment 2: ");
3433 printf(
"failed to add segment 3: ");
3438 printf(
"failed to add segment 4: ");
3455 static int StreamTcpReassembleInlineTest03(
void)
3463 memset(&
tv, 0x00,
sizeof(
tv));
3473 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3476 printf(
"couldn't get a packet: ");
3484 printf(
"failed to add segment 1: ");
3488 printf(
"failed to add segment 2: ");
3492 printf(
"failed to add segment 3: ");
3497 printf(
"failed to add segment 4: ");
3516 static int StreamTcpReassembleInlineTest04(
void)
3524 memset(&
tv, 0x00,
sizeof(
tv));
3534 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3537 printf(
"couldn't get a packet: ");
3545 printf(
"failed to add segment 1: ");
3549 printf(
"failed to add segment 2: ");
3553 printf(
"failed to add segment 3: ");
3558 printf(
"failed to add segment 4: ");
3578 static int StreamTcpReassembleInlineTest08(
void)
3582 memset(&
tv, 0x00,
sizeof(
tv));
3594 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3626 static int StreamTcpReassembleInlineTest09(
void)
3634 memset(&
tv, 0x00,
sizeof(
tv));
3644 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3647 printf(
"couldn't get a packet: ");
3655 printf(
"failed to add segment 1: ");
3659 printf(
"failed to add segment 2: ");
3663 printf(
"failed to add segment 3: ");
3671 printf(
"failed to add segment 4: ");
3693 static int StreamTcpReassembleInlineTest10(
void)
3702 memset(&
tv, 0x00,
sizeof(
tv));
3713 f =
UTHBuildFlow(AF_INET,
"1.1.1.1",
"2.2.2.2", 1024, 80);
3717 f->
proto = IPPROTO_TCP;
3719 uint8_t stream_payload1[] =
"GE";
3720 uint8_t stream_payload2[] =
"T /";
3721 uint8_t stream_payload3[] =
"HTTP/1.0\r\n\r\n";
3723 p =
UTHBuildPacketReal(stream_payload3, 12, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
3725 printf(
"couldn't get a packet: ");
3733 printf(
"failed to add segment 1: ");
3740 printf(
"StreamTcpReassembleAppLayer failed: ");
3746 printf(
"expected ra_app_base_seq 1, got %u: ", ssn.
client.
base_seq);
3751 printf(
"failed to add segment 2: ");
3755 printf(
"failed to add segment 3: ");
3762 printf(
"StreamTcpReassembleAppLayer failed: ");
3779 static int StreamTcpReassembleInsertTest01(
void)
3786 memset(&
tv, 0x00,
sizeof(
tv));
3794 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3816 static int StreamTcpReassembleInsertTest02(
void)
3823 memset(&
tv, 0x00,
sizeof(
tv));
3830 for (i = 2; i < 10; i++) {
3841 printf(
"failed to add segment 1: ");
3846 printf(
"failed to add segment 2: ");
3859 static int StreamTcpReassembleInsertTest03(
void)
3866 memset(&
tv, 0x00,
sizeof(
tv));
3873 printf(
"failed to add segment 2: ");
3878 for (i = 2; i < 10; i++) {
3889 printf(
"failed to add segment 2: ");
3910 UtRegisterTest(
"StreamTcpReassembleTest25 -- Gap at Start Reassembly Test",
3911 StreamTcpReassembleTest25);
3912 UtRegisterTest(
"StreamTcpReassembleTest26 -- Gap at middle Reassembly Test",
3913 StreamTcpReassembleTest26);
3914 UtRegisterTest(
"StreamTcpReassembleTest27 -- Gap at after Reassembly Test",
3915 StreamTcpReassembleTest27);
3916 UtRegisterTest(
"StreamTcpReassembleTest28 -- Gap at Start IDS missed packet Reassembly Test",
3917 StreamTcpReassembleTest28);
3918 UtRegisterTest(
"StreamTcpReassembleTest29 -- Gap at Middle IDS missed packet Reassembly Test",
3919 StreamTcpReassembleTest29);
3921 StreamTcpReassembleTest33);
3923 StreamTcpReassembleTest34);
3925 StreamTcpReassembleTest39);
3927 StreamTcpReassembleTest40);
3929 StreamTcpReassembleTest44);
3931 StreamTcpReassembleTest45);
3933 StreamTcpReassembleTest46);
3934 UtRegisterTest(
"StreamTcpReassembleTest47 -- TCP Sequence Wraparound Test",
3935 StreamTcpReassembleTest47);
3937 UtRegisterTest(
"StreamTcpReassembleInlineTest01 -- inline RAW ra",
3938 StreamTcpReassembleInlineTest01);
3939 UtRegisterTest(
"StreamTcpReassembleInlineTest02 -- inline RAW ra 2",
3940 StreamTcpReassembleInlineTest02);
3941 UtRegisterTest(
"StreamTcpReassembleInlineTest03 -- inline RAW ra 3",
3942 StreamTcpReassembleInlineTest03);
3943 UtRegisterTest(
"StreamTcpReassembleInlineTest04 -- inline RAW ra 4",
3944 StreamTcpReassembleInlineTest04);
3945 UtRegisterTest(
"StreamTcpReassembleInlineTest08 -- inline RAW ra 8 cleanup",
3946 StreamTcpReassembleInlineTest08);
3947 UtRegisterTest(
"StreamTcpReassembleInlineTest09 -- inline RAW ra 9 GAP cleanup",
3948 StreamTcpReassembleInlineTest09);
3950 UtRegisterTest(
"StreamTcpReassembleInlineTest10 -- inline APP ra 10",
3951 StreamTcpReassembleInlineTest10);
3953 UtRegisterTest(
"StreamTcpReassembleInsertTest01 -- insert with overlap",
3954 StreamTcpReassembleInsertTest01);
3955 UtRegisterTest(
"StreamTcpReassembleInsertTest02 -- insert with overlap",
3956 StreamTcpReassembleInsertTest02);
3957 UtRegisterTest(
"StreamTcpReassembleInsertTest03 -- insert with overlap",
3958 StreamTcpReassembleInsertTest03);
3963 StreamTcpReassembleRawRegisterTests();