74 static SCMutex segment_pool_memuse_mutex;
75 static uint64_t segment_pool_memuse = 0;
76 static uint64_t segment_pool_memcnt = 0;
79 thread_local uint64_t t_pcapcnt = UINT64_MAX;
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))) {
169 SCLogNotice(
"simulating memcap reached condition for packet %" PRIu64, 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)
284 "TcpSegmentPcapHdrStorage");
293 "packet header data within "
294 "TcpSegmentPcapHdrStorage");
300 StreamTcpReassembleIncrMemuse(memuse);
308 static int TcpSegmentPoolInit(
void *data)
326 StreamTcpReassembleIncrMemuse(memuse);
336 segment_pool_memcnt++;
337 SCLogDebug(
"segment_pool_memcnt %"PRIu64
"", segment_pool_memcnt);
341 StreamTcpReassembleIncrMemuse((uint32_t)
sizeof(
TcpSegment));
346 static void TcpSegmentPoolCleanup(
void *ptr)
362 StreamTcpReassembleDecrMemuse((uint32_t)
sizeof(
TcpSegment));
367 segment_pool_memcnt--;
368 SCLogDebug(
"segment_pool_memcnt %"PRIu64
"", segment_pool_memcnt);
405 static inline uint64_t GetAbsLastAck(
const TcpStream *stream)
407 if (STREAM_LASTACK_GT_BASESEQ(stream)) {
418 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
425 uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
427 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
454 const uint16_t eof_flags = APP_LAYER_PARSER_EOF_TS | APP_LAYER_PARSER_EOF_TC;
479 static int StreamTcpReassemblyConfig(
bool quiet)
481 uint32_t segment_prealloc = 2048;
484 uint32_t prealloc = 0;
491 segment_prealloc = prealloc;
494 SCLogConfig(
"stream.reassembly \"segment-prealloc\": %u", segment_prealloc);
497 int overlap_diff_data = 0;
498 (void)
SCConfGetBool(
"stream.reassembly.check-overlap-different-data", &overlap_diff_data);
499 if (overlap_diff_data) {
506 uint16_t max_regions = 8;
517 SCLogConfig(
"stream.reassembly \"max-regions\": %u", max_regions);
535 if (StreamTcpReassemblyConfig(quiet) < 0)
557 if (segment_pool_memuse > 0)
558 SCLogDebug(
"segment_pool_memuse %" PRIu64
" segment_pool_memcnt %" PRIu64
"",
559 segment_pool_memuse, segment_pool_memcnt);
578 TcpSegmentPoolInit, TcpSegmentPoolCleanup);
580 SCLogDebug(
"pool size %d, thread segment_thread_pool_id %d",
586 SCLogDebug(
"pool size %d, thread segment_thread_pool_id %d",
592 SCLogError(
"failed to setup/expand stream segment pool. Expand stream.reassembly.memcap?");
612 static void StreamTcpReassembleExceptionPolicyStatsIncr(
658 uint32_t
seq, uint32_t size)
676 SCLogDebug(
"segment entirely before base_seq, weird: base %u, seq %u, re %u",
690 SCLogDebug(
"seq + size %u, base %u, seg_depth %"PRIu64
" limit %u", (
seq + size),
695 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
699 SCLogDebug(
"NOT STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
702 SCLogDebug(
"full depth not yet reached: %"PRIu64
" <= %"PRIu32,
703 (stream->base_seq_offset + stream->
base_seq + size),
770 SCLogDebug(
"ssn %p: both app and raw reassembly disabled, not reassembling",
ssn);
774 uint16_t *urg_offset;
781 const TCPHdr *tcph = PacketGetTCP(
p);
785 uint8_t urg_data = 0;
795 if ((*urg_offset) < UINT16_MAX) {
799 if ((*urg_offset) == UINT16_MAX) {
816 (*urg_offset) == UINT16_MAX &&
832 uint32_t size = StreamTcpReassembleCheckDepth(
ssn, stream, seg_seq,
payload_len);
833 SCLogDebug(
"ssn %p: check depth returned %"PRIu32,
ssn, size);
879 SCLogDebug(
"StreamTcpReassembleInsertSegment failed");
891 flag |= STREAM_START;
899 flag |= STREAM_MIDSTREAM;
907 flag |= STREAM_TOSERVER;
909 flag |= STREAM_TOCLIENT;
912 flag |= STREAM_DEPTH;
923 static bool StreamTcpReassembleRawCheckLimit(
929 #define STREAMTCP_STREAM_FLAG_FLUSH_FLAGS \
930 ( STREAMTCP_STREAM_FLAG_DEPTH_REACHED \
931 | STREAMTCP_STREAM_FLAG_TRIGGER_RAW \
932 | STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED)
936 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_DEPTH_REACHED "
937 "is set, so not expecting any new data segments");
940 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_TRIGGER_RAW is set");
943 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED is set, "
944 "so no new segments will be considered");
948 #undef STREAMTCP_STREAM_FLAG_FLUSH_FLAGS
957 const uint64_t last_ack_abs = GetAbsLastAck(stream);
963 if (chunk_size <= diff) {
966 SCLogDebug(
"%s min chunk len not yet reached: "
967 "last_ack %" PRIu32
", ra_raw_base_seq %" PRIu32
", %" PRIu32
" < "
984 const char *dirstr = NULL;
986 if (direction == STREAM_TOSERVER) {
1010 const uint64_t right_edge =
1012 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
1013 " (use: %s). Stream right edge: %" PRIu64,
1017 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
1022 const uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
1023 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
1024 " (use: %s). Stream right edge: %" PRIu64,
1028 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
1033 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NONE", dirstr);
1038 static uint64_t GetStreamSize(
TcpStream *stream)
1043 uint64_t last_ack_abs = GetAbsLastAck(stream);
1044 uint64_t last_re = 0;
1050 const uint64_t seg_abs =
1052 if (last_re != 0 && last_re < seg_abs) {
1053 const char *gacked = NULL;
1054 if (last_ack_abs >= seg_abs) {
1055 gacked =
"fully ack'd";
1056 }
else if (last_ack_abs > last_re) {
1057 gacked =
"partly ack'd";
1059 gacked =
"not yet ack'd";
1061 SCLogDebug(
" -> gap of size %" PRIu64
", ack:%s", seg_abs - last_re, gacked);
1064 const char *acked = NULL;
1065 if (last_ack_abs >= seg_abs + (uint64_t)
TCP_SEG_LEN(seg)) {
1066 acked =
"fully ack'd";
1067 }
else if (last_ack_abs > seg_abs) {
1068 acked =
"partly ack'd";
1070 acked =
"not yet ack'd";
1073 SCLogDebug(
"%u -> seg %p seq %u abs %" PRIu64
" size %u abs %" PRIu64
" (%" PRIu64
1106 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);
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
"",
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)",
2170 if (direction == STREAM_TOSERVER) {
2176 SCLogDebug(
"flagged ssn %p for immediate raw reassembly",
ssn);
2187 if (direction == STREAM_TOSERVER) {
2189 SCLogDebug(
"ssn %p: set client.min_inspect_depth to %u",
ssn, depth);
2192 SCLogDebug(
"ssn %p: set server.min_inspect_depth to %u",
ssn, depth);
2200 #define SET_ISN(stream, setseq) \
2201 (stream)->isn = (setseq); \
2202 (stream)->base_seq = (setseq) + 1
2220 for (; i <
len; i++)
2234 data, data_len) == 0)
2243 #define MISSED_START(isn) \
2244 TcpReassemblyThreadCtx *ra_ctx = NULL; \
2247 memset(&tv, 0, sizeof(tv)); \
2249 StreamTcpUTInit(&ra_ctx); \
2251 StreamTcpUTSetupSession(&ssn); \
2252 StreamTcpUTSetupStream(&ssn.server, (isn)); \
2253 StreamTcpUTSetupStream(&ssn.client, (isn)); \
2255 TcpStream *stream = &ssn.client;
2257 #define MISSED_END \
2258 StreamTcpUTClearSession(&ssn); \
2259 StreamTcpUTDeinit(ra_ctx); \
2262 #define MISSED_STEP(seq, seg, seglen, buf, buflen) \
2263 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen)); \
2264 FAIL_IF(!(VALIDATE(stream, (uint8_t *)(buf), (buflen))));
2266 #define MISSED_ADD_PAYLOAD(seq, seg, seglen) \
2267 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen));
2274 uint64_t last_re = 0;
2278 if (sbb->
offset != last_re) {
2298 uint64_t last_re = 0;
2302 if (sbb->
offset != last_re) {
2308 const uint8_t *buf = NULL;
2309 uint32_t buf_len = 0;
2312 if (
len == buf_len) {
2313 return (memcmp(data, buf,
len) == 0);
2330 static int StreamTcpReassembleTest25 (
void)
2351 static int StreamTcpReassembleTest26 (
void)
2370 static int StreamTcpReassembleTest27 (
void)
2387 static int StreamTcpReassembleTest28 (
void)
2411 static int StreamTcpReassembleTest29 (
void)
2423 static int StreamTcpReassembleTest33(
void)
2432 uint8_t packet[1460] =
"";
2437 memset(&
f, 0,
sizeof (
Flow));
2438 memset(&tcph, 0,
sizeof (
TCPHdr));
2485 static int StreamTcpReassembleTest34(
void)
2494 uint8_t packet[1460] =
"";
2498 memset(&
f, 0,
sizeof (
Flow));
2499 memset(&tcph, 0,
sizeof (
TCPHdr));
2516 tcph.
th_seq = htonl(857961230);
2522 tcph.
th_seq = htonl(857961534);
2528 tcph.
th_seq = htonl(857963582);
2534 tcph.
th_seq = htonl(857960946);
2555 static int StreamTcpReassembleTest39 (
void)
2565 memset (&
f, 0,
sizeof(
Flow));
2567 memset(&stt, 0,
sizeof (stt));
2568 memset(&tcph, 0,
sizeof (
TCPHdr));
2579 tcph.
th_win = htons(5480);
2647 uint8_t request1[] = { 0x47, 0x45, };
2694 uint8_t request2[] = {
2695 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
2696 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
2697 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
2698 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
2699 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
2700 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
2701 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
2702 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
2703 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
2704 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
2705 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
2730 uint8_t response[] = {
2731 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
2732 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
2733 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
2734 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
2735 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
2736 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
2737 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
2738 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
2739 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
2740 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
2741 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
2742 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
2743 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
2744 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
2745 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
2746 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
2747 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
2748 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
2749 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
2750 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
2751 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
2752 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
2753 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
2754 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
2755 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
2756 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
2757 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
2758 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
2759 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
2760 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
2761 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
2762 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
2763 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
2764 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
2765 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
2766 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
2767 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
2768 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
2769 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
2770 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
2771 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
2797 tcph.
th_ack = htonl(328);
2823 tcph.
th_seq = htonl(328);
2847 tcph.
th_ack = htonl(328);
2872 tcph.
th_seq = htonl(328);
2897 tcph.
th_ack = htonl(328);
2923 tcph.
th_seq = htonl(328);
2948 tcph.
th_ack = htonl(328);
2975 tcph.
th_ack = htonl(175);
2976 tcph.
th_seq = htonl(328);
3003 tcph.
th_ack = htonl(175);
3004 tcph.
th_seq = htonl(328);
3020 tcph.
th_ack = htonl(328);
3021 tcph.
th_seq = htonl(175);
3042 static int StreamTcpReassembleTest40 (
void)
3049 memset(&tcph, 0,
sizeof (
TCPHdr));
3059 uint8_t httpbuf1[] =
"P";
3060 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3061 uint8_t httpbuf3[] =
"O";
3062 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
3063 uint8_t httpbuf4[] =
"S";
3064 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
3065 uint8_t httpbuf5[] =
"T \r\n";
3066 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
3068 uint8_t httpbuf2[] =
"HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
3069 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3082 tcph.
th_win = htons(5480);
3134 tcph.
th_ack = htonl(100);
3143 tcph.
th_seq = htonl(100);
3154 tcph.
th_ack = htonl(145);
3163 tcph.
th_seq = htonl(145);
3180 static int StreamTcpReassembleTest44(
void)
3184 StreamTcpReassembleIncrMemuse(500);
3186 StreamTcpReassembleDecrMemuse(500);
3202 static int StreamTcpReassembleTest45 (
void)
3207 memset(&
tv, 0,
sizeof(
tv));
3208 uint8_t payload[100] = {0};
3209 uint16_t payload_size = 100;
3240 static int StreamTcpReassembleTest46 (
void)
3245 memset(&
tv, 0,
sizeof(
tv));
3246 uint8_t payload[100] = {0};
3247 uint16_t payload_size = 100;
3278 static int StreamTcpReassembleTest47 (
void)
3286 memset(&tcph, 0,
sizeof (
TCPHdr));
3293 uint8_t httpbuf1[] =
"GET /EVILSUFF HTTP/1.1\r\n\r\n";
3294 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3308 tcph.
th_win = htons(5480);
3315 tcph.
th_ack = htonl(572799782UL);
3327 tcph.
th_seq = htonl(572799782UL);
3346 static int StreamTcpReassembleInlineTest01(
void)
3353 memset(&
tv, 0x00,
sizeof(
tv));
3361 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3381 static int StreamTcpReassembleInlineTest02(
void)
3388 memset(&
tv, 0x00,
sizeof(
tv));
3396 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3419 static int StreamTcpReassembleInlineTest03(
void)
3426 memset(&
tv, 0x00,
sizeof(
tv));
3436 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3462 static int StreamTcpReassembleInlineTest04(
void)
3469 memset(&
tv, 0x00,
sizeof(
tv));
3479 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3506 static int StreamTcpReassembleInlineTest08(
void)
3510 memset(&
tv, 0x00,
sizeof(
tv));
3522 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3554 static int StreamTcpReassembleInlineTest09(
void)
3561 memset(&
tv, 0x00,
sizeof(
tv));
3571 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3603 static int StreamTcpReassembleInlineTest10(
void)
3610 memset(&
tv, 0x00,
sizeof(
tv));
3626 uint8_t stream_payload1[] =
"GE";
3627 uint8_t stream_payload2[] =
"T /";
3628 uint8_t stream_payload3[] =
"HTTP/1.0\r\n\r\n";
3664 static int StreamTcpReassembleInsertTest01(
void)
3671 memset(&
tv, 0x00,
sizeof(
tv));
3679 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3701 static int StreamTcpReassembleInsertTest02(
void)
3707 memset(&
tv, 0x00,
sizeof(
tv));
3714 for (i = 2; i < 10; i++) {
3735 static int StreamTcpReassembleInsertTest03(
void)
3741 memset(&
tv, 0x00,
sizeof(
tv));
3750 for (i = 2; i < 10; i++) {
3777 UtRegisterTest(
"StreamTcpReassembleTest25 -- Gap at Start Reassembly Test",
3778 StreamTcpReassembleTest25);
3779 UtRegisterTest(
"StreamTcpReassembleTest26 -- Gap at middle Reassembly Test",
3780 StreamTcpReassembleTest26);
3782 "StreamTcpReassembleTest27 -- Gap at after Reassembly Test", StreamTcpReassembleTest27);
3783 UtRegisterTest(
"StreamTcpReassembleTest28 -- Gap at Start IDS missed packet Reassembly Test",
3784 StreamTcpReassembleTest28);
3785 UtRegisterTest(
"StreamTcpReassembleTest29 -- Gap at Middle IDS missed packet Reassembly Test",
3786 StreamTcpReassembleTest29);
3788 StreamTcpReassembleTest33);
3790 StreamTcpReassembleTest34);
3792 StreamTcpReassembleTest39);
3794 StreamTcpReassembleTest40);
3796 StreamTcpReassembleTest44);
3798 StreamTcpReassembleTest45);
3800 StreamTcpReassembleTest46);
3801 UtRegisterTest(
"StreamTcpReassembleTest47 -- TCP Sequence Wraparound Test",
3802 StreamTcpReassembleTest47);
3804 UtRegisterTest(
"StreamTcpReassembleInlineTest01 -- inline RAW ra",
3805 StreamTcpReassembleInlineTest01);
3806 UtRegisterTest(
"StreamTcpReassembleInlineTest02 -- inline RAW ra 2",
3807 StreamTcpReassembleInlineTest02);
3808 UtRegisterTest(
"StreamTcpReassembleInlineTest03 -- inline RAW ra 3",
3809 StreamTcpReassembleInlineTest03);
3810 UtRegisterTest(
"StreamTcpReassembleInlineTest04 -- inline RAW ra 4",
3811 StreamTcpReassembleInlineTest04);
3812 UtRegisterTest(
"StreamTcpReassembleInlineTest08 -- inline RAW ra 8 cleanup",
3813 StreamTcpReassembleInlineTest08);
3814 UtRegisterTest(
"StreamTcpReassembleInlineTest09 -- inline RAW ra 9 GAP cleanup",
3815 StreamTcpReassembleInlineTest09);
3817 UtRegisterTest(
"StreamTcpReassembleInlineTest10 -- inline APP ra 10",
3818 StreamTcpReassembleInlineTest10);
3820 UtRegisterTest(
"StreamTcpReassembleInsertTest01 -- insert with overlap",
3821 StreamTcpReassembleInsertTest01);
3822 UtRegisterTest(
"StreamTcpReassembleInsertTest02 -- insert with overlap",
3823 StreamTcpReassembleInsertTest02);
3824 UtRegisterTest(
"StreamTcpReassembleInsertTest03 -- insert with overlap",
3825 StreamTcpReassembleInsertTest03);
3830 StreamTcpReassembleRawRegisterTests();