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)
285 "TcpSegmentPcapHdrStorage");
294 "packet header data within "
295 "TcpSegmentPcapHdrStorage");
301 StreamTcpReassembleIncrMemuse(memuse);
309 static int TcpSegmentPoolInit(
void *data)
327 StreamTcpReassembleIncrMemuse(memuse);
337 segment_pool_memcnt++;
338 SCLogDebug(
"segment_pool_memcnt %"PRIu64
"", segment_pool_memcnt);
342 StreamTcpReassembleIncrMemuse((uint32_t)
sizeof(
TcpSegment));
347 static void TcpSegmentPoolCleanup(
void *ptr)
363 StreamTcpReassembleDecrMemuse((uint32_t)
sizeof(
TcpSegment));
368 segment_pool_memcnt--;
369 SCLogDebug(
"segment_pool_memcnt %"PRIu64
"", segment_pool_memcnt);
406 static inline uint64_t GetAbsLastAck(
const TcpStream *stream)
408 if (STREAM_LASTACK_GT_BASESEQ(stream)) {
419 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
426 uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
428 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
455 const uint16_t eof_flags = APP_LAYER_PARSER_EOF_TS | APP_LAYER_PARSER_EOF_TC;
480 static int StreamTcpReassemblyConfig(
bool quiet)
482 uint32_t segment_prealloc = 2048;
485 uint32_t prealloc = 0;
492 segment_prealloc = prealloc;
495 SCLogConfig(
"stream.reassembly \"segment-prealloc\": %u", segment_prealloc);
498 int overlap_diff_data = 0;
499 (void)
SCConfGetBool(
"stream.reassembly.check-overlap-different-data", &overlap_diff_data);
500 if (overlap_diff_data) {
507 uint16_t max_regions = 8;
518 SCLogConfig(
"stream.reassembly \"max-regions\": %u", max_regions);
536 if (StreamTcpReassemblyConfig(quiet) < 0)
558 if (segment_pool_memuse > 0)
559 SCLogDebug(
"segment_pool_memuse %" PRIu64
" segment_pool_memcnt %" PRIu64
"",
560 segment_pool_memuse, segment_pool_memcnt);
579 TcpSegmentPoolInit, TcpSegmentPoolCleanup);
581 SCLogDebug(
"pool size %d, thread segment_thread_pool_id %d",
587 SCLogDebug(
"pool size %d, thread segment_thread_pool_id %d",
593 SCLogError(
"failed to setup/expand stream segment pool. Expand stream.reassembly.memcap?");
613 static void StreamTcpReassembleExceptionPolicyStatsIncr(
659 uint32_t
seq, uint32_t size)
677 SCLogDebug(
"segment entirely before base_seq, weird: base %u, seq %u, re %u",
691 SCLogDebug(
"seq + size %u, base %u, seg_depth %"PRIu64
" limit %u", (
seq + size),
696 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
700 SCLogDebug(
"NOT STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
703 SCLogDebug(
"full depth not yet reached: %"PRIu64
" <= %"PRIu32,
704 (stream->base_seq_offset + stream->
base_seq + size),
771 SCLogDebug(
"ssn %p: both app and raw reassembly disabled, not reassembling",
ssn);
775 uint16_t *urg_offset;
782 const TCPHdr *tcph = PacketGetTCP(
p);
786 uint8_t urg_data = 0;
796 if ((*urg_offset) < UINT16_MAX) {
800 if ((*urg_offset) == UINT16_MAX) {
817 (*urg_offset) == UINT16_MAX &&
833 uint32_t size = StreamTcpReassembleCheckDepth(
ssn, stream, seg_seq,
payload_len);
834 SCLogDebug(
"ssn %p: check depth returned %"PRIu32,
ssn, size);
880 SCLogDebug(
"StreamTcpReassembleInsertSegment failed");
892 flag |= STREAM_START;
900 flag |= STREAM_MIDSTREAM;
908 flag |= STREAM_TOSERVER;
910 flag |= STREAM_TOCLIENT;
913 flag |= STREAM_DEPTH;
924 static bool StreamTcpReassembleRawCheckLimit(
930 #define STREAMTCP_STREAM_FLAG_FLUSH_FLAGS \
931 ( STREAMTCP_STREAM_FLAG_DEPTH_REACHED \
932 | STREAMTCP_STREAM_FLAG_TRIGGER_RAW \
933 | STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED)
937 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_DEPTH_REACHED "
938 "is set, so not expecting any new data segments");
941 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_TRIGGER_RAW is set");
944 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED is set, "
945 "so no new segments will be considered");
949 #undef STREAMTCP_STREAM_FLAG_FLUSH_FLAGS
958 const uint64_t last_ack_abs = GetAbsLastAck(stream);
964 if (chunk_size <= diff) {
967 SCLogDebug(
"%s min chunk len not yet reached: "
968 "last_ack %" PRIu32
", ra_raw_base_seq %" PRIu32
", %" PRIu32
" < "
985 const char *dirstr = NULL;
987 if (direction == STREAM_TOSERVER) {
1011 const uint64_t right_edge =
1013 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
1014 " (use: %s). Stream right edge: %" PRIu64,
1018 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
1023 const uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
1024 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
1025 " (use: %s). Stream right edge: %" PRIu64,
1029 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
1034 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NONE", dirstr);
1039 static uint64_t GetStreamSize(
TcpStream *stream)
1044 uint64_t last_ack_abs = GetAbsLastAck(stream);
1045 uint64_t last_re = 0;
1051 const uint64_t seg_abs =
1053 if (last_re != 0 && last_re < seg_abs) {
1054 const char *gacked = NULL;
1055 if (last_ack_abs >= seg_abs) {
1056 gacked =
"fully ack'd";
1057 }
else if (last_ack_abs > last_re) {
1058 gacked =
"partly ack'd";
1060 gacked =
"not yet ack'd";
1062 SCLogDebug(
" -> gap of size %" PRIu64
", ack:%s", seg_abs - last_re, gacked);
1065 const char *acked = NULL;
1066 if (last_ack_abs >= seg_abs + (uint64_t)
TCP_SEG_LEN(seg)) {
1067 acked =
"fully ack'd";
1068 }
else if (last_ack_abs > seg_abs) {
1069 acked =
"partly ack'd";
1071 acked =
"not yet ack'd";
1074 SCLogDebug(
"%u -> seg %p seq %u abs %" PRIu64
" size %u abs %" PRIu64
" (%" PRIu64
1107 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.",
1224 "last_ack_abs %" PRIu64
" <= app_progress %" PRIu64,
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(
"pcap_cnt %" PRIu64
": progress %" PRIu64
" app %" PRIu64
" raw %" PRIu64
1586 " tcp win %" PRIu32,
1595 SCLogDebug(
"ssn %p: STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED set, "
1596 "now that detect ran also set STREAMTCP_STREAM_FLAG_DISABLE_RAW",
ssn);
1643 "packet payload len %u, so chunk_size adjusted to %u",
p->
payload_len, chunk_size);
1646 const TCPHdr *tcph = PacketGetTCP(
p);
1651 uint64_t packet_rightedge_abs = packet_leftedge_abs +
p->
payload_len;
1652 SCLogDebug(
"packet_leftedge_abs %"PRIu64
", rightedge %"PRIu64,
1653 packet_leftedge_abs, packet_rightedge_abs);
1655 const uint8_t *mydata = NULL;
1656 uint32_t mydata_len = 0;
1657 uint64_t mydata_offset = 0;
1659 bool return_progress =
false;
1664 return_progress =
true;
1667 SCLogDebug(
"finding our SBB from offset %"PRIu64, packet_leftedge_abs);
1674 mydata_offset = sbb->
offset;
1679 uint64_t mydata_rightedge_abs = mydata_offset + mydata_len;
1680 if ((mydata == NULL || mydata_len == 0) ||
1681 (mydata_offset >= packet_rightedge_abs ||
1682 packet_leftedge_abs >= mydata_rightedge_abs) ||
1683 (packet_leftedge_abs < mydata_offset ||
1684 packet_rightedge_abs > mydata_rightedge_abs))
1689 mydata_offset = packet_leftedge_abs;
1693 SCLogDebug(
"chunk_size %u mydata_len %u", chunk_size, mydata_len);
1694 if (mydata_len > chunk_size) {
1695 uint32_t excess = mydata_len - chunk_size;
1696 SCLogDebug(
"chunk_size %u mydata_len %u excess %u", chunk_size, mydata_len, excess);
1698 if (mydata_rightedge_abs == packet_rightedge_abs) {
1700 mydata_len -= excess;
1701 mydata_offset += excess;
1702 SCLogDebug(
"cutting front of the buffer with %u", excess);
1703 }
else if (mydata_offset == packet_leftedge_abs) {
1704 mydata_len -= excess;
1705 SCLogDebug(
"cutting tail of the buffer with %u", excess);
1708 uint32_t abs_before = (uint32_t)(packet_leftedge_abs - mydata_offset);
1710 uint32_t abs_after = (uint32_t)(mydata_rightedge_abs - packet_rightedge_abs);
1711 uint32_t before = abs_before;
1712 uint32_t after = abs_after;
1713 SCLogDebug(
"before %u after %u", before, after);
1738 uint32_t skip = abs_before - before;
1740 uint32_t cut = abs_after - after;
1745 mydata_len -= (skip + cut);
1746 mydata_offset += skip;
1752 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1755 if (return_progress) {
1756 *progress_out = (mydata_offset + mydata_len);
1763 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1764 SCLogDebug(
"last_ack_abs %"PRIu64, last_ack_abs);
1767 if (mydata_offset > last_ack_abs) {
1769 *progress_out = last_ack_abs;
1771 *progress_out = (mydata_offset + mydata_len);
1810 const uint64_t re, uint64_t *progress_out,
bool eof)
1816 uint64_t progress = progress_in;
1821 const uint8_t *mydata;
1822 uint32_t mydata_len;
1823 uint64_t mydata_offset = 0;
1825 GetRawBuffer(stream, &mydata, &mydata_len, &iter, progress, &mydata_offset);
1826 if (mydata_len == 0) {
1832 SCLogDebug(
"raw progress %"PRIu64, progress);
1833 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1834 stream, &stream->
sb, mydata_len, progress);
1839 if (re < progress) {
1844 SCLogDebug(
"re %" PRIu64
", raw_progress %" PRIu64, re, progress);
1845 SCLogDebug(
"raw_progress + mydata_len %" PRIu64
", re %" PRIu64, progress + mydata_len,
1849 if (progress + mydata_len > re) {
1850 #ifdef DEBUG_VALIDATION
1851 uint32_t check = mydata_len;
1853 mydata_len = (uint32_t)(re - progress);
1855 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1856 "data is considered", mydata_len);
1859 if (mydata_len == 0)
1862 SCLogDebug(
"data %p len %u", mydata, mydata_len);
1865 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1868 if (mydata_offset == progress) {
1869 SCLogDebug(
"progress %"PRIu64
" increasing with data len %u to %"PRIu64,
1870 progress, mydata_len, progress_in + mydata_len);
1872 progress += mydata_len;
1873 SCLogDebug(
"raw progress now %"PRIu64, progress);
1876 }
else if (mydata_offset > progress && mydata_offset < re) {
1877 SCLogDebug(
"GAP: data is missing from %"PRIu64
" (%u bytes), setting to first data we have: %"PRIu64, progress, (uint32_t)(mydata_offset - progress), mydata_offset);
1879 progress = mydata_offset;
1880 SCLogDebug(
"raw progress now %"PRIu64, progress);
1884 }
else if (mydata_offset > progress && mydata_offset == re) {
1885 SCLogDebug(
"mydata_offset %" PRIu64
", progress %" PRIu64
", re %" PRIu64,
1886 mydata_offset, progress, re);
1889 SCLogDebug(
"not increasing progress, data gap => mydata_offset "
1890 "%"PRIu64
" != progress %"PRIu64, mydata_offset, progress);
1893 if (iter == NULL || r == 1)
1897 *progress_out = progress;
1902 void *cb_data,
const uint64_t
offset,
const bool eof)
1906 SCLogDebug(
"app_progress %" PRIu64, app_progress);
1908 uint64_t unused = 0;
1909 return StreamReassembleRawDo(
1910 ssn, stream, Callback, cb_data,
offset, app_progress, &unused, eof);
1915 uint64_t *progress_out,
bool respect_inspect_depth)
1919 return StreamReassembleRawInline(
ssn,
p, Callback, cb_data, progress_out);
1930 StreamTcpReassembleRawCheckLimit(
ssn, stream,
p) == 0)
1942 SCLogDebug(
"respect_inspect_depth %s STREAMTCP_STREAM_FLAG_TRIGGER_RAW %s "
1943 "stream->min_inspect_depth %u",
1944 respect_inspect_depth ?
"true" :
"false",
1961 SCLogDebug(
"applied min inspect depth due to STREAMTCP_STREAM_FLAG_TRIGGER_RAW: progress "
1971 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1972 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1974 return StreamReassembleRawDo(
ssn, stream, Callback, cb_data, progress, last_ack_abs,
1980 uint64_t *progress_out,
const bool eof)
1986 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1987 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1989 return StreamReassembleRawDo(
1990 ssn, stream, Callback, cb_data, progress_in, last_ack_abs, progress_out, eof);
1998 static int StreamTcpReassembleHandleSegmentUpdateACK (
ThreadVars *
tv,
2015 const TCPHdr *tcph = PacketGetTCP(
p);
2017 SCLogDebug(
"ssn %p, stream %p, p %p, p->payload_len %"PRIu16
"",
2055 if (StreamTcpReassembleHandleSegmentUpdateACK(
tv, ra_ctx,
ssn, opposing_stream,
p) != 0) {
2056 SCLogDebug(
"StreamTcpReassembleHandleSegmentUpdateACK error");
2064 if (reversed_before_ack_handling != reversed_after_ack_handling) {
2066 stream = opposing_stream;
2072 SCLogDebug(
"calling StreamTcpReassembleHandleSegmentHandleData");
2075 SCLogDebug(
"StreamTcpReassembleHandleSegmentHandleData error");
2079 StreamTcpReassembleExceptionPolicyStatsIncr(
2087 SCLogDebug(
"ssn %p / stream %p: not calling StreamTcpReassembleHandleSegmentHandleData:"
2088 " p->payload_len %u, STREAMTCP_STREAM_FLAG_NOREASSEMBLY %s",
2098 if ((stream->
flags &
2102 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED, truncate applayer");
2104 SCLogDebug(
"override: direction now UPDATE_DIR_PACKET so we "
2105 "can trigger Truncate");
2113 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));
2486 static int StreamTcpReassembleTest34(
void)
2495 uint8_t packet[1460] =
"";
2499 memset(&
f, 0,
sizeof (
Flow));
2500 memset(&tcph, 0,
sizeof (
TCPHdr));
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));
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;
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;
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));
3627 uint8_t stream_payload1[] =
"GE";
3628 uint8_t stream_payload2[] =
"T /";
3629 uint8_t stream_payload3[] =
"HTTP/1.0\r\n\r\n";
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();