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)) {
1118 static bool GetAppBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1119 uint64_t
offset,
const bool check_for_gap)
1121 const uint8_t *mydata;
1122 uint32_t mydata_len;
1123 bool gap_ahead =
false;
1131 *data_len = mydata_len;
1150 gap_ahead = check_for_gap && GapAhead(stream, blk);
1154 SCLogDebug(
"gap, want data at offset %"PRIu64
", "
1155 "got data at %"PRIu64
". GAP of size %"PRIu64,
1162 SCLogDebug(
"get data from offset %"PRIu64
". SBB %"PRIu64
"/%u",
1165 SCLogDebug(
"data %p, data_len %u", *data, *data_len);
1167 gap_ahead = check_for_gap && GapAhead(stream, blk);
1186 const uint64_t last_ack_abs = GetAbsLastAck(stream) - (uint64_t)ackadded;
1193 if (last_ack_abs > app_progress) {
1200 "next_seq %u < last_ack %u, but no data in list",
1204 const uint64_t next_seq_abs =
1207 if (blk->
offset > next_seq_abs && blk->
offset < last_ack_abs) {
1210 "next_seq %u < last_ack %u, but ACK'd data beyond gap.",
1217 "last_ack_abs %" PRIu64
" > app_progress %" PRIu64
", "
1218 "but we have no data.",
1223 "last_ack_abs %" PRIu64
" <= app_progress %" PRIu64,
1228 static inline uint32_t AdjustToAcked(
const Packet *p,
1230 const uint64_t app_progress,
const uint32_t data_len)
1232 uint32_t adjusted = data_len;
1243 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1247 if (app_progress <= last_ack_abs && app_progress + data_len > last_ack_abs) {
1248 adjusted = (uint32_t)(last_ack_abs - app_progress);
1250 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1251 "data is considered", adjusted);
1268 SCLogDebug(
"app progress %"PRIu64, app_progress);
1270 uint64_t last_ack_abs = GetAbsLastAck(*stream);
1271 SCLogDebug(
"last_ack %u (abs %" PRIu64
"), base_seq %u", (*stream)->last_ack, last_ack_abs,
1272 (*stream)->base_seq);
1274 const uint8_t *mydata;
1275 uint32_t mydata_len;
1276 bool last_was_gap =
false;
1279 const uint8_t
flags = StreamGetAppLayerFlags(ssn, *stream, p);
1280 bool check_for_gap_ahead = ((*stream)->data_required > 0);
1282 GetAppBuffer(*stream, &mydata, &mydata_len, app_progress, check_for_gap_ahead);
1284 if (last_was_gap && mydata_len == 0) {
1287 last_was_gap =
false;
1290 mydata_len = AdjustToAcked(p, ssn, *stream, app_progress, mydata_len);
1292 if (mydata == NULL && mydata_len > 0 && CheckGap(ssn, *stream, p)) {
1293 SCLogDebug(
"sending GAP to app-layer (size: %u)", mydata_len);
1296 StreamGetAppLayerFlags(ssn, *stream, p) | STREAM_GAP, app_update_dir);
1310 if ((*stream)->data_required > 0) {
1311 if ((*stream)->data_required > mydata_len) {
1312 (*stream)->data_required -= mydata_len;
1314 (*stream)->data_required = 0;
1319 if (no_progress_update)
1321 last_was_gap =
true;
1324 }
else if (
flags & STREAM_DEPTH) {
1327 if (mydata == NULL && mydata_len > 0) {
1330 }
else if (mydata == NULL || (mydata_len == 0 && ((
flags & STREAM_EOF) == 0))) {
1343 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1344 *stream, &(*stream)->sb, mydata_len, app_progress);
1348 if (mydata_len < (*stream)->data_required) {
1351 SCLogDebug(
"GAP while expecting more data (expect %u, gap size %u)",
1352 (*stream)->data_required, mydata_len);
1353 (*stream)->app_progress_rel += mydata_len;
1354 (*stream)->data_required -= mydata_len;
1364 (*stream)->data_required = 0;
1369 mydata_len,
flags, app_update_dir);
1375 app_progress = new_app_progress;
1376 if (
flags & STREAM_DEPTH)
1404 SCLogDebug(
"stream no reassembly flag set or app-layer disabled.");
1410 GetSessionSize(ssn, p);
1421 uint8_t stream_flags = StreamGetAppLayerFlags(ssn, stream, p);
1423 tv, ra_ctx, p, p->
flow, ssn, &stream, NULL, 0, stream_flags, app_update_dir);
1431 return ReassembleUpdateAppLayer(
tv, ra_ctx, ssn, &stream, p, app_update_dir);
1437 static int GetRawBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1440 const uint8_t *mydata;
1441 uint32_t mydata_len;
1446 uint64_t roffset =
offset;
1454 *data_len = mydata_len;
1455 *data_offset = roffset;
1457 SCLogDebug(
"multiblob %s. Want offset %"PRIu64,
1458 *iter == NULL ?
"starting" :
"continuing",
offset);
1459 if (*iter == NULL) {
1464 if (*iter == NULL) {
1471 SCLogDebug(
"getting multiple blobs. Iter %p, %"PRIu64
"/%u", *iter, (*iter)->offset, (*iter)->len);
1476 if ((*iter)->offset <
offset) {
1477 uint64_t delta =
offset - (*iter)->offset;
1478 if (delta < mydata_len) {
1479 *data = mydata + delta;
1480 *data_len = (uint32_t)(mydata_len - delta);
1491 *data_len = mydata_len;
1492 *data_offset = (*iter)->offset;
1495 *iter = SBB_RB_NEXT(*iter);
1526 const uint64_t segs_re_abs =
1531 if (StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 1) {
1569 }
else if (progress == 0) {
1574 target = GetAbsLastAck(stream);
1584 SCLogDebug(
"pcap_cnt %" PRIu64
": progress %" PRIu64
" app %" PRIu64
" raw %" PRIu64
1585 " 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);
1883 }
else if (mydata_offset > progress && mydata_offset == re) {
1884 SCLogDebug(
"mydata_offset %" PRIu64
", progress %" PRIu64
", re %" PRIu64,
1885 mydata_offset, progress, re);
1888 SCLogDebug(
"not increasing progress, data gap => mydata_offset "
1889 "%"PRIu64
" != progress %"PRIu64, mydata_offset, progress);
1892 if (iter == NULL || r == 1)
1896 *progress_out = progress;
1901 void *cb_data,
const uint64_t
offset,
const bool eof)
1905 SCLogDebug(
"app_progress %" PRIu64, app_progress);
1907 uint64_t unused = 0;
1908 return StreamReassembleRawDo(
1909 ssn, stream, Callback, cb_data,
offset, app_progress, &unused, eof);
1914 uint64_t *progress_out,
bool respect_inspect_depth)
1918 return StreamReassembleRawInline(ssn, p, Callback, cb_data, progress_out);
1929 StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 0)
1941 SCLogDebug(
"respect_inspect_depth %s STREAMTCP_STREAM_FLAG_TRIGGER_RAW %s "
1942 "stream->min_inspect_depth %u",
1943 respect_inspect_depth ?
"true" :
"false",
1960 SCLogDebug(
"applied min inspect depth due to STREAMTCP_STREAM_FLAG_TRIGGER_RAW: progress "
1970 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1971 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1973 return StreamReassembleRawDo(ssn, stream, Callback, cb_data, progress, last_ack_abs,
1979 uint64_t *progress_out,
const bool eof)
1985 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1986 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1988 return StreamReassembleRawDo(
1989 ssn, stream, Callback, cb_data, progress_in, last_ack_abs, progress_out, eof);
1997 static int StreamTcpReassembleHandleSegmentUpdateACK (
ThreadVars *
tv,
2014 const TCPHdr *tcph = PacketGetTCP(p);
2016 SCLogDebug(
"ssn %p, stream %p, p %p, p->payload_len %"PRIu16
"",
2046 if (stream == &ssn->
client) {
2047 opposing_stream = &ssn->
server;
2049 opposing_stream = &ssn->
client;
2054 if (StreamTcpReassembleHandleSegmentUpdateACK(
tv, ra_ctx, ssn, opposing_stream, p) != 0) {
2055 SCLogDebug(
"StreamTcpReassembleHandleSegmentUpdateACK error");
2063 if (reversed_before_ack_handling != reversed_after_ack_handling) {
2065 stream = opposing_stream;
2071 SCLogDebug(
"calling StreamTcpReassembleHandleSegmentHandleData");
2074 SCLogDebug(
"StreamTcpReassembleHandleSegmentHandleData error");
2078 StreamTcpReassembleExceptionPolicyStatsIncr(
2086 SCLogDebug(
"ssn %p / stream %p: not calling StreamTcpReassembleHandleSegmentHandleData:"
2087 " p->payload_len %u, STREAMTCP_STREAM_FLAG_NOREASSEMBLY %s",
2097 if ((stream->
flags &
2101 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED, truncate applayer");
2103 SCLogDebug(
"override: direction now UPDATE_DIR_PACKET so we "
2104 "can trigger Truncate");
2112 SCLogDebug(
"inline (%s) or PKT_PSEUDO_STREAM_END (%s)",
2171 if (direction == STREAM_TOSERVER) {
2177 SCLogDebug(
"flagged ssn %p for immediate raw reassembly", ssn);
2188 if (direction == STREAM_TOSERVER) {
2190 SCLogDebug(
"ssn %p: set client.min_inspect_depth to %u", ssn, depth);
2193 SCLogDebug(
"ssn %p: set server.min_inspect_depth to %u", ssn, depth);
2201 #define SET_ISN(stream, setseq) \
2202 (stream)->isn = (setseq); \
2203 (stream)->base_seq = (setseq) + 1
2221 for (; i <
len; i++)
2235 data, data_len) == 0)
2244 #define MISSED_START(isn) \
2245 TcpReassemblyThreadCtx *ra_ctx = NULL; \
2248 memset(&tv, 0, sizeof(tv)); \
2250 StreamTcpUTInit(&ra_ctx); \
2252 StreamTcpUTSetupSession(&ssn); \
2253 StreamTcpUTSetupStream(&ssn.server, (isn)); \
2254 StreamTcpUTSetupStream(&ssn.client, (isn)); \
2256 TcpStream *stream = &ssn.client;
2258 #define MISSED_END \
2259 StreamTcpUTClearSession(&ssn); \
2260 StreamTcpUTDeinit(ra_ctx); \
2263 #define MISSED_STEP(seq, seg, seglen, buf, buflen) \
2264 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen)); \
2265 FAIL_IF(!(VALIDATE(stream, (uint8_t *)(buf), (buflen))));
2267 #define MISSED_ADD_PAYLOAD(seq, seg, seglen) \
2268 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen));
2275 uint64_t last_re = 0;
2279 if (sbb->
offset != last_re) {
2299 uint64_t last_re = 0;
2303 if (sbb->
offset != last_re) {
2309 const uint8_t *buf = NULL;
2310 uint32_t buf_len = 0;
2313 if (
len == buf_len) {
2314 return (memcmp(data, buf,
len) == 0);
2331 static int StreamTcpReassembleTest25 (
void)
2352 static int StreamTcpReassembleTest26 (
void)
2371 static int StreamTcpReassembleTest27 (
void)
2388 static int StreamTcpReassembleTest28 (
void)
2412 static int StreamTcpReassembleTest29 (
void)
2424 static int StreamTcpReassembleTest33(
void)
2433 uint8_t packet[1460] =
"";
2438 memset(&f, 0,
sizeof (
Flow));
2439 memset(&tcph, 0,
sizeof (
TCPHdr));
2444 f.
proto = IPPROTO_TCP;
2447 p->
proto = IPPROTO_TCP;
2486 static int StreamTcpReassembleTest34(
void)
2495 uint8_t packet[1460] =
"";
2499 memset(&f, 0,
sizeof (
Flow));
2500 memset(&tcph, 0,
sizeof (
TCPHdr));
2505 f.
proto = IPPROTO_TCP;
2508 p->
proto = IPPROTO_TCP;
2517 tcph.
th_seq = htonl(857961230);
2523 tcph.
th_seq = htonl(857961534);
2529 tcph.
th_seq = htonl(857963582);
2535 tcph.
th_seq = htonl(857960946);
2556 static int StreamTcpReassembleTest39 (
void)
2566 memset (&f, 0,
sizeof(
Flow));
2568 memset(&stt, 0,
sizeof (stt));
2569 memset(&tcph, 0,
sizeof (
TCPHdr));
2573 f.
proto = IPPROTO_TCP;
2580 tcph.
th_win = htons(5480);
2648 uint8_t request1[] = { 0x47, 0x45, };
2695 uint8_t request2[] = {
2696 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
2697 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
2698 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
2699 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
2700 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
2701 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
2702 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
2703 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
2704 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
2705 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
2706 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
2731 uint8_t response[] = {
2732 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
2733 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
2734 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
2735 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
2736 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
2737 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
2738 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
2739 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
2740 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
2741 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
2742 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
2743 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
2744 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
2745 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
2746 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
2747 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
2748 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
2749 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
2750 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
2751 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
2752 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
2753 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
2754 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
2755 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
2756 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
2757 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
2758 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
2759 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
2760 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
2761 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
2762 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
2763 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
2764 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
2765 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
2766 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
2767 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
2768 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
2769 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
2770 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
2771 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
2772 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
2798 tcph.
th_ack = htonl(328);
2824 tcph.
th_seq = htonl(328);
2848 tcph.
th_ack = htonl(328);
2873 tcph.
th_seq = htonl(328);
2898 tcph.
th_ack = htonl(328);
2924 tcph.
th_seq = htonl(328);
2949 tcph.
th_ack = htonl(328);
2976 tcph.
th_ack = htonl(175);
2977 tcph.
th_seq = htonl(328);
3004 tcph.
th_ack = htonl(175);
3005 tcph.
th_seq = htonl(328);
3021 tcph.
th_ack = htonl(328);
3022 tcph.
th_seq = htonl(175);
3043 static int StreamTcpReassembleTest40 (
void)
3050 memset(&tcph, 0,
sizeof (
TCPHdr));
3060 uint8_t httpbuf1[] =
"P";
3061 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3062 uint8_t httpbuf3[] =
"O";
3063 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
3064 uint8_t httpbuf4[] =
"S";
3065 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
3066 uint8_t httpbuf5[] =
"T \r\n";
3067 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
3069 uint8_t httpbuf2[] =
"HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
3070 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3077 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3080 f->
proto = IPPROTO_TCP;
3083 tcph.
th_win = htons(5480);
3135 tcph.
th_ack = htonl(100);
3144 tcph.
th_seq = htonl(100);
3155 tcph.
th_ack = htonl(145);
3164 tcph.
th_seq = htonl(145);
3181 static int StreamTcpReassembleTest44(
void)
3185 StreamTcpReassembleIncrMemuse(500);
3187 StreamTcpReassembleDecrMemuse(500);
3203 static int StreamTcpReassembleTest45 (
void)
3208 memset(&
tv, 0,
sizeof(
tv));
3209 uint8_t payload[100] = {0};
3210 uint16_t payload_size = 100;
3241 static int StreamTcpReassembleTest46 (
void)
3246 memset(&
tv, 0,
sizeof(
tv));
3247 uint8_t payload[100] = {0};
3248 uint16_t payload_size = 100;
3279 static int StreamTcpReassembleTest47 (
void)
3287 memset(&tcph, 0,
sizeof (
TCPHdr));
3294 uint8_t httpbuf1[] =
"GET /EVILSUFF HTTP/1.1\r\n\r\n";
3295 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3303 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3306 f->
proto = IPPROTO_TCP;
3309 tcph.
th_win = htons(5480);
3316 tcph.
th_ack = htonl(572799782UL);
3328 tcph.
th_seq = htonl(572799782UL);
3347 static int StreamTcpReassembleInlineTest01(
void)
3354 memset(&
tv, 0x00,
sizeof(
tv));
3362 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3382 static int StreamTcpReassembleInlineTest02(
void)
3389 memset(&
tv, 0x00,
sizeof(
tv));
3397 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3420 static int StreamTcpReassembleInlineTest03(
void)
3427 memset(&
tv, 0x00,
sizeof(
tv));
3437 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3463 static int StreamTcpReassembleInlineTest04(
void)
3470 memset(&
tv, 0x00,
sizeof(
tv));
3480 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3507 static int StreamTcpReassembleInlineTest08(
void)
3511 memset(&
tv, 0x00,
sizeof(
tv));
3523 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3555 static int StreamTcpReassembleInlineTest09(
void)
3562 memset(&
tv, 0x00,
sizeof(
tv));
3572 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3604 static int StreamTcpReassembleInlineTest10(
void)
3611 memset(&
tv, 0x00,
sizeof(
tv));
3625 f->
proto = IPPROTO_TCP;
3627 uint8_t stream_payload1[] =
"GE";
3628 uint8_t stream_payload2[] =
"T /";
3629 uint8_t stream_payload3[] =
"HTTP/1.0\r\n\r\n";
3631 p =
UTHBuildPacketReal(stream_payload3, 12, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
3665 static int StreamTcpReassembleInsertTest01(
void)
3672 memset(&
tv, 0x00,
sizeof(
tv));
3680 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3702 static int StreamTcpReassembleInsertTest02(
void)
3708 memset(&
tv, 0x00,
sizeof(
tv));
3715 for (i = 2; i < 10; i++) {
3736 static int StreamTcpReassembleInsertTest03(
void)
3742 memset(&
tv, 0x00,
sizeof(
tv));
3751 for (i = 2; i < 10; i++) {
3778 UtRegisterTest(
"StreamTcpReassembleTest25 -- Gap at Start Reassembly Test",
3779 StreamTcpReassembleTest25);
3780 UtRegisterTest(
"StreamTcpReassembleTest26 -- Gap at middle Reassembly Test",
3781 StreamTcpReassembleTest26);
3783 "StreamTcpReassembleTest27 -- Gap at after Reassembly Test", StreamTcpReassembleTest27);
3784 UtRegisterTest(
"StreamTcpReassembleTest28 -- Gap at Start IDS missed packet Reassembly Test",
3785 StreamTcpReassembleTest28);
3786 UtRegisterTest(
"StreamTcpReassembleTest29 -- Gap at Middle IDS missed packet Reassembly Test",
3787 StreamTcpReassembleTest29);
3789 StreamTcpReassembleTest33);
3791 StreamTcpReassembleTest34);
3793 StreamTcpReassembleTest39);
3795 StreamTcpReassembleTest40);
3797 StreamTcpReassembleTest44);
3799 StreamTcpReassembleTest45);
3801 StreamTcpReassembleTest46);
3802 UtRegisterTest(
"StreamTcpReassembleTest47 -- TCP Sequence Wraparound Test",
3803 StreamTcpReassembleTest47);
3805 UtRegisterTest(
"StreamTcpReassembleInlineTest01 -- inline RAW ra",
3806 StreamTcpReassembleInlineTest01);
3807 UtRegisterTest(
"StreamTcpReassembleInlineTest02 -- inline RAW ra 2",
3808 StreamTcpReassembleInlineTest02);
3809 UtRegisterTest(
"StreamTcpReassembleInlineTest03 -- inline RAW ra 3",
3810 StreamTcpReassembleInlineTest03);
3811 UtRegisterTest(
"StreamTcpReassembleInlineTest04 -- inline RAW ra 4",
3812 StreamTcpReassembleInlineTest04);
3813 UtRegisterTest(
"StreamTcpReassembleInlineTest08 -- inline RAW ra 8 cleanup",
3814 StreamTcpReassembleInlineTest08);
3815 UtRegisterTest(
"StreamTcpReassembleInlineTest09 -- inline RAW ra 9 GAP cleanup",
3816 StreamTcpReassembleInlineTest09);
3818 UtRegisterTest(
"StreamTcpReassembleInlineTest10 -- inline APP ra 10",
3819 StreamTcpReassembleInlineTest10);
3821 UtRegisterTest(
"StreamTcpReassembleInsertTest01 -- insert with overlap",
3822 StreamTcpReassembleInsertTest01);
3823 UtRegisterTest(
"StreamTcpReassembleInsertTest02 -- insert with overlap",
3824 StreamTcpReassembleInsertTest02);
3825 UtRegisterTest(
"StreamTcpReassembleInsertTest03 -- insert with overlap",
3826 StreamTcpReassembleInsertTest03);
3831 StreamTcpReassembleRawRegisterTests();