75 static SCMutex segment_pool_memuse_mutex;
76 static uint64_t segment_pool_memuse = 0;
77 static uint64_t segment_pool_memcnt = 0;
78 thread_local uint64_t t_pcapcnt = UINT64_MAX;
88 static int g_tcp_session_dump_enabled = 0;
92 return g_tcp_session_dump_enabled == 1;
97 g_tcp_session_dump_enabled = 1;
115 static void StreamTcpReassembleIncrMemuse(uint64_t size)
128 static void StreamTcpReassembleDecrMemuse(uint64_t size)
133 BUG_ON(presize > UINT_MAX);
142 BUG_ON(postsize > presize);
166 if (
unlikely((g_eps_stream_reassembly_memcap != UINT64_MAX &&
167 g_eps_stream_reassembly_memcap == t_pcapcnt))) {
168 SCLogNotice(
"simulating memcap reached condition for packet %" PRIu64, t_pcapcnt);
173 if (memcapcopy == 0 ||
174 (uint64_t)((uint64_t)size +
SC_ATOMIC_GET(ra_memuse)) <= memcapcopy)
186 if (size == 0 || (uint64_t)
SC_ATOMIC_GET(ra_memuse) < size) {
210 static void *ReassembleCalloc(
size_t n,
size_t size)
221 StreamTcpReassembleIncrMemuse(n * size);
230 if (size > orig_size) {
243 if (size > orig_size) {
244 StreamTcpReassembleIncrMemuse(size - orig_size);
246 StreamTcpReassembleDecrMemuse(orig_size - size);
254 static void ReassembleFree(
void *ptr,
size_t size)
257 StreamTcpReassembleDecrMemuse(size);
261 static void *TcpSegmentPoolAlloc(
void)
285 "TcpSegmentPcapHdrStorage");
294 "packet header data within "
295 "TcpSegmentPcapHdrStorage");
302 StreamTcpReassembleIncrMemuse(memuse);
310 static int TcpSegmentPoolInit(
void *data,
void *initdata)
328 StreamTcpReassembleIncrMemuse(memuse);
338 segment_pool_memcnt++;
339 SCLogDebug(
"segment_pool_memcnt %"PRIu64
"", segment_pool_memcnt);
343 StreamTcpReassembleIncrMemuse((uint32_t)
sizeof(
TcpSegment));
348 static void TcpSegmentPoolCleanup(
void *ptr)
364 StreamTcpReassembleDecrMemuse((uint32_t)
sizeof(
TcpSegment));
369 segment_pool_memcnt--;
370 SCLogDebug(
"segment_pool_memcnt %"PRIu64
"", segment_pool_memcnt);
407 static inline uint64_t GetAbsLastAck(
const TcpStream *stream)
409 if (STREAM_LASTACK_GT_BASESEQ(stream)) {
420 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
427 uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
429 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
471 static int StreamTcpReassemblyConfig(
bool quiet)
473 uint32_t segment_prealloc = 2048;
476 uint32_t prealloc = 0;
483 segment_prealloc = prealloc;
486 SCLogConfig(
"stream.reassembly \"segment-prealloc\": %u", segment_prealloc);
489 int overlap_diff_data = 0;
490 (void)
SCConfGetBool(
"stream.reassembly.check-overlap-different-data", &overlap_diff_data);
491 if (overlap_diff_data) {
498 uint16_t max_regions = 8;
509 SCLogConfig(
"stream.reassembly \"max-regions\": %u", max_regions);
527 if (StreamTcpReassemblyConfig(quiet) < 0)
549 if (segment_pool_memuse > 0)
550 SCLogDebug(
"segment_pool_memuse %" PRIu64
" segment_pool_memcnt %" PRIu64
"",
551 segment_pool_memuse, segment_pool_memcnt);
572 TcpSegmentPoolInit, NULL,
573 TcpSegmentPoolCleanup, NULL);
575 SCLogDebug(
"pool size %d, thread segment_thread_pool_id %d",
581 SCLogDebug(
"pool size %d, thread segment_thread_pool_id %d",
587 SCLogError(
"failed to setup/expand stream segment pool. Expand stream.reassembly.memcap?");
607 static void StreamTcpReassembleExceptionPolicyStatsIncr(
653 uint32_t
seq, uint32_t size)
671 SCLogDebug(
"segment entirely before base_seq, weird: base %u, seq %u, re %u",
685 SCLogDebug(
"seq + size %u, base %u, seg_depth %"PRIu64
" limit %u", (
seq + size),
690 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
694 SCLogDebug(
"NOT STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
697 SCLogDebug(
"full depth not yet reached: %"PRIu64
" <= %"PRIu32,
698 (stream->base_seq_offset + stream->
base_seq + size),
765 SCLogDebug(
"ssn %p: both app and raw reassembly disabled, not reassembling", ssn);
769 uint16_t *urg_offset;
776 const TCPHdr *tcph = PacketGetTCP(p);
780 uint8_t urg_data = 0;
790 if ((*urg_offset) < UINT16_MAX) {
794 if ((*urg_offset) == UINT16_MAX) {
811 (*urg_offset) == UINT16_MAX &&
827 uint32_t size = StreamTcpReassembleCheckDepth(ssn, stream, seg_seq,
payload_len);
828 SCLogDebug(
"ssn %p: check depth returned %"PRIu32, ssn, size);
837 SCLogDebug(
"ssn %p: depth reached, not reassembling", ssn);
874 SCLogDebug(
"StreamTcpReassembleInsertSegment failed");
886 flag |= STREAM_START;
894 flag |= STREAM_MIDSTREAM;
901 if (&ssn->
client == stream) {
902 flag |= STREAM_TOSERVER;
904 flag |= STREAM_TOCLIENT;
907 flag |= STREAM_DEPTH;
918 static bool StreamTcpReassembleRawCheckLimit(
924 #define STREAMTCP_STREAM_FLAG_FLUSH_FLAGS \
925 ( STREAMTCP_STREAM_FLAG_DEPTH_REACHED \
926 | STREAMTCP_STREAM_FLAG_TRIGGER_RAW \
927 | STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED)
931 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_DEPTH_REACHED "
932 "is set, so not expecting any new data segments");
935 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_TRIGGER_RAW is set");
938 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED is set, "
939 "so no new segments will be considered");
943 #undef STREAMTCP_STREAM_FLAG_FLUSH_FLAGS
952 const uint64_t last_ack_abs = GetAbsLastAck(stream);
958 if (chunk_size <= diff) {
961 SCLogDebug(
"%s min chunk len not yet reached: "
962 "last_ack %" PRIu32
", ra_raw_base_seq %" PRIu32
", %" PRIu32
" < "
979 const char *dirstr = NULL;
981 if (direction == STREAM_TOSERVER) {
1005 const uint64_t right_edge =
1007 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
1008 " (use: %s). Stream right edge: %" PRIu64,
1012 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
1017 const uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
1018 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
1019 " (use: %s). Stream right edge: %" PRIu64,
1023 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
1028 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NONE", dirstr);
1033 static uint64_t GetStreamSize(
TcpStream *stream)
1038 uint64_t last_ack_abs = GetAbsLastAck(stream);
1039 uint64_t last_re = 0;
1045 const uint64_t seg_abs =
1047 if (last_re != 0 && last_re < seg_abs) {
1048 const char *gacked = NULL;
1049 if (last_ack_abs >= seg_abs) {
1050 gacked =
"fully ack'd";
1051 }
else if (last_ack_abs > last_re) {
1052 gacked =
"partly ack'd";
1054 gacked =
"not yet ack'd";
1056 SCLogDebug(
" -> gap of size %" PRIu64
", ack:%s", seg_abs - last_re, gacked);
1059 const char *acked = NULL;
1060 if (last_ack_abs >= seg_abs + (uint64_t)
TCP_SEG_LEN(seg)) {
1061 acked =
"fully ack'd";
1062 }
else if (last_ack_abs > seg_abs) {
1063 acked =
"partly ack'd";
1065 acked =
"not yet ack'd";
1068 SCLogDebug(
"%u -> seg %p seq %u abs %" PRIu64
" size %u abs %" PRIu64
" (%" PRIu64
1087 size = GetStreamSize(&ssn->
client);
1088 size += GetStreamSize(&ssn->
server);
1101 GetAbsLastAck(stream) > (cur_blk->
offset + cur_blk->
len)) {
1116 static bool GetAppBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1117 uint64_t
offset,
const bool check_for_gap)
1119 const uint8_t *mydata;
1120 uint32_t mydata_len;
1121 bool gap_ahead =
false;
1129 *data_len = mydata_len;
1148 gap_ahead = check_for_gap && GapAhead(stream, blk);
1152 SCLogDebug(
"gap, want data at offset %"PRIu64
", "
1153 "got data at %"PRIu64
". GAP of size %"PRIu64,
1160 SCLogDebug(
"get data from offset %"PRIu64
". SBB %"PRIu64
"/%u",
1163 SCLogDebug(
"data %p, data_len %u", *data, *data_len);
1165 gap_ahead = check_for_gap && GapAhead(stream, blk);
1184 const uint64_t last_ack_abs = GetAbsLastAck(stream) - (uint64_t)ackadded;
1191 if (last_ack_abs > app_progress) {
1198 "next_seq %u < last_ack %u, but no data in list",
1202 const uint64_t next_seq_abs =
1205 if (blk->
offset > next_seq_abs && blk->
offset < last_ack_abs) {
1208 "next_seq %u < last_ack %u, but ACK'd data beyond gap.",
1215 "last_ack_abs %" PRIu64
" > app_progress %" PRIu64
", "
1216 "but we have no data.",
1221 "last_ack_abs %" PRIu64
" <= app_progress %" PRIu64,
1226 static inline uint32_t AdjustToAcked(
const Packet *p,
1228 const uint64_t app_progress,
const uint32_t data_len)
1230 uint32_t adjusted = data_len;
1241 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1245 if (app_progress <= last_ack_abs && app_progress + data_len > last_ack_abs) {
1246 adjusted = (uint32_t)(last_ack_abs - app_progress);
1248 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1249 "data is considered", adjusted);
1266 SCLogDebug(
"app progress %"PRIu64, app_progress);
1268 uint64_t last_ack_abs = GetAbsLastAck(*stream);
1269 SCLogDebug(
"last_ack %u (abs %" PRIu64
"), base_seq %u", (*stream)->last_ack, last_ack_abs,
1270 (*stream)->base_seq);
1272 const uint8_t *mydata;
1273 uint32_t mydata_len;
1274 bool last_was_gap =
false;
1277 const uint8_t
flags = StreamGetAppLayerFlags(ssn, *stream, p);
1278 bool check_for_gap_ahead = ((*stream)->data_required > 0);
1280 GetAppBuffer(*stream, &mydata, &mydata_len, app_progress, check_for_gap_ahead);
1282 if (last_was_gap && mydata_len == 0) {
1285 last_was_gap =
false;
1288 mydata_len = AdjustToAcked(p, ssn, *stream, app_progress, mydata_len);
1290 if (mydata == NULL && mydata_len > 0 && CheckGap(ssn, *stream, p)) {
1291 SCLogDebug(
"sending GAP to app-layer (size: %u)", mydata_len);
1294 StreamGetAppLayerFlags(ssn, *stream, p) | STREAM_GAP, app_update_dir);
1308 if ((*stream)->data_required > 0) {
1309 if ((*stream)->data_required > mydata_len) {
1310 (*stream)->data_required -= mydata_len;
1312 (*stream)->data_required = 0;
1317 if (no_progress_update)
1319 last_was_gap =
true;
1322 }
else if (
flags & STREAM_DEPTH) {
1325 if (mydata == NULL && mydata_len > 0) {
1328 }
else if (mydata == NULL || (mydata_len == 0 && ((
flags & STREAM_EOF) == 0))) {
1341 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1342 *stream, &(*stream)->sb, mydata_len, app_progress);
1346 if (mydata_len < (*stream)->data_required) {
1349 SCLogDebug(
"GAP while expecting more data (expect %u, gap size %u)",
1350 (*stream)->data_required, mydata_len);
1351 (*stream)->app_progress_rel += mydata_len;
1352 (*stream)->data_required -= mydata_len;
1362 (*stream)->data_required = 0;
1367 mydata_len,
flags, app_update_dir);
1373 app_progress = new_app_progress;
1374 if (
flags & STREAM_DEPTH)
1402 SCLogDebug(
"stream no reassembly flag set or app-layer disabled.");
1408 GetSessionSize(ssn, p);
1419 uint8_t stream_flags = StreamGetAppLayerFlags(ssn, stream, p);
1421 tv, ra_ctx, p, p->
flow, ssn, &stream, NULL, 0, stream_flags, app_update_dir);
1429 return ReassembleUpdateAppLayer(
tv, ra_ctx, ssn, &stream, p, app_update_dir);
1435 static int GetRawBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1438 const uint8_t *mydata;
1439 uint32_t mydata_len;
1444 uint64_t roffset =
offset;
1452 *data_len = mydata_len;
1453 *data_offset = roffset;
1455 SCLogDebug(
"multiblob %s. Want offset %"PRIu64,
1456 *iter == NULL ?
"starting" :
"continuing",
offset);
1457 if (*iter == NULL) {
1462 if (*iter == NULL) {
1469 SCLogDebug(
"getting multiple blobs. Iter %p, %"PRIu64
"/%u", *iter, (*iter)->offset, (*iter)->len);
1474 if ((*iter)->offset <
offset) {
1475 uint64_t delta =
offset - (*iter)->offset;
1476 if (delta < mydata_len) {
1477 *data = mydata + delta;
1478 *data_len = (uint32_t)(mydata_len - delta);
1489 *data_len = mydata_len;
1490 *data_offset = (*iter)->offset;
1493 *iter = SBB_RB_NEXT(*iter);
1524 const uint64_t segs_re_abs =
1529 if (StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 1) {
1567 }
else if (progress == 0) {
1572 target = GetAbsLastAck(stream);
1582 SCLogDebug(
"PcapPacketCntGet(p) %" PRIu64
": progress %" PRIu64
" app %" PRIu64
1583 " raw %" PRIu64
" tcp win %" PRIu32,
1592 SCLogDebug(
"ssn %p: STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED set, "
1593 "now that detect ran also set STREAMTCP_STREAM_FLAG_DISABLE_RAW", ssn);
1640 "packet payload len %u, so chunk_size adjusted to %u", p->
payload_len, chunk_size);
1643 const TCPHdr *tcph = PacketGetTCP(p);
1648 uint64_t packet_rightedge_abs = packet_leftedge_abs + p->
payload_len;
1649 SCLogDebug(
"packet_leftedge_abs %"PRIu64
", rightedge %"PRIu64,
1650 packet_leftedge_abs, packet_rightedge_abs);
1652 const uint8_t *mydata = NULL;
1653 uint32_t mydata_len = 0;
1654 uint64_t mydata_offset = 0;
1656 bool return_progress =
false;
1661 return_progress =
true;
1664 SCLogDebug(
"finding our SBB from offset %"PRIu64, packet_leftedge_abs);
1671 mydata_offset = sbb->
offset;
1676 uint64_t mydata_rightedge_abs = mydata_offset + mydata_len;
1677 if ((mydata == NULL || mydata_len == 0) ||
1678 (mydata_offset >= packet_rightedge_abs ||
1679 packet_leftedge_abs >= mydata_rightedge_abs) ||
1680 (packet_leftedge_abs < mydata_offset ||
1681 packet_rightedge_abs > mydata_rightedge_abs))
1686 mydata_offset = packet_leftedge_abs;
1690 SCLogDebug(
"chunk_size %u mydata_len %u", chunk_size, mydata_len);
1691 if (mydata_len > chunk_size) {
1692 uint32_t excess = mydata_len - chunk_size;
1693 SCLogDebug(
"chunk_size %u mydata_len %u excess %u", chunk_size, mydata_len, excess);
1695 if (mydata_rightedge_abs == packet_rightedge_abs) {
1697 mydata_len -= excess;
1698 mydata_offset += excess;
1699 SCLogDebug(
"cutting front of the buffer with %u", excess);
1700 }
else if (mydata_offset == packet_leftedge_abs) {
1701 mydata_len -= excess;
1702 SCLogDebug(
"cutting tail of the buffer with %u", excess);
1705 uint32_t abs_before = (uint32_t)(packet_leftedge_abs - mydata_offset);
1707 uint32_t abs_after = (uint32_t)(mydata_rightedge_abs - packet_rightedge_abs);
1708 uint32_t before = abs_before;
1709 uint32_t after = abs_after;
1710 SCLogDebug(
"before %u after %u", before, after);
1715 if (before >= (chunk_size - p->
payload_len) / 2) {
1717 before = after = (chunk_size - p->
payload_len) / 2;
1726 if (before >= (chunk_size - p->
payload_len) / 2) {
1735 uint32_t skip = abs_before - before;
1737 uint32_t cut = abs_after - after;
1742 mydata_len -= (skip + cut);
1743 mydata_offset += skip;
1749 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1752 if (return_progress) {
1753 *progress_out = (mydata_offset + mydata_len);
1760 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1761 SCLogDebug(
"last_ack_abs %"PRIu64, last_ack_abs);
1764 if (mydata_offset > last_ack_abs) {
1766 *progress_out = last_ack_abs;
1768 *progress_out = (mydata_offset + mydata_len);
1807 const uint64_t re, uint64_t *progress_out,
bool eof)
1813 uint64_t progress = progress_in;
1818 const uint8_t *mydata;
1819 uint32_t mydata_len;
1820 uint64_t mydata_offset = 0;
1822 GetRawBuffer(stream, &mydata, &mydata_len, &iter, progress, &mydata_offset);
1823 if (mydata_len == 0) {
1829 SCLogDebug(
"raw progress %"PRIu64, progress);
1830 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1831 stream, &stream->
sb, mydata_len, progress);
1836 if (re < progress) {
1841 SCLogDebug(
"re %" PRIu64
", raw_progress %" PRIu64, re, progress);
1842 SCLogDebug(
"raw_progress + mydata_len %" PRIu64
", re %" PRIu64, progress + mydata_len,
1846 if (progress + mydata_len > re) {
1847 #ifdef DEBUG_VALIDATION
1848 uint32_t check = mydata_len;
1850 mydata_len = (uint32_t)(re - progress);
1852 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1853 "data is considered", mydata_len);
1856 if (mydata_len == 0)
1859 SCLogDebug(
"data %p len %u", mydata, mydata_len);
1862 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1865 if (mydata_offset == progress) {
1866 SCLogDebug(
"progress %"PRIu64
" increasing with data len %u to %"PRIu64,
1867 progress, mydata_len, progress_in + mydata_len);
1869 progress += mydata_len;
1870 SCLogDebug(
"raw progress now %"PRIu64, progress);
1873 }
else if (mydata_offset > progress && mydata_offset < re) {
1874 SCLogDebug(
"GAP: data is missing from %"PRIu64
" (%u bytes), setting to first data we have: %"PRIu64, progress, (uint32_t)(mydata_offset - progress), mydata_offset);
1876 progress = mydata_offset;
1877 SCLogDebug(
"raw progress now %"PRIu64, progress);
1880 SCLogDebug(
"not increasing progress, data gap => mydata_offset "
1881 "%"PRIu64
" != progress %"PRIu64, mydata_offset, progress);
1884 if (iter == NULL || r == 1)
1888 *progress_out = progress;
1893 void *cb_data,
const uint64_t
offset,
const bool eof)
1897 SCLogDebug(
"app_progress %" PRIu64, app_progress);
1899 uint64_t unused = 0;
1900 return StreamReassembleRawDo(
1901 ssn, stream, Callback, cb_data,
offset, app_progress, &unused, eof);
1906 uint64_t *progress_out,
bool respect_inspect_depth)
1910 return StreamReassembleRawInline(ssn, p, Callback, cb_data, progress_out);
1921 StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 0)
1933 SCLogDebug(
"respect_inspect_depth %s STREAMTCP_STREAM_FLAG_TRIGGER_RAW %s "
1934 "stream->min_inspect_depth %u",
1935 respect_inspect_depth ?
"true" :
"false",
1952 SCLogDebug(
"applied min inspect depth due to STREAMTCP_STREAM_FLAG_TRIGGER_RAW: progress "
1962 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1963 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1965 return StreamReassembleRawDo(ssn, stream, Callback, cb_data, progress, last_ack_abs,
1971 uint64_t *progress_out,
const bool eof)
1977 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1978 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1980 return StreamReassembleRawDo(
1981 ssn, stream, Callback, cb_data, progress_in, last_ack_abs, progress_out, eof);
1989 static int StreamTcpReassembleHandleSegmentUpdateACK (
ThreadVars *
tv,
2006 const TCPHdr *tcph = PacketGetTCP(p);
2008 SCLogDebug(
"ssn %p, stream %p, p %p, p->payload_len %"PRIu16
"",
2038 if (stream == &ssn->
client) {
2039 opposing_stream = &ssn->
server;
2041 opposing_stream = &ssn->
client;
2046 if (StreamTcpReassembleHandleSegmentUpdateACK(
tv, ra_ctx, ssn, opposing_stream, p) != 0) {
2047 SCLogDebug(
"StreamTcpReassembleHandleSegmentUpdateACK error");
2055 if (reversed_before_ack_handling != reversed_after_ack_handling) {
2057 stream = opposing_stream;
2063 SCLogDebug(
"calling StreamTcpReassembleHandleSegmentHandleData");
2066 SCLogDebug(
"StreamTcpReassembleHandleSegmentHandleData error");
2070 StreamTcpReassembleExceptionPolicyStatsIncr(
2078 SCLogDebug(
"ssn %p / stream %p: not calling StreamTcpReassembleHandleSegmentHandleData:"
2079 " p->payload_len %u, STREAMTCP_STREAM_FLAG_NOREASSEMBLY %s",
2089 if ((stream->
flags &
2093 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED, truncate applayer");
2095 SCLogDebug(
"override: direction now UPDATE_DIR_PACKET so we "
2096 "can trigger Truncate");
2104 SCLogDebug(
"inline (%s) or PKT_PSEUDO_STREAM_END (%s)",
2163 if (direction == STREAM_TOSERVER) {
2169 SCLogDebug(
"flagged ssn %p for immediate raw reassembly", ssn);
2180 if (direction == STREAM_TOSERVER) {
2182 SCLogDebug(
"ssn %p: set client.min_inspect_depth to %u", ssn, depth);
2185 SCLogDebug(
"ssn %p: set server.min_inspect_depth to %u", ssn, depth);
2193 #define SET_ISN(stream, setseq) \
2194 (stream)->isn = (setseq); \
2195 (stream)->base_seq = (setseq) + 1
2213 for (; i <
len; i++)
2227 data, data_len) == 0)
2236 #define MISSED_START(isn) \
2237 TcpReassemblyThreadCtx *ra_ctx = NULL; \
2240 memset(&tv, 0, sizeof(tv)); \
2242 StreamTcpUTInit(&ra_ctx); \
2244 StreamTcpUTSetupSession(&ssn); \
2245 StreamTcpUTSetupStream(&ssn.server, (isn)); \
2246 StreamTcpUTSetupStream(&ssn.client, (isn)); \
2248 TcpStream *stream = &ssn.client;
2250 #define MISSED_END \
2251 StreamTcpUTClearSession(&ssn); \
2252 StreamTcpUTDeinit(ra_ctx); \
2255 #define MISSED_STEP(seq, seg, seglen, buf, buflen) \
2256 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen)); \
2257 FAIL_IF(!(VALIDATE(stream, (uint8_t *)(buf), (buflen))));
2259 #define MISSED_ADD_PAYLOAD(seq, seg, seglen) \
2260 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen));
2267 uint64_t last_re = 0;
2271 if (sbb->
offset != last_re) {
2291 uint64_t last_re = 0;
2295 if (sbb->
offset != last_re) {
2301 const uint8_t *buf = NULL;
2302 uint32_t buf_len = 0;
2305 if (
len == buf_len) {
2306 return (memcmp(data, buf,
len) == 0);
2323 static int StreamTcpReassembleTest25 (
void)
2344 static int StreamTcpReassembleTest26 (
void)
2363 static int StreamTcpReassembleTest27 (
void)
2380 static int StreamTcpReassembleTest28 (
void)
2404 static int StreamTcpReassembleTest29 (
void)
2416 static int StreamTcpReassembleTest33(
void)
2425 uint8_t packet[1460] =
"";
2430 memset(&f, 0,
sizeof (
Flow));
2431 memset(&tcph, 0,
sizeof (
TCPHdr));
2436 f.
proto = IPPROTO_TCP;
2439 p->
proto = IPPROTO_TCP;
2478 static int StreamTcpReassembleTest34(
void)
2487 uint8_t packet[1460] =
"";
2491 memset(&f, 0,
sizeof (
Flow));
2492 memset(&tcph, 0,
sizeof (
TCPHdr));
2497 f.
proto = IPPROTO_TCP;
2500 p->
proto = IPPROTO_TCP;
2509 tcph.
th_seq = htonl(857961230);
2515 tcph.
th_seq = htonl(857961534);
2521 tcph.
th_seq = htonl(857963582);
2527 tcph.
th_seq = htonl(857960946);
2548 static int StreamTcpReassembleTest39 (
void)
2558 memset (&f, 0,
sizeof(
Flow));
2560 memset(&stt, 0,
sizeof (stt));
2561 memset(&tcph, 0,
sizeof (
TCPHdr));
2565 f.
proto = IPPROTO_TCP;
2572 tcph.
th_win = htons(5480);
2640 uint8_t request1[] = { 0x47, 0x45, };
2687 uint8_t request2[] = {
2688 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
2689 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
2690 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
2691 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
2692 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
2693 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
2694 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
2695 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
2696 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
2697 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
2698 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
2723 uint8_t response[] = {
2724 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
2725 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
2726 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
2727 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
2728 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
2729 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
2730 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
2731 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
2732 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
2733 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
2734 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
2735 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
2736 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
2737 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
2738 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
2739 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
2740 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
2741 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
2742 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
2743 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
2744 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
2745 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
2746 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
2747 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
2748 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
2749 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
2750 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
2751 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
2752 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
2753 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
2754 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
2755 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
2756 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
2757 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
2758 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
2759 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
2760 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
2761 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
2762 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
2763 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
2764 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
2790 tcph.
th_ack = htonl(328);
2816 tcph.
th_seq = htonl(328);
2840 tcph.
th_ack = htonl(328);
2865 tcph.
th_seq = htonl(328);
2890 tcph.
th_ack = htonl(328);
2916 tcph.
th_seq = htonl(328);
2941 tcph.
th_ack = htonl(328);
2968 tcph.
th_ack = htonl(175);
2969 tcph.
th_seq = htonl(328);
2996 tcph.
th_ack = htonl(175);
2997 tcph.
th_seq = htonl(328);
3013 tcph.
th_ack = htonl(328);
3014 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);
3195 static int StreamTcpReassembleTest45 (
void)
3200 memset(&
tv, 0,
sizeof(
tv));
3201 uint8_t payload[100] = {0};
3202 uint16_t payload_size = 100;
3233 static int StreamTcpReassembleTest46 (
void)
3238 memset(&
tv, 0,
sizeof(
tv));
3239 uint8_t payload[100] = {0};
3240 uint16_t payload_size = 100;
3271 static int StreamTcpReassembleTest47 (
void)
3279 memset(&tcph, 0,
sizeof (
TCPHdr));
3286 uint8_t httpbuf1[] =
"GET /EVILSUFF HTTP/1.1\r\n\r\n";
3287 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3295 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3298 f->
proto = IPPROTO_TCP;
3301 tcph.
th_win = htons(5480);
3308 tcph.
th_ack = htonl(572799782UL);
3320 tcph.
th_seq = htonl(572799782UL);
3339 static int StreamTcpReassembleInlineTest01(
void)
3346 memset(&
tv, 0x00,
sizeof(
tv));
3354 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3374 static int StreamTcpReassembleInlineTest02(
void)
3381 memset(&
tv, 0x00,
sizeof(
tv));
3389 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3412 static int StreamTcpReassembleInlineTest03(
void)
3419 memset(&
tv, 0x00,
sizeof(
tv));
3429 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3455 static int StreamTcpReassembleInlineTest04(
void)
3462 memset(&
tv, 0x00,
sizeof(
tv));
3472 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3499 static int StreamTcpReassembleInlineTest08(
void)
3503 memset(&
tv, 0x00,
sizeof(
tv));
3515 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3547 static int StreamTcpReassembleInlineTest09(
void)
3554 memset(&
tv, 0x00,
sizeof(
tv));
3564 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3596 static int StreamTcpReassembleInlineTest10(
void)
3603 memset(&
tv, 0x00,
sizeof(
tv));
3617 f->
proto = IPPROTO_TCP;
3619 uint8_t stream_payload1[] =
"GE";
3620 uint8_t stream_payload2[] =
"T /";
3621 uint8_t stream_payload3[] =
"HTTP/1.0\r\n\r\n";
3623 p =
UTHBuildPacketReal(stream_payload3, 12, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
3657 static int StreamTcpReassembleInsertTest01(
void)
3664 memset(&
tv, 0x00,
sizeof(
tv));
3672 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3694 static int StreamTcpReassembleInsertTest02(
void)
3700 memset(&
tv, 0x00,
sizeof(
tv));
3707 for (i = 2; i < 10; i++) {
3728 static int StreamTcpReassembleInsertTest03(
void)
3734 memset(&
tv, 0x00,
sizeof(
tv));
3743 for (i = 2; i < 10; i++) {
3770 UtRegisterTest(
"StreamTcpReassembleTest25 -- Gap at Start Reassembly Test",
3771 StreamTcpReassembleTest25);
3772 UtRegisterTest(
"StreamTcpReassembleTest26 -- Gap at middle Reassembly Test",
3773 StreamTcpReassembleTest26);
3775 "StreamTcpReassembleTest27 -- Gap at after Reassembly Test", StreamTcpReassembleTest27);
3776 UtRegisterTest(
"StreamTcpReassembleTest28 -- Gap at Start IDS missed packet Reassembly Test",
3777 StreamTcpReassembleTest28);
3778 UtRegisterTest(
"StreamTcpReassembleTest29 -- Gap at Middle IDS missed packet Reassembly Test",
3779 StreamTcpReassembleTest29);
3781 StreamTcpReassembleTest33);
3783 StreamTcpReassembleTest34);
3785 StreamTcpReassembleTest39);
3787 StreamTcpReassembleTest40);
3789 StreamTcpReassembleTest44);
3791 StreamTcpReassembleTest45);
3793 StreamTcpReassembleTest46);
3794 UtRegisterTest(
"StreamTcpReassembleTest47 -- TCP Sequence Wraparound Test",
3795 StreamTcpReassembleTest47);
3797 UtRegisterTest(
"StreamTcpReassembleInlineTest01 -- inline RAW ra",
3798 StreamTcpReassembleInlineTest01);
3799 UtRegisterTest(
"StreamTcpReassembleInlineTest02 -- inline RAW ra 2",
3800 StreamTcpReassembleInlineTest02);
3801 UtRegisterTest(
"StreamTcpReassembleInlineTest03 -- inline RAW ra 3",
3802 StreamTcpReassembleInlineTest03);
3803 UtRegisterTest(
"StreamTcpReassembleInlineTest04 -- inline RAW ra 4",
3804 StreamTcpReassembleInlineTest04);
3805 UtRegisterTest(
"StreamTcpReassembleInlineTest08 -- inline RAW ra 8 cleanup",
3806 StreamTcpReassembleInlineTest08);
3807 UtRegisterTest(
"StreamTcpReassembleInlineTest09 -- inline RAW ra 9 GAP cleanup",
3808 StreamTcpReassembleInlineTest09);
3810 UtRegisterTest(
"StreamTcpReassembleInlineTest10 -- inline APP ra 10",
3811 StreamTcpReassembleInlineTest10);
3813 UtRegisterTest(
"StreamTcpReassembleInsertTest01 -- insert with overlap",
3814 StreamTcpReassembleInsertTest01);
3815 UtRegisterTest(
"StreamTcpReassembleInsertTest02 -- insert with overlap",
3816 StreamTcpReassembleInsertTest02);
3817 UtRegisterTest(
"StreamTcpReassembleInsertTest03 -- insert with overlap",
3818 StreamTcpReassembleInsertTest03);
3823 StreamTcpReassembleRawRegisterTests();