75 static SCMutex segment_pool_memuse_mutex;
76 static uint64_t segment_pool_memuse = 0;
77 static uint64_t segment_pool_memcnt = 0;
80 thread_local uint64_t t_pcapcnt = UINT64_MAX;
90 static int g_tcp_session_dump_enabled = 0;
94 return g_tcp_session_dump_enabled == 1;
99 g_tcp_session_dump_enabled = 1;
117 static void StreamTcpReassembleIncrMemuse(uint64_t size)
130 static void StreamTcpReassembleDecrMemuse(uint64_t size)
135 BUG_ON(presize > UINT_MAX);
144 BUG_ON(postsize > presize);
168 if (
unlikely((g_eps_stream_reassembly_memcap != UINT64_MAX &&
169 g_eps_stream_reassembly_memcap == t_pcapcnt))) {
170 SCLogNotice(
"simulating memcap reached condition for packet %" PRIu64, t_pcapcnt);
175 if (memcapcopy == 0 ||
176 (uint64_t)((uint64_t)size +
SC_ATOMIC_GET(ra_memuse)) <= memcapcopy)
188 if (size == 0 || (uint64_t)
SC_ATOMIC_GET(ra_memuse) < size) {
212 static void *ReassembleCalloc(
size_t n,
size_t size)
223 StreamTcpReassembleIncrMemuse(n * size);
232 if (size > orig_size) {
245 if (size > orig_size) {
246 StreamTcpReassembleIncrMemuse(size - orig_size);
248 StreamTcpReassembleDecrMemuse(orig_size - size);
256 static void ReassembleFree(
void *ptr,
size_t size)
259 StreamTcpReassembleDecrMemuse(size);
263 static void *TcpSegmentPoolAlloc(
void)
287 "TcpSegmentPcapHdrStorage");
296 "packet header data within "
297 "TcpSegmentPcapHdrStorage");
304 StreamTcpReassembleIncrMemuse(memuse);
312 static int TcpSegmentPoolInit(
void *data,
void *initdata)
330 StreamTcpReassembleIncrMemuse(memuse);
340 segment_pool_memcnt++;
341 SCLogDebug(
"segment_pool_memcnt %"PRIu64
"", segment_pool_memcnt);
345 StreamTcpReassembleIncrMemuse((uint32_t)
sizeof(
TcpSegment));
350 static void TcpSegmentPoolCleanup(
void *ptr)
366 StreamTcpReassembleDecrMemuse((uint32_t)
sizeof(
TcpSegment));
371 segment_pool_memcnt--;
372 SCLogDebug(
"segment_pool_memcnt %"PRIu64
"", segment_pool_memcnt);
409 static inline uint64_t GetAbsLastAck(
const TcpStream *stream)
411 if (STREAM_LASTACK_GT_BASESEQ(stream)) {
422 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
429 uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
431 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
473 static int StreamTcpReassemblyConfig(
bool quiet)
475 uint32_t segment_prealloc = 2048;
478 uint32_t prealloc = 0;
485 segment_prealloc = prealloc;
488 SCLogConfig(
"stream.reassembly \"segment-prealloc\": %u", segment_prealloc);
491 int overlap_diff_data = 0;
492 (void)
SCConfGetBool(
"stream.reassembly.check-overlap-different-data", &overlap_diff_data);
493 if (overlap_diff_data) {
500 uint16_t max_regions = 8;
511 SCLogConfig(
"stream.reassembly \"max-regions\": %u", max_regions);
529 if (StreamTcpReassemblyConfig(quiet) < 0)
551 if (segment_pool_memuse > 0)
552 SCLogDebug(
"segment_pool_memuse %" PRIu64
" segment_pool_memcnt %" PRIu64
"",
553 segment_pool_memuse, segment_pool_memcnt);
574 TcpSegmentPoolInit, NULL,
575 TcpSegmentPoolCleanup, NULL);
577 SCLogDebug(
"pool size %d, thread segment_thread_pool_id %d",
583 SCLogDebug(
"pool size %d, thread segment_thread_pool_id %d",
589 SCLogError(
"failed to setup/expand stream segment pool. Expand stream.reassembly.memcap?");
609 static void StreamTcpReassembleExceptionPolicyStatsIncr(
655 uint32_t
seq, uint32_t size)
673 SCLogDebug(
"segment entirely before base_seq, weird: base %u, seq %u, re %u",
687 SCLogDebug(
"seq + size %u, base %u, seg_depth %"PRIu64
" limit %u", (
seq + size),
692 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
696 SCLogDebug(
"NOT STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
699 SCLogDebug(
"full depth not yet reached: %"PRIu64
" <= %"PRIu32,
700 (stream->base_seq_offset + stream->
base_seq + size),
767 SCLogDebug(
"ssn %p: both app and raw reassembly disabled, not reassembling", ssn);
771 uint16_t *urg_offset;
778 const TCPHdr *tcph = PacketGetTCP(p);
782 uint8_t urg_data = 0;
792 if ((*urg_offset) < UINT16_MAX) {
796 if ((*urg_offset) == UINT16_MAX) {
813 (*urg_offset) == UINT16_MAX &&
829 uint32_t size = StreamTcpReassembleCheckDepth(ssn, stream, seg_seq,
payload_len);
830 SCLogDebug(
"ssn %p: check depth returned %"PRIu32, ssn, size);
839 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);
1103 GetAbsLastAck(stream) > (cur_blk->
offset + cur_blk->
len);
1115 static bool GetAppBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1116 uint64_t
offset,
const bool check_for_gap)
1118 const uint8_t *mydata;
1119 uint32_t mydata_len;
1120 bool gap_ahead =
false;
1128 *data_len = mydata_len;
1147 gap_ahead = check_for_gap && GapAhead(stream, blk);
1151 SCLogDebug(
"gap, want data at offset %"PRIu64
", "
1152 "got data at %"PRIu64
". GAP of size %"PRIu64,
1159 SCLogDebug(
"get data from offset %"PRIu64
". SBB %"PRIu64
"/%u",
1162 SCLogDebug(
"data %p, data_len %u", *data, *data_len);
1164 gap_ahead = check_for_gap && GapAhead(stream, blk);
1183 const uint64_t last_ack_abs = GetAbsLastAck(stream) - (uint64_t)ackadded;
1190 if (last_ack_abs > app_progress) {
1197 "next_seq %u < last_ack %u, but no data in list",
1201 const uint64_t next_seq_abs =
1204 if (blk->
offset > next_seq_abs && blk->
offset < last_ack_abs) {
1207 "next_seq %u < last_ack %u, but ACK'd data beyond gap.",
1214 "last_ack_abs %" PRIu64
" > app_progress %" PRIu64
", "
1215 "but we have no data.",
1220 "last_ack_abs %" PRIu64
" <= app_progress %" PRIu64,
1225 static inline uint32_t AdjustToAcked(
const Packet *p,
1227 const uint64_t app_progress,
const uint32_t data_len)
1229 uint32_t adjusted = data_len;
1240 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1244 if (app_progress <= last_ack_abs && app_progress + data_len > last_ack_abs) {
1245 adjusted = (uint32_t)(last_ack_abs - app_progress);
1247 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1248 "data is considered", adjusted);
1265 SCLogDebug(
"app progress %"PRIu64, app_progress);
1267 uint64_t last_ack_abs = GetAbsLastAck(*stream);
1268 SCLogDebug(
"last_ack %u (abs %" PRIu64
"), base_seq %u", (*stream)->last_ack, last_ack_abs,
1269 (*stream)->base_seq);
1271 const uint8_t *mydata;
1272 uint32_t mydata_len;
1273 bool last_was_gap =
false;
1276 const uint8_t
flags = StreamGetAppLayerFlags(ssn, *stream, p);
1277 bool check_for_gap_ahead = ((*stream)->data_required > 0);
1279 GetAppBuffer(*stream, &mydata, &mydata_len, app_progress, check_for_gap_ahead);
1281 if (last_was_gap && mydata_len == 0) {
1284 last_was_gap =
false;
1287 mydata_len = AdjustToAcked(p, ssn, *stream, app_progress, mydata_len);
1289 if (mydata == NULL && mydata_len > 0 && CheckGap(ssn, *stream, p)) {
1290 SCLogDebug(
"sending GAP to app-layer (size: %u)", mydata_len);
1293 StreamGetAppLayerFlags(ssn, *stream, p) | STREAM_GAP, app_update_dir);
1307 if ((*stream)->data_required > 0) {
1308 if ((*stream)->data_required > mydata_len) {
1309 (*stream)->data_required -= mydata_len;
1311 (*stream)->data_required = 0;
1316 if (no_progress_update)
1318 last_was_gap =
true;
1321 }
else if (
flags & STREAM_DEPTH) {
1324 if (mydata == NULL && mydata_len > 0) {
1327 }
else if (mydata == NULL || (mydata_len == 0 && ((
flags & STREAM_EOF) == 0))) {
1340 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1341 *stream, &(*stream)->sb, mydata_len, app_progress);
1345 if (mydata_len < (*stream)->data_required) {
1348 SCLogDebug(
"GAP while expecting more data (expect %u, gap size %u)",
1349 (*stream)->data_required, mydata_len);
1350 (*stream)->app_progress_rel += mydata_len;
1351 (*stream)->data_required -= mydata_len;
1361 (*stream)->data_required = 0;
1366 mydata_len,
flags, app_update_dir);
1372 app_progress = new_app_progress;
1373 if (
flags & STREAM_DEPTH)
1401 SCLogDebug(
"stream no reassembly flag set or app-layer disabled.");
1407 GetSessionSize(ssn, p);
1418 uint8_t stream_flags = StreamGetAppLayerFlags(ssn, stream, p);
1420 tv, ra_ctx, p, p->
flow, ssn, &stream, NULL, 0, stream_flags, app_update_dir);
1428 return ReassembleUpdateAppLayer(
tv, ra_ctx, ssn, &stream, p, app_update_dir);
1434 static int GetRawBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1437 const uint8_t *mydata;
1438 uint32_t mydata_len;
1443 uint64_t roffset =
offset;
1451 *data_len = mydata_len;
1452 *data_offset = roffset;
1454 SCLogDebug(
"multiblob %s. Want offset %"PRIu64,
1455 *iter == NULL ?
"starting" :
"continuing",
offset);
1456 if (*iter == NULL) {
1461 if (*iter == NULL) {
1468 SCLogDebug(
"getting multiple blobs. Iter %p, %"PRIu64
"/%u", *iter, (*iter)->offset, (*iter)->len);
1473 if ((*iter)->offset <
offset) {
1474 uint64_t delta =
offset - (*iter)->offset;
1475 if (delta < mydata_len) {
1476 *data = mydata + delta;
1477 *data_len = (uint32_t)(mydata_len - delta);
1488 *data_len = mydata_len;
1489 *data_offset = (*iter)->offset;
1492 *iter = SBB_RB_NEXT(*iter);
1523 const uint64_t segs_re_abs =
1528 if (StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 1) {
1566 }
else if (progress == 0) {
1571 target = GetAbsLastAck(stream);
1581 SCLogDebug(
"pcap_cnt %" PRIu64
": progress %" PRIu64
" app %" PRIu64
" raw %" PRIu64
1582 " tcp win %" PRIu32,
1591 SCLogDebug(
"ssn %p: STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED set, "
1592 "now that detect ran also set STREAMTCP_STREAM_FLAG_DISABLE_RAW", ssn);
1639 "packet payload len %u, so chunk_size adjusted to %u", p->
payload_len, chunk_size);
1642 const TCPHdr *tcph = PacketGetTCP(p);
1647 uint64_t packet_rightedge_abs = packet_leftedge_abs + p->
payload_len;
1648 SCLogDebug(
"packet_leftedge_abs %"PRIu64
", rightedge %"PRIu64,
1649 packet_leftedge_abs, packet_rightedge_abs);
1651 const uint8_t *mydata = NULL;
1652 uint32_t mydata_len = 0;
1653 uint64_t mydata_offset = 0;
1655 bool return_progress =
false;
1660 return_progress =
true;
1663 SCLogDebug(
"finding our SBB from offset %"PRIu64, packet_leftedge_abs);
1670 mydata_offset = sbb->
offset;
1675 uint64_t mydata_rightedge_abs = mydata_offset + mydata_len;
1676 if ((mydata == NULL || mydata_len == 0) ||
1677 (mydata_offset >= packet_rightedge_abs ||
1678 packet_leftedge_abs >= mydata_rightedge_abs) ||
1679 (packet_leftedge_abs < mydata_offset ||
1680 packet_rightedge_abs > mydata_rightedge_abs))
1685 mydata_offset = packet_leftedge_abs;
1689 SCLogDebug(
"chunk_size %u mydata_len %u", chunk_size, mydata_len);
1690 if (mydata_len > chunk_size) {
1691 uint32_t excess = mydata_len - chunk_size;
1692 SCLogDebug(
"chunk_size %u mydata_len %u excess %u", chunk_size, mydata_len, excess);
1694 if (mydata_rightedge_abs == packet_rightedge_abs) {
1696 mydata_len -= excess;
1697 mydata_offset += excess;
1698 SCLogDebug(
"cutting front of the buffer with %u", excess);
1699 }
else if (mydata_offset == packet_leftedge_abs) {
1700 mydata_len -= excess;
1701 SCLogDebug(
"cutting tail of the buffer with %u", excess);
1704 uint32_t abs_before = (uint32_t)(packet_leftedge_abs - mydata_offset);
1706 uint32_t abs_after = (uint32_t)(mydata_rightedge_abs - packet_rightedge_abs);
1707 uint32_t before = abs_before;
1708 uint32_t after = abs_after;
1709 SCLogDebug(
"before %u after %u", before, after);
1714 if (before >= (chunk_size - p->
payload_len) / 2) {
1716 before = after = (chunk_size - p->
payload_len) / 2;
1725 if (before >= (chunk_size - p->
payload_len) / 2) {
1734 uint32_t skip = abs_before - before;
1736 uint32_t cut = abs_after - after;
1741 mydata_len -= (skip + cut);
1742 mydata_offset += skip;
1748 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1751 if (return_progress) {
1752 *progress_out = (mydata_offset + mydata_len);
1759 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1760 SCLogDebug(
"last_ack_abs %"PRIu64, last_ack_abs);
1763 if (mydata_offset > last_ack_abs) {
1765 *progress_out = last_ack_abs;
1767 *progress_out = (mydata_offset + mydata_len);
1806 const uint64_t re, uint64_t *progress_out,
bool eof)
1812 uint64_t progress = progress_in;
1817 const uint8_t *mydata;
1818 uint32_t mydata_len;
1819 uint64_t mydata_offset = 0;
1821 GetRawBuffer(stream, &mydata, &mydata_len, &iter, progress, &mydata_offset);
1822 if (mydata_len == 0) {
1828 SCLogDebug(
"raw progress %"PRIu64, progress);
1829 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1830 stream, &stream->
sb, mydata_len, progress);
1835 if (re < progress) {
1840 SCLogDebug(
"re %" PRIu64
", raw_progress %" PRIu64, re, progress);
1841 SCLogDebug(
"raw_progress + mydata_len %" PRIu64
", re %" PRIu64, progress + mydata_len,
1845 if (progress + mydata_len > re) {
1846 #ifdef DEBUG_VALIDATION
1847 uint32_t check = mydata_len;
1849 mydata_len = (uint32_t)(re - progress);
1851 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1852 "data is considered", mydata_len);
1855 if (mydata_len == 0)
1858 SCLogDebug(
"data %p len %u", mydata, mydata_len);
1861 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1864 if (mydata_offset == progress) {
1865 SCLogDebug(
"progress %"PRIu64
" increasing with data len %u to %"PRIu64,
1866 progress, mydata_len, progress_in + mydata_len);
1868 progress += mydata_len;
1869 SCLogDebug(
"raw progress now %"PRIu64, progress);
1872 }
else if (mydata_offset > progress && mydata_offset < re) {
1873 SCLogDebug(
"GAP: data is missing from %"PRIu64
" (%u bytes), setting to first data we have: %"PRIu64, progress, (uint32_t)(mydata_offset - progress), mydata_offset);
1875 progress = mydata_offset;
1876 SCLogDebug(
"raw progress now %"PRIu64, progress);
1880 }
else if (mydata_offset > progress && mydata_offset == re) {
1881 SCLogDebug(
"mydata_offset %" PRIu64
", progress %" PRIu64
", re %" PRIu64,
1882 mydata_offset, progress, re);
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);
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);
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;
2483 static int StreamTcpReassembleTest34(
void)
2492 uint8_t packet[1460] =
"";
2496 memset(&f, 0,
sizeof (
Flow));
2497 memset(&tcph, 0,
sizeof (
TCPHdr));
2502 f.
proto = IPPROTO_TCP;
2505 p->
proto = IPPROTO_TCP;
2514 tcph.
th_seq = htonl(857961230);
2520 tcph.
th_seq = htonl(857961534);
2526 tcph.
th_seq = htonl(857963582);
2532 tcph.
th_seq = htonl(857960946);
2553 static int StreamTcpReassembleTest39 (
void)
2563 memset (&f, 0,
sizeof(
Flow));
2565 memset(&stt, 0,
sizeof (stt));
2566 memset(&tcph, 0,
sizeof (
TCPHdr));
2570 f.
proto = IPPROTO_TCP;
2577 tcph.
th_win = htons(5480);
2645 uint8_t request1[] = { 0x47, 0x45, };
2692 uint8_t request2[] = {
2693 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
2694 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
2695 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
2696 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
2697 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
2698 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
2699 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
2700 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
2701 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
2702 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
2703 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
2728 uint8_t response[] = {
2729 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
2730 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
2731 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
2732 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
2733 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
2734 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
2735 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
2736 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
2737 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
2738 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
2739 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
2740 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
2741 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
2742 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
2743 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
2744 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
2745 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
2746 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
2747 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
2748 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
2749 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
2750 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
2751 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
2752 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
2753 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
2754 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
2755 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
2756 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
2757 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
2758 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
2759 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
2760 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
2761 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
2762 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
2763 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
2764 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
2765 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
2766 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
2767 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
2768 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
2769 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
2795 tcph.
th_ack = htonl(328);
2821 tcph.
th_seq = htonl(328);
2845 tcph.
th_ack = htonl(328);
2870 tcph.
th_seq = htonl(328);
2895 tcph.
th_ack = htonl(328);
2921 tcph.
th_seq = htonl(328);
2946 tcph.
th_ack = htonl(328);
2973 tcph.
th_ack = htonl(175);
2974 tcph.
th_seq = htonl(328);
3001 tcph.
th_ack = htonl(175);
3002 tcph.
th_seq = htonl(328);
3018 tcph.
th_ack = htonl(328);
3019 tcph.
th_seq = htonl(175);
3040 static int StreamTcpReassembleTest40 (
void)
3047 memset(&tcph, 0,
sizeof (
TCPHdr));
3057 uint8_t httpbuf1[] =
"P";
3058 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3059 uint8_t httpbuf3[] =
"O";
3060 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
3061 uint8_t httpbuf4[] =
"S";
3062 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
3063 uint8_t httpbuf5[] =
"T \r\n";
3064 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
3066 uint8_t httpbuf2[] =
"HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
3067 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3074 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3077 f->
proto = IPPROTO_TCP;
3080 tcph.
th_win = htons(5480);
3132 tcph.
th_ack = htonl(100);
3141 tcph.
th_seq = htonl(100);
3152 tcph.
th_ack = htonl(145);
3161 tcph.
th_seq = htonl(145);
3178 static int StreamTcpReassembleTest44(
void)
3182 StreamTcpReassembleIncrMemuse(500);
3184 StreamTcpReassembleDecrMemuse(500);
3200 static int StreamTcpReassembleTest45 (
void)
3205 memset(&
tv, 0,
sizeof(
tv));
3206 uint8_t payload[100] = {0};
3207 uint16_t payload_size = 100;
3238 static int StreamTcpReassembleTest46 (
void)
3243 memset(&
tv, 0,
sizeof(
tv));
3244 uint8_t payload[100] = {0};
3245 uint16_t payload_size = 100;
3276 static int StreamTcpReassembleTest47 (
void)
3284 memset(&tcph, 0,
sizeof (
TCPHdr));
3291 uint8_t httpbuf1[] =
"GET /EVILSUFF HTTP/1.1\r\n\r\n";
3292 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3300 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3303 f->
proto = IPPROTO_TCP;
3306 tcph.
th_win = htons(5480);
3313 tcph.
th_ack = htonl(572799782UL);
3325 tcph.
th_seq = htonl(572799782UL);
3344 static int StreamTcpReassembleInlineTest01(
void)
3351 memset(&
tv, 0x00,
sizeof(
tv));
3359 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3379 static int StreamTcpReassembleInlineTest02(
void)
3386 memset(&
tv, 0x00,
sizeof(
tv));
3394 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3417 static int StreamTcpReassembleInlineTest03(
void)
3424 memset(&
tv, 0x00,
sizeof(
tv));
3434 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3460 static int StreamTcpReassembleInlineTest04(
void)
3467 memset(&
tv, 0x00,
sizeof(
tv));
3477 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3504 static int StreamTcpReassembleInlineTest08(
void)
3508 memset(&
tv, 0x00,
sizeof(
tv));
3520 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3552 static int StreamTcpReassembleInlineTest09(
void)
3559 memset(&
tv, 0x00,
sizeof(
tv));
3569 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3601 static int StreamTcpReassembleInlineTest10(
void)
3608 memset(&
tv, 0x00,
sizeof(
tv));
3622 f->
proto = IPPROTO_TCP;
3624 uint8_t stream_payload1[] =
"GE";
3625 uint8_t stream_payload2[] =
"T /";
3626 uint8_t stream_payload3[] =
"HTTP/1.0\r\n\r\n";
3628 p =
UTHBuildPacketReal(stream_payload3, 12, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
3662 static int StreamTcpReassembleInsertTest01(
void)
3669 memset(&
tv, 0x00,
sizeof(
tv));
3677 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3699 static int StreamTcpReassembleInsertTest02(
void)
3705 memset(&
tv, 0x00,
sizeof(
tv));
3712 for (i = 2; i < 10; i++) {
3733 static int StreamTcpReassembleInsertTest03(
void)
3739 memset(&
tv, 0x00,
sizeof(
tv));
3748 for (i = 2; i < 10; i++) {
3775 UtRegisterTest(
"StreamTcpReassembleTest25 -- Gap at Start Reassembly Test",
3776 StreamTcpReassembleTest25);
3777 UtRegisterTest(
"StreamTcpReassembleTest26 -- Gap at middle Reassembly Test",
3778 StreamTcpReassembleTest26);
3780 "StreamTcpReassembleTest27 -- Gap at after Reassembly Test", StreamTcpReassembleTest27);
3781 UtRegisterTest(
"StreamTcpReassembleTest28 -- Gap at Start IDS missed packet Reassembly Test",
3782 StreamTcpReassembleTest28);
3783 UtRegisterTest(
"StreamTcpReassembleTest29 -- Gap at Middle IDS missed packet Reassembly Test",
3784 StreamTcpReassembleTest29);
3786 StreamTcpReassembleTest33);
3788 StreamTcpReassembleTest34);
3790 StreamTcpReassembleTest39);
3792 StreamTcpReassembleTest40);
3794 StreamTcpReassembleTest44);
3796 StreamTcpReassembleTest45);
3798 StreamTcpReassembleTest46);
3799 UtRegisterTest(
"StreamTcpReassembleTest47 -- TCP Sequence Wraparound Test",
3800 StreamTcpReassembleTest47);
3802 UtRegisterTest(
"StreamTcpReassembleInlineTest01 -- inline RAW ra",
3803 StreamTcpReassembleInlineTest01);
3804 UtRegisterTest(
"StreamTcpReassembleInlineTest02 -- inline RAW ra 2",
3805 StreamTcpReassembleInlineTest02);
3806 UtRegisterTest(
"StreamTcpReassembleInlineTest03 -- inline RAW ra 3",
3807 StreamTcpReassembleInlineTest03);
3808 UtRegisterTest(
"StreamTcpReassembleInlineTest04 -- inline RAW ra 4",
3809 StreamTcpReassembleInlineTest04);
3810 UtRegisterTest(
"StreamTcpReassembleInlineTest08 -- inline RAW ra 8 cleanup",
3811 StreamTcpReassembleInlineTest08);
3812 UtRegisterTest(
"StreamTcpReassembleInlineTest09 -- inline RAW ra 9 GAP cleanup",
3813 StreamTcpReassembleInlineTest09);
3815 UtRegisterTest(
"StreamTcpReassembleInlineTest10 -- inline APP ra 10",
3816 StreamTcpReassembleInlineTest10);
3818 UtRegisterTest(
"StreamTcpReassembleInsertTest01 -- insert with overlap",
3819 StreamTcpReassembleInsertTest01);
3820 UtRegisterTest(
"StreamTcpReassembleInsertTest02 -- insert with overlap",
3821 StreamTcpReassembleInsertTest02);
3822 UtRegisterTest(
"StreamTcpReassembleInsertTest03 -- insert with overlap",
3823 StreamTcpReassembleInsertTest03);
3828 StreamTcpReassembleRawRegisterTests();