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);
875 SCLogDebug(
"StreamTcpReassembleInsertSegment failed");
887 flag |= STREAM_START;
895 flag |= STREAM_MIDSTREAM;
902 if (&ssn->
client == stream) {
903 flag |= STREAM_TOSERVER;
905 flag |= STREAM_TOCLIENT;
908 flag |= STREAM_DEPTH;
919 static bool StreamTcpReassembleRawCheckLimit(
925 #define STREAMTCP_STREAM_FLAG_FLUSH_FLAGS \
926 ( STREAMTCP_STREAM_FLAG_DEPTH_REACHED \
927 | STREAMTCP_STREAM_FLAG_TRIGGER_RAW \
928 | STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED)
932 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_DEPTH_REACHED "
933 "is set, so not expecting any new data segments");
936 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_TRIGGER_RAW is set");
939 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED is set, "
940 "so no new segments will be considered");
944 #undef STREAMTCP_STREAM_FLAG_FLUSH_FLAGS
953 const uint64_t last_ack_abs = GetAbsLastAck(stream);
959 if (chunk_size <= diff) {
962 SCLogDebug(
"%s min chunk len not yet reached: "
963 "last_ack %" PRIu32
", ra_raw_base_seq %" PRIu32
", %" PRIu32
" < "
980 const char *dirstr = NULL;
982 if (direction == STREAM_TOSERVER) {
1006 const uint64_t right_edge =
1008 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
1009 " (use: %s). Stream right edge: %" PRIu64,
1013 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
1018 const uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
1019 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
1020 " (use: %s). Stream right edge: %" PRIu64,
1024 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
1029 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NONE", dirstr);
1034 static uint64_t GetStreamSize(
TcpStream *stream)
1039 uint64_t last_ack_abs = GetAbsLastAck(stream);
1040 uint64_t last_re = 0;
1046 const uint64_t seg_abs =
1048 if (last_re != 0 && last_re < seg_abs) {
1049 const char *gacked = NULL;
1050 if (last_ack_abs >= seg_abs) {
1051 gacked =
"fully ack'd";
1052 }
else if (last_ack_abs > last_re) {
1053 gacked =
"partly ack'd";
1055 gacked =
"not yet ack'd";
1057 SCLogDebug(
" -> gap of size %" PRIu64
", ack:%s", seg_abs - last_re, gacked);
1060 const char *acked = NULL;
1061 if (last_ack_abs >= seg_abs + (uint64_t)
TCP_SEG_LEN(seg)) {
1062 acked =
"fully ack'd";
1063 }
else if (last_ack_abs > seg_abs) {
1064 acked =
"partly ack'd";
1066 acked =
"not yet ack'd";
1069 SCLogDebug(
"%u -> seg %p seq %u abs %" PRIu64
" size %u abs %" PRIu64
" (%" PRIu64
1088 size = GetStreamSize(&ssn->
client);
1089 size += GetStreamSize(&ssn->
server);
1104 GetAbsLastAck(stream) > (cur_blk->
offset + cur_blk->
len)) {
1119 static bool GetAppBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1120 uint64_t
offset,
const bool check_for_gap)
1122 const uint8_t *mydata;
1123 uint32_t mydata_len;
1124 bool gap_ahead =
false;
1132 *data_len = mydata_len;
1151 gap_ahead = check_for_gap && GapAhead(stream, blk);
1155 SCLogDebug(
"gap, want data at offset %"PRIu64
", "
1156 "got data at %"PRIu64
". GAP of size %"PRIu64,
1163 SCLogDebug(
"get data from offset %"PRIu64
". SBB %"PRIu64
"/%u",
1166 SCLogDebug(
"data %p, data_len %u", *data, *data_len);
1168 gap_ahead = check_for_gap && GapAhead(stream, blk);
1187 const uint64_t last_ack_abs = GetAbsLastAck(stream) - (uint64_t)ackadded;
1194 if (last_ack_abs > app_progress) {
1201 "next_seq %u < last_ack %u, but no data in list",
1205 const uint64_t next_seq_abs =
1208 if (blk->
offset > next_seq_abs && blk->
offset < last_ack_abs) {
1211 "next_seq %u < last_ack %u, but ACK'd data beyond gap.",
1218 "last_ack_abs %" PRIu64
" > app_progress %" PRIu64
", "
1219 "but we have no data.",
1220 p->
pcap_cnt, last_ack_abs, app_progress);
1224 "last_ack_abs %"PRIu64
" <= app_progress %"PRIu64,
1225 p->
pcap_cnt, last_ack_abs, app_progress);
1229 static inline uint32_t AdjustToAcked(
const Packet *p,
1231 const uint64_t app_progress,
const uint32_t data_len)
1233 uint32_t adjusted = data_len;
1244 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1248 if (app_progress <= last_ack_abs && app_progress + data_len > last_ack_abs) {
1249 adjusted = (uint32_t)(last_ack_abs - app_progress);
1251 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1252 "data is considered", adjusted);
1269 SCLogDebug(
"app progress %"PRIu64, app_progress);
1271 uint64_t last_ack_abs = GetAbsLastAck(*stream);
1272 SCLogDebug(
"last_ack %u (abs %" PRIu64
"), base_seq %u", (*stream)->last_ack, last_ack_abs,
1273 (*stream)->base_seq);
1275 const uint8_t *mydata;
1276 uint32_t mydata_len;
1277 bool last_was_gap =
false;
1280 const uint8_t
flags = StreamGetAppLayerFlags(ssn, *stream, p);
1281 bool check_for_gap_ahead = ((*stream)->data_required > 0);
1283 GetAppBuffer(*stream, &mydata, &mydata_len, app_progress, check_for_gap_ahead);
1285 if (last_was_gap && mydata_len == 0) {
1288 last_was_gap =
false;
1291 mydata_len = AdjustToAcked(p, ssn, *stream, app_progress, mydata_len);
1293 if (mydata == NULL && mydata_len > 0 && CheckGap(ssn, *stream, p)) {
1294 SCLogDebug(
"sending GAP to app-layer (size: %u)", mydata_len);
1297 StreamGetAppLayerFlags(ssn, *stream, p) | STREAM_GAP, app_update_dir);
1311 if ((*stream)->data_required > 0) {
1312 if ((*stream)->data_required > mydata_len) {
1313 (*stream)->data_required -= mydata_len;
1315 (*stream)->data_required = 0;
1320 if (no_progress_update)
1322 last_was_gap =
true;
1325 }
else if (
flags & STREAM_DEPTH) {
1328 if (mydata == NULL && mydata_len > 0) {
1331 }
else if (mydata == NULL || (mydata_len == 0 && ((
flags & STREAM_EOF) == 0))) {
1344 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1345 *stream, &(*stream)->sb, mydata_len, app_progress);
1349 if (mydata_len < (*stream)->data_required) {
1352 SCLogDebug(
"GAP while expecting more data (expect %u, gap size %u)",
1353 (*stream)->data_required, mydata_len);
1354 (*stream)->app_progress_rel += mydata_len;
1355 (*stream)->data_required -= mydata_len;
1365 (*stream)->data_required = 0;
1370 mydata_len,
flags, app_update_dir);
1376 app_progress = new_app_progress;
1377 if (
flags & STREAM_DEPTH)
1405 SCLogDebug(
"stream no reassembly flag set or app-layer disabled.");
1411 GetSessionSize(ssn, p);
1422 uint8_t stream_flags = StreamGetAppLayerFlags(ssn, stream, p);
1424 tv, ra_ctx, p, p->
flow, ssn, &stream, NULL, 0, stream_flags, app_update_dir);
1432 return ReassembleUpdateAppLayer(
tv, ra_ctx, ssn, &stream, p, app_update_dir);
1438 static int GetRawBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1441 const uint8_t *mydata;
1442 uint32_t mydata_len;
1447 uint64_t roffset =
offset;
1455 *data_len = mydata_len;
1456 *data_offset = roffset;
1458 SCLogDebug(
"multiblob %s. Want offset %"PRIu64,
1459 *iter == NULL ?
"starting" :
"continuing",
offset);
1460 if (*iter == NULL) {
1465 if (*iter == NULL) {
1472 SCLogDebug(
"getting multiple blobs. Iter %p, %"PRIu64
"/%u", *iter, (*iter)->offset, (*iter)->len);
1477 if ((*iter)->offset <
offset) {
1478 uint64_t delta =
offset - (*iter)->offset;
1479 if (delta < mydata_len) {
1480 *data = mydata + delta;
1481 *data_len = (uint32_t)(mydata_len - delta);
1492 *data_len = mydata_len;
1493 *data_offset = (*iter)->offset;
1496 *iter = SBB_RB_NEXT(*iter);
1527 const uint64_t segs_re_abs =
1532 if (StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 1) {
1570 }
else if (progress == 0) {
1575 target = GetAbsLastAck(stream);
1585 SCLogDebug(
"p->pcap_cnt %"PRIu64
": progress %"PRIu64
" app %"PRIu64
" raw %"PRIu64
" tcp win %"PRIu32,
1594 SCLogDebug(
"ssn %p: STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED set, "
1595 "now that detect ran also set STREAMTCP_STREAM_FLAG_DISABLE_RAW", ssn);
1642 "packet payload len %u, so chunk_size adjusted to %u", p->
payload_len, chunk_size);
1645 const TCPHdr *tcph = PacketGetTCP(p);
1650 uint64_t packet_rightedge_abs = packet_leftedge_abs + p->
payload_len;
1651 SCLogDebug(
"packet_leftedge_abs %"PRIu64
", rightedge %"PRIu64,
1652 packet_leftedge_abs, packet_rightedge_abs);
1654 const uint8_t *mydata = NULL;
1655 uint32_t mydata_len = 0;
1656 uint64_t mydata_offset = 0;
1658 bool return_progress =
false;
1663 return_progress =
true;
1666 SCLogDebug(
"finding our SBB from offset %"PRIu64, packet_leftedge_abs);
1673 mydata_offset = sbb->
offset;
1678 uint64_t mydata_rightedge_abs = mydata_offset + mydata_len;
1679 if ((mydata == NULL || mydata_len == 0) ||
1680 (mydata_offset >= packet_rightedge_abs ||
1681 packet_leftedge_abs >= mydata_rightedge_abs) ||
1682 (packet_leftedge_abs < mydata_offset ||
1683 packet_rightedge_abs > mydata_rightedge_abs))
1688 mydata_offset = packet_leftedge_abs;
1692 SCLogDebug(
"chunk_size %u mydata_len %u", chunk_size, mydata_len);
1693 if (mydata_len > chunk_size) {
1694 uint32_t excess = mydata_len - chunk_size;
1695 SCLogDebug(
"chunk_size %u mydata_len %u excess %u", chunk_size, mydata_len, excess);
1697 if (mydata_rightedge_abs == packet_rightedge_abs) {
1699 mydata_len -= excess;
1700 mydata_offset += excess;
1701 SCLogDebug(
"cutting front of the buffer with %u", excess);
1702 }
else if (mydata_offset == packet_leftedge_abs) {
1703 mydata_len -= excess;
1704 SCLogDebug(
"cutting tail of the buffer with %u", excess);
1707 uint32_t abs_before = (uint32_t)(packet_leftedge_abs - mydata_offset);
1709 uint32_t abs_after = (uint32_t)(mydata_rightedge_abs - packet_rightedge_abs);
1710 uint32_t before = abs_before;
1711 uint32_t after = abs_after;
1712 SCLogDebug(
"before %u after %u", before, after);
1717 if (before >= (chunk_size - p->
payload_len) / 2) {
1719 before = after = (chunk_size - p->
payload_len) / 2;
1728 if (before >= (chunk_size - p->
payload_len) / 2) {
1737 uint32_t skip = abs_before - before;
1739 uint32_t cut = abs_after - after;
1744 mydata_len -= (skip + cut);
1745 mydata_offset += skip;
1751 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1754 if (return_progress) {
1755 *progress_out = (mydata_offset + mydata_len);
1762 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1763 SCLogDebug(
"last_ack_abs %"PRIu64, last_ack_abs);
1766 if (mydata_offset > last_ack_abs) {
1768 *progress_out = last_ack_abs;
1770 *progress_out = (mydata_offset + mydata_len);
1809 const uint64_t re, uint64_t *progress_out,
bool eof)
1815 uint64_t progress = progress_in;
1820 const uint8_t *mydata;
1821 uint32_t mydata_len;
1822 uint64_t mydata_offset = 0;
1824 GetRawBuffer(stream, &mydata, &mydata_len, &iter, progress, &mydata_offset);
1825 if (mydata_len == 0) {
1831 SCLogDebug(
"raw progress %"PRIu64, progress);
1832 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1833 stream, &stream->
sb, mydata_len, progress);
1838 if (re < progress) {
1843 SCLogDebug(
"re %" PRIu64
", raw_progress %" PRIu64, re, progress);
1844 SCLogDebug(
"raw_progress + mydata_len %" PRIu64
", re %" PRIu64, progress + mydata_len,
1848 if (progress + mydata_len > re) {
1849 #ifdef DEBUG_VALIDATION
1850 uint32_t check = mydata_len;
1852 mydata_len = (uint32_t)(re - progress);
1854 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1855 "data is considered", mydata_len);
1858 if (mydata_len == 0)
1861 SCLogDebug(
"data %p len %u", mydata, mydata_len);
1864 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1867 if (mydata_offset == progress) {
1868 SCLogDebug(
"progress %"PRIu64
" increasing with data len %u to %"PRIu64,
1869 progress, mydata_len, progress_in + mydata_len);
1871 progress += mydata_len;
1872 SCLogDebug(
"raw progress now %"PRIu64, progress);
1875 }
else if (mydata_offset > progress && mydata_offset < re) {
1876 SCLogDebug(
"GAP: data is missing from %"PRIu64
" (%u bytes), setting to first data we have: %"PRIu64, progress, (uint32_t)(mydata_offset - progress), mydata_offset);
1878 progress = mydata_offset;
1879 SCLogDebug(
"raw progress now %"PRIu64, progress);
1882 SCLogDebug(
"not increasing progress, data gap => mydata_offset "
1883 "%"PRIu64
" != progress %"PRIu64, mydata_offset, progress);
1886 if (iter == NULL || r == 1)
1890 *progress_out = progress;
1895 void *cb_data,
const uint64_t
offset,
const bool eof)
1899 SCLogDebug(
"app_progress %" PRIu64, app_progress);
1901 uint64_t unused = 0;
1902 return StreamReassembleRawDo(
1903 ssn, stream, Callback, cb_data,
offset, app_progress, &unused, eof);
1908 uint64_t *progress_out,
bool respect_inspect_depth)
1912 return StreamReassembleRawInline(ssn, p, Callback, cb_data, progress_out);
1923 StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 0)
1935 SCLogDebug(
"respect_inspect_depth %s STREAMTCP_STREAM_FLAG_TRIGGER_RAW %s "
1936 "stream->min_inspect_depth %u",
1937 respect_inspect_depth ?
"true" :
"false",
1954 SCLogDebug(
"applied min inspect depth due to STREAMTCP_STREAM_FLAG_TRIGGER_RAW: progress "
1964 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1965 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1967 return StreamReassembleRawDo(ssn, stream, Callback, cb_data, progress, last_ack_abs,
1973 uint64_t *progress_out,
const bool eof)
1979 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1980 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1982 return StreamReassembleRawDo(
1983 ssn, stream, Callback, cb_data, progress_in, last_ack_abs, progress_out, eof);
1991 static int StreamTcpReassembleHandleSegmentUpdateACK (
ThreadVars *
tv,
2008 const TCPHdr *tcph = PacketGetTCP(p);
2010 SCLogDebug(
"ssn %p, stream %p, p %p, p->payload_len %"PRIu16
"",
2040 if (stream == &ssn->
client) {
2041 opposing_stream = &ssn->
server;
2043 opposing_stream = &ssn->
client;
2048 if (StreamTcpReassembleHandleSegmentUpdateACK(
tv, ra_ctx, ssn, opposing_stream, p) != 0) {
2049 SCLogDebug(
"StreamTcpReassembleHandleSegmentUpdateACK error");
2057 if (reversed_before_ack_handling != reversed_after_ack_handling) {
2059 stream = opposing_stream;
2065 SCLogDebug(
"calling StreamTcpReassembleHandleSegmentHandleData");
2068 SCLogDebug(
"StreamTcpReassembleHandleSegmentHandleData error");
2072 StreamTcpReassembleExceptionPolicyStatsIncr(
2080 SCLogDebug(
"ssn %p / stream %p: not calling StreamTcpReassembleHandleSegmentHandleData:"
2081 " p->payload_len %u, STREAMTCP_STREAM_FLAG_NOREASSEMBLY %s",
2091 if ((stream->
flags &
2095 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED, truncate applayer");
2097 SCLogDebug(
"override: direction now UPDATE_DIR_PACKET so we "
2098 "can trigger Truncate");
2106 SCLogDebug(
"inline (%s) or PKT_PSEUDO_STREAM_END (%s)",
2165 if (direction == STREAM_TOSERVER) {
2171 SCLogDebug(
"flagged ssn %p for immediate raw reassembly", ssn);
2182 if (direction == STREAM_TOSERVER) {
2184 SCLogDebug(
"ssn %p: set client.min_inspect_depth to %u", ssn, depth);
2187 SCLogDebug(
"ssn %p: set server.min_inspect_depth to %u", ssn, depth);
2195 #define SET_ISN(stream, setseq) \
2196 (stream)->isn = (setseq); \
2197 (stream)->base_seq = (setseq) + 1
2215 for (; i <
len; i++)
2229 data, data_len) == 0)
2238 #define MISSED_START(isn) \
2239 TcpReassemblyThreadCtx *ra_ctx = NULL; \
2242 memset(&tv, 0, sizeof(tv)); \
2244 StreamTcpUTInit(&ra_ctx); \
2246 StreamTcpUTSetupSession(&ssn); \
2247 StreamTcpUTSetupStream(&ssn.server, (isn)); \
2248 StreamTcpUTSetupStream(&ssn.client, (isn)); \
2250 TcpStream *stream = &ssn.client;
2252 #define MISSED_END \
2253 StreamTcpUTClearSession(&ssn); \
2254 StreamTcpUTDeinit(ra_ctx); \
2257 #define MISSED_STEP(seq, seg, seglen, buf, buflen) \
2258 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen)); \
2259 FAIL_IF(!(VALIDATE(stream, (uint8_t *)(buf), (buflen))));
2261 #define MISSED_ADD_PAYLOAD(seq, seg, seglen) \
2262 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen));
2269 uint64_t last_re = 0;
2273 if (sbb->
offset != last_re) {
2293 uint64_t last_re = 0;
2297 if (sbb->
offset != last_re) {
2303 const uint8_t *buf = NULL;
2304 uint32_t buf_len = 0;
2307 if (
len == buf_len) {
2308 return (memcmp(data, buf,
len) == 0);
2325 static int StreamTcpReassembleTest25 (
void)
2346 static int StreamTcpReassembleTest26 (
void)
2365 static int StreamTcpReassembleTest27 (
void)
2382 static int StreamTcpReassembleTest28 (
void)
2406 static int StreamTcpReassembleTest29 (
void)
2418 static int StreamTcpReassembleTest33(
void)
2427 uint8_t packet[1460] =
"";
2432 memset(&f, 0,
sizeof (
Flow));
2433 memset(&tcph, 0,
sizeof (
TCPHdr));
2438 f.
proto = IPPROTO_TCP;
2441 p->
proto = IPPROTO_TCP;
2480 static int StreamTcpReassembleTest34(
void)
2489 uint8_t packet[1460] =
"";
2493 memset(&f, 0,
sizeof (
Flow));
2494 memset(&tcph, 0,
sizeof (
TCPHdr));
2499 f.
proto = IPPROTO_TCP;
2502 p->
proto = IPPROTO_TCP;
2511 tcph.
th_seq = htonl(857961230);
2517 tcph.
th_seq = htonl(857961534);
2523 tcph.
th_seq = htonl(857963582);
2529 tcph.
th_seq = htonl(857960946);
2550 static int StreamTcpReassembleTest39 (
void)
2560 memset (&f, 0,
sizeof(
Flow));
2562 memset(&stt, 0,
sizeof (stt));
2563 memset(&tcph, 0,
sizeof (
TCPHdr));
2567 f.
proto = IPPROTO_TCP;
2574 tcph.
th_win = htons(5480);
2642 uint8_t request1[] = { 0x47, 0x45, };
2689 uint8_t request2[] = {
2690 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
2691 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
2692 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
2693 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
2694 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
2695 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
2696 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
2697 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
2698 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
2699 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
2700 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
2725 uint8_t response[] = {
2726 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
2727 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
2728 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
2729 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
2730 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
2731 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
2732 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
2733 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
2734 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
2735 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
2736 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
2737 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
2738 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
2739 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
2740 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
2741 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
2742 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
2743 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
2744 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
2745 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
2746 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
2747 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
2748 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
2749 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
2750 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
2751 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
2752 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
2753 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
2754 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
2755 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
2756 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
2757 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
2758 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
2759 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
2760 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
2761 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
2762 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
2763 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
2764 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
2765 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
2766 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
2792 tcph.
th_ack = htonl(328);
2818 tcph.
th_seq = htonl(328);
2842 tcph.
th_ack = htonl(328);
2867 tcph.
th_seq = htonl(328);
2892 tcph.
th_ack = htonl(328);
2918 tcph.
th_seq = htonl(328);
2943 tcph.
th_ack = htonl(328);
2970 tcph.
th_ack = htonl(175);
2971 tcph.
th_seq = htonl(328);
2998 tcph.
th_ack = htonl(175);
2999 tcph.
th_seq = htonl(328);
3015 tcph.
th_ack = htonl(328);
3016 tcph.
th_seq = htonl(175);
3037 static int StreamTcpReassembleTest40 (
void)
3044 memset(&tcph, 0,
sizeof (
TCPHdr));
3054 uint8_t httpbuf1[] =
"P";
3055 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3056 uint8_t httpbuf3[] =
"O";
3057 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
3058 uint8_t httpbuf4[] =
"S";
3059 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
3060 uint8_t httpbuf5[] =
"T \r\n";
3061 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
3063 uint8_t httpbuf2[] =
"HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
3064 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3071 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3074 f->
proto = IPPROTO_TCP;
3077 tcph.
th_win = htons(5480);
3129 tcph.
th_ack = htonl(100);
3138 tcph.
th_seq = htonl(100);
3149 tcph.
th_ack = htonl(145);
3158 tcph.
th_seq = htonl(145);
3175 static int StreamTcpReassembleTest44(
void)
3179 StreamTcpReassembleIncrMemuse(500);
3181 StreamTcpReassembleDecrMemuse(500);
3197 static int StreamTcpReassembleTest45 (
void)
3202 memset(&
tv, 0,
sizeof(
tv));
3203 uint8_t payload[100] = {0};
3204 uint16_t payload_size = 100;
3235 static int StreamTcpReassembleTest46 (
void)
3240 memset(&
tv, 0,
sizeof(
tv));
3241 uint8_t payload[100] = {0};
3242 uint16_t payload_size = 100;
3273 static int StreamTcpReassembleTest47 (
void)
3281 memset(&tcph, 0,
sizeof (
TCPHdr));
3288 uint8_t httpbuf1[] =
"GET /EVILSUFF HTTP/1.1\r\n\r\n";
3289 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3297 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3300 f->
proto = IPPROTO_TCP;
3303 tcph.
th_win = htons(5480);
3310 tcph.
th_ack = htonl(572799782UL);
3322 tcph.
th_seq = htonl(572799782UL);
3341 static int StreamTcpReassembleInlineTest01(
void)
3348 memset(&
tv, 0x00,
sizeof(
tv));
3356 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3376 static int StreamTcpReassembleInlineTest02(
void)
3383 memset(&
tv, 0x00,
sizeof(
tv));
3391 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3414 static int StreamTcpReassembleInlineTest03(
void)
3421 memset(&
tv, 0x00,
sizeof(
tv));
3431 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3457 static int StreamTcpReassembleInlineTest04(
void)
3464 memset(&
tv, 0x00,
sizeof(
tv));
3474 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3501 static int StreamTcpReassembleInlineTest08(
void)
3505 memset(&
tv, 0x00,
sizeof(
tv));
3517 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3549 static int StreamTcpReassembleInlineTest09(
void)
3556 memset(&
tv, 0x00,
sizeof(
tv));
3566 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3598 static int StreamTcpReassembleInlineTest10(
void)
3605 memset(&
tv, 0x00,
sizeof(
tv));
3619 f->
proto = IPPROTO_TCP;
3621 uint8_t stream_payload1[] =
"GE";
3622 uint8_t stream_payload2[] =
"T /";
3623 uint8_t stream_payload3[] =
"HTTP/1.0\r\n\r\n";
3625 p =
UTHBuildPacketReal(stream_payload3, 12, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
3659 static int StreamTcpReassembleInsertTest01(
void)
3666 memset(&
tv, 0x00,
sizeof(
tv));
3674 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3696 static int StreamTcpReassembleInsertTest02(
void)
3702 memset(&
tv, 0x00,
sizeof(
tv));
3709 for (i = 2; i < 10; i++) {
3730 static int StreamTcpReassembleInsertTest03(
void)
3736 memset(&
tv, 0x00,
sizeof(
tv));
3745 for (i = 2; i < 10; i++) {
3772 UtRegisterTest(
"StreamTcpReassembleTest25 -- Gap at Start Reassembly Test",
3773 StreamTcpReassembleTest25);
3774 UtRegisterTest(
"StreamTcpReassembleTest26 -- Gap at middle Reassembly Test",
3775 StreamTcpReassembleTest26);
3776 UtRegisterTest(
"StreamTcpReassembleTest27 -- Gap at after Reassembly Test",
3777 StreamTcpReassembleTest27);
3778 UtRegisterTest(
"StreamTcpReassembleTest28 -- Gap at Start IDS missed packet Reassembly Test",
3779 StreamTcpReassembleTest28);
3780 UtRegisterTest(
"StreamTcpReassembleTest29 -- Gap at Middle IDS missed packet Reassembly Test",
3781 StreamTcpReassembleTest29);
3783 StreamTcpReassembleTest33);
3785 StreamTcpReassembleTest34);
3787 StreamTcpReassembleTest39);
3789 StreamTcpReassembleTest40);
3791 StreamTcpReassembleTest44);
3793 StreamTcpReassembleTest45);
3795 StreamTcpReassembleTest46);
3796 UtRegisterTest(
"StreamTcpReassembleTest47 -- TCP Sequence Wraparound Test",
3797 StreamTcpReassembleTest47);
3799 UtRegisterTest(
"StreamTcpReassembleInlineTest01 -- inline RAW ra",
3800 StreamTcpReassembleInlineTest01);
3801 UtRegisterTest(
"StreamTcpReassembleInlineTest02 -- inline RAW ra 2",
3802 StreamTcpReassembleInlineTest02);
3803 UtRegisterTest(
"StreamTcpReassembleInlineTest03 -- inline RAW ra 3",
3804 StreamTcpReassembleInlineTest03);
3805 UtRegisterTest(
"StreamTcpReassembleInlineTest04 -- inline RAW ra 4",
3806 StreamTcpReassembleInlineTest04);
3807 UtRegisterTest(
"StreamTcpReassembleInlineTest08 -- inline RAW ra 8 cleanup",
3808 StreamTcpReassembleInlineTest08);
3809 UtRegisterTest(
"StreamTcpReassembleInlineTest09 -- inline RAW ra 9 GAP cleanup",
3810 StreamTcpReassembleInlineTest09);
3812 UtRegisterTest(
"StreamTcpReassembleInlineTest10 -- inline APP ra 10",
3813 StreamTcpReassembleInlineTest10);
3815 UtRegisterTest(
"StreamTcpReassembleInsertTest01 -- insert with overlap",
3816 StreamTcpReassembleInsertTest01);
3817 UtRegisterTest(
"StreamTcpReassembleInsertTest02 -- insert with overlap",
3818 StreamTcpReassembleInsertTest02);
3819 UtRegisterTest(
"StreamTcpReassembleInsertTest03 -- insert with overlap",
3820 StreamTcpReassembleInsertTest03);
3825 StreamTcpReassembleRawRegisterTests();