73 static SCMutex segment_pool_memuse_mutex;
74 static uint64_t segment_pool_memuse = 0;
75 static uint64_t segment_pool_memcnt = 0;
87 static int g_tcp_session_dump_enabled = 0;
91 return g_tcp_session_dump_enabled == 1;
96 g_tcp_session_dump_enabled = 1;
132 BUG_ON(presize > UINT_MAX);
141 BUG_ON(postsize > presize);
165 if (
unlikely((g_eps_stream_reassembly_memcap != UINT64_MAX &&
166 g_eps_stream_reassembly_memcap ==
t_pcapcnt))) {
172 if (memcapcopy == 0 ||
173 (uint64_t)((uint64_t)size +
SC_ATOMIC_GET(ra_memuse)) <= memcapcopy)
185 if (size == 0 || (uint64_t)
SC_ATOMIC_GET(ra_memuse) < size) {
209 static void *ReassembleCalloc(
size_t n,
size_t size)
229 if (size > orig_size) {
242 if (size > orig_size) {
253 static void ReassembleFree(
void *ptr,
size_t size)
260 static void *TcpSegmentPoolAlloc(
void)
284 "TcpSegmentPcapHdrStorage");
293 "packet header data within "
294 "TcpSegmentPcapHdrStorage");
309 static int TcpSegmentPoolInit(
void *data,
void *initdata)
337 segment_pool_memcnt++;
338 SCLogDebug(
"segment_pool_memcnt %"PRIu64
"", segment_pool_memcnt);
347 static void TcpSegmentPoolCleanup(
void *ptr)
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)) {
417 return GetAbsLastAck(stream);
425 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
432 uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
434 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
476 static int StreamTcpReassemblyConfig(
bool quiet)
478 uint32_t segment_prealloc = 2048;
481 uint32_t prealloc = 0;
488 segment_prealloc = prealloc;
491 SCLogConfig(
"stream.reassembly \"segment-prealloc\": %u", segment_prealloc);
494 int overlap_diff_data = 0;
495 (void)
ConfGetBool(
"stream.reassembly.check-overlap-different-data", &overlap_diff_data);
496 if (overlap_diff_data) {
503 uint16_t max_regions = 8;
514 SCLogConfig(
"stream.reassembly \"max-regions\": %u", max_regions);
532 if (StreamTcpReassemblyConfig(quiet) < 0)
554 if (segment_pool_memuse > 0)
555 SCLogDebug(
"segment_pool_memuse %" PRIu64
" segment_pool_memcnt %" PRIu64
"",
556 segment_pool_memuse, segment_pool_memcnt);
579 TcpSegmentPoolInit, NULL,
580 TcpSegmentPoolCleanup, NULL);
582 SCLogDebug(
"pool size %d, thread segment_thread_pool_id %d",
588 SCLogDebug(
"pool size %d, thread segment_thread_pool_id %d",
594 SCLogError(
"failed to setup/expand stream segment pool. Expand stream.reassembly.memcap?");
651 uint32_t
seq, uint32_t size)
669 SCLogDebug(
"segment entirely before base_seq, weird: base %u, seq %u, re %u",
683 SCLogDebug(
"seq + size %u, base %u, seg_depth %"PRIu64
" limit %u", (
seq + size),
688 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
692 SCLogDebug(
"NOT STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
695 SCLogDebug(
"full depth not yet reached: %"PRIu64
" <= %"PRIu32,
696 (stream->base_seq_offset + stream->
base_seq + size),
763 SCLogDebug(
"ssn %p: both app and raw reassembly disabled, not reassembling", ssn);
770 SCLogDebug(
"ssn %p: check depth returned %"PRIu32, ssn, size);
779 SCLogDebug(
"ssn %p: depth reached, not reassembling", ssn);
817 SCLogDebug(
"StreamTcpReassembleInsertSegment failed");
829 flag |= STREAM_START;
837 flag |= STREAM_MIDSTREAM;
844 if (&ssn->
client == stream) {
845 flag |= STREAM_TOSERVER;
847 flag |= STREAM_TOCLIENT;
850 flag |= STREAM_DEPTH;
861 static int StreamTcpReassembleRawCheckLimit(
const TcpSession *ssn,
867 #define STREAMTCP_STREAM_FLAG_FLUSH_FLAGS \
868 ( STREAMTCP_STREAM_FLAG_DEPTH_REACHED \
869 | STREAMTCP_STREAM_FLAG_TRIGGER_RAW \
870 | STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED)
874 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_DEPTH_REACHED "
875 "is set, so not expecting any new data segments");
878 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_TRIGGER_RAW is set");
881 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED is set, "
882 "so no new segments will be considered");
886 #undef STREAMTCP_STREAM_FLAG_FLUSH_FLAGS
895 const uint64_t last_ack_abs = GetAbsLastAck(stream);
901 if (chunk_size <= diff) {
904 SCLogDebug(
"%s min chunk len not yet reached: "
905 "last_ack %" PRIu32
", ra_raw_base_seq %" PRIu32
", %" PRIu32
" < "
922 const char *dirstr = NULL;
924 if (direction == STREAM_TOSERVER) {
948 const uint64_t right_edge =
950 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
951 " (use: %s). Stream right edge: %" PRIu64,
955 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
960 const uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
961 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
962 " (use: %s). Stream right edge: %" PRIu64,
966 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
971 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NONE", dirstr);
976 static uint64_t GetStreamSize(
TcpStream *stream)
981 uint64_t last_ack_abs = GetAbsLastAck(stream);
982 uint64_t last_re = 0;
988 const uint64_t seg_abs =
990 if (last_re != 0 && last_re < seg_abs) {
991 const char *gacked = NULL;
992 if (last_ack_abs >= seg_abs) {
993 gacked =
"fully ack'd";
994 }
else if (last_ack_abs > last_re) {
995 gacked =
"partly ack'd";
997 gacked =
"not yet ack'd";
999 SCLogDebug(
" -> gap of size %" PRIu64
", ack:%s", seg_abs - last_re, gacked);
1002 const char *acked = NULL;
1003 if (last_ack_abs >= seg_abs + (uint64_t)
TCP_SEG_LEN(seg)) {
1004 acked =
"fully ack'd";
1005 }
else if (last_ack_abs > seg_abs) {
1006 acked =
"partly ack'd";
1008 acked =
"not yet ack'd";
1011 SCLogDebug(
"%u -> seg %p seq %u abs %" PRIu64
" size %u abs %" PRIu64
" (%" PRIu64
1020 SCLogDebug(
"size %"PRIu64
", cnt %"PRIu32, size, cnt);
1030 size = GetStreamSize(&ssn->
client);
1031 size += GetStreamSize(&ssn->
server);
1046 for ( ; blk != NULL; blk = SBB_RB_NEXT(blk)) {
1060 GetAbsLastAck(stream) > (cur_blk->
offset + cur_blk->
len)) {
1075 static bool GetAppBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1076 uint64_t
offset,
const bool check_for_gap)
1078 const uint8_t *mydata;
1079 uint32_t mydata_len;
1080 bool gap_ahead =
false;
1088 *data_len = mydata_len;
1106 gap_ahead = check_for_gap && GapAhead(stream, blk);
1110 SCLogDebug(
"gap, want data at offset %"PRIu64
", "
1111 "got data at %"PRIu64
". GAP of size %"PRIu64,
1118 SCLogDebug(
"get data from offset %"PRIu64
". SBB %"PRIu64
"/%u",
1121 SCLogDebug(
"data %p, data_len %u", *data, *data_len);
1123 gap_ahead = check_for_gap && GapAhead(stream, blk);
1142 const uint64_t last_ack_abs = GetAbsLastAck(stream) - (uint64_t)ackadded;
1149 if (last_ack_abs > app_progress) {
1156 "next_seq %u < last_ack %u, but no data in list",
1160 const uint64_t next_seq_abs =
1163 if (blk->
offset > next_seq_abs && blk->
offset < last_ack_abs) {
1166 "next_seq %u < last_ack %u, but ACK'd data beyond gap.",
1174 "last_ack_abs %" PRIu64
" > app_progress %" PRIu64
", "
1175 "but we have no data.",
1176 p->
pcap_cnt, last_ack_abs, app_progress);
1180 "last_ack_abs %"PRIu64
" <= app_progress %"PRIu64,
1181 p->
pcap_cnt, last_ack_abs, app_progress);
1185 static inline uint32_t AdjustToAcked(
const Packet *p,
1187 const uint64_t app_progress,
const uint32_t data_len)
1189 uint32_t adjusted = data_len;
1200 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1204 if (app_progress <= last_ack_abs && app_progress + data_len > last_ack_abs) {
1205 uint32_t check = data_len;
1206 adjusted = last_ack_abs - app_progress;
1207 BUG_ON(adjusted > check);
1208 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1209 "data is considered", adjusted);
1228 SCLogDebug(
"app progress %"PRIu64, app_progress);
1230 uint64_t last_ack_abs = GetAbsLastAck(*stream);
1231 SCLogDebug(
"last_ack %u (abs %" PRIu64
"), base_seq %u", (*stream)->last_ack, last_ack_abs,
1232 (*stream)->base_seq);
1234 const uint8_t *mydata;
1235 uint32_t mydata_len;
1236 bool last_was_gap =
false;
1239 const uint8_t
flags = StreamGetAppLayerFlags(ssn, *stream, p);
1240 bool check_for_gap_ahead = ((*stream)->data_required > 0);
1242 GetAppBuffer(*stream, &mydata, &mydata_len, app_progress, check_for_gap_ahead);
1244 if (last_was_gap && mydata_len == 0) {
1247 last_was_gap =
false;
1250 mydata_len = AdjustToAcked(p, ssn, *stream, app_progress, mydata_len);
1252 if (mydata == NULL && mydata_len > 0 && CheckGap(ssn, *stream, p)) {
1253 SCLogDebug(
"sending GAP to app-layer (size: %u)", mydata_len);
1256 StreamGetAppLayerFlags(ssn, *stream, p) | STREAM_GAP, dir);
1257 AppLayerProfilingStore(ra_ctx->
app_tctx, p);
1270 if ((*stream)->data_required > 0) {
1271 if ((*stream)->data_required > mydata_len) {
1272 (*stream)->data_required -= mydata_len;
1274 (*stream)->data_required = 0;
1279 if (no_progress_update)
1281 last_was_gap =
true;
1284 }
else if (
flags & STREAM_DEPTH) {
1287 if (mydata == NULL && mydata_len > 0) {
1290 }
else if (mydata == NULL || (mydata_len == 0 && ((
flags & STREAM_EOF) == 0))) {
1303 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1304 *stream, &(*stream)->sb, mydata_len, app_progress);
1308 if (mydata_len < (*stream)->data_required) {
1311 SCLogDebug(
"GAP while expecting more data (expect %u, gap size %u)",
1312 (*stream)->data_required, mydata_len);
1313 (*stream)->app_progress_rel += mydata_len;
1314 (*stream)->data_required -= mydata_len;
1324 (*stream)->data_required = 0;
1329 tv, ra_ctx, p, p->
flow, ssn, stream, (uint8_t *)mydata, mydata_len,
flags, dir);
1330 AppLayerProfilingStore(ra_ctx->
app_tctx, p);
1335 app_progress = new_app_progress;
1336 if (
flags & STREAM_DEPTH)
1365 SCLogDebug(
"stream no reassembly flag set or app-layer disabled.");
1371 GetSessionSize(ssn, p);
1383 StreamGetAppLayerFlags(ssn, stream, p), dir);
1384 AppLayerProfilingStore(ra_ctx->
app_tctx, p);
1391 return ReassembleUpdateAppLayer(
tv, ra_ctx, ssn, &stream, p, dir);
1397 static int GetRawBuffer(
TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1400 const uint8_t *mydata;
1401 uint32_t mydata_len;
1405 uint64_t roffset =
offset;
1413 *data_len = mydata_len;
1414 *data_offset = roffset;
1416 SCLogDebug(
"multiblob %s. Want offset %"PRIu64,
1417 *iter == NULL ?
"starting" :
"continuing",
offset);
1418 if (*iter == NULL) {
1423 if (*iter == NULL) {
1430 SCLogDebug(
"getting multiple blobs. Iter %p, %"PRIu64
"/%u", *iter, (*iter)->offset, (*iter)->len);
1435 if ((*iter)->offset <
offset) {
1436 uint64_t delta =
offset - (*iter)->offset;
1437 if (delta < mydata_len) {
1438 *data = mydata + delta;
1439 *data_len = mydata_len - delta;
1450 *data_len = mydata_len;
1451 *data_offset = (*iter)->offset;
1454 *iter = SBB_RB_NEXT(*iter);
1485 const uint64_t segs_re_abs =
1490 if (StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 1) {
1527 }
else if (progress == 0) {
1532 target = GetAbsLastAck(stream);
1541 SCLogDebug(
"p->pcap_cnt %"PRIu64
": progress %"PRIu64
" app %"PRIu64
" raw %"PRIu64
" tcp win %"PRIu32,
1550 SCLogDebug(
"ssn %p: STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED set, "
1551 "now that detect ran also set STREAMTCP_STREAM_FLAG_DISABLE_RAW", ssn);
1597 SCLogDebug(
"packet payload len %u, so chunk_size adjusted to %u",
1599 }
else if (((chunk_size / 3 ) * 2) < p->
payload_len) {
1601 SCLogDebug(
"packet payload len %u, so chunk_size adjusted to %u",
1606 uint64_t packet_rightedge_abs = packet_leftedge_abs + p->
payload_len;
1607 SCLogDebug(
"packet_leftedge_abs %"PRIu64
", rightedge %"PRIu64,
1608 packet_leftedge_abs, packet_rightedge_abs);
1610 const uint8_t *mydata = NULL;
1611 uint32_t mydata_len = 0;
1612 uint64_t mydata_offset = 0;
1614 bool return_progress =
false;
1619 return_progress =
true;
1622 SCLogDebug(
"finding our SBB from offset %"PRIu64, packet_leftedge_abs);
1629 mydata_offset = sbb->
offset;
1634 uint64_t mydata_rightedge_abs = mydata_offset + mydata_len;
1635 if ((mydata == NULL || mydata_len == 0) ||
1636 (mydata_offset >= packet_rightedge_abs ||
1637 packet_leftedge_abs >= mydata_rightedge_abs) ||
1638 (packet_leftedge_abs < mydata_offset ||
1639 packet_rightedge_abs > mydata_rightedge_abs))
1644 mydata_offset = packet_leftedge_abs;
1648 SCLogDebug(
"chunk_size %u mydata_len %u", chunk_size, mydata_len);
1649 if (mydata_len > chunk_size) {
1650 uint32_t excess = mydata_len - chunk_size;
1651 SCLogDebug(
"chunk_size %u mydata_len %u excess %u", chunk_size, mydata_len, excess);
1653 if (mydata_rightedge_abs == packet_rightedge_abs) {
1655 mydata_len -= excess;
1656 mydata_offset += excess;
1657 SCLogDebug(
"cutting front of the buffer with %u", excess);
1658 }
else if (mydata_offset == packet_leftedge_abs) {
1659 mydata_len -= excess;
1660 SCLogDebug(
"cutting tail of the buffer with %u", excess);
1662 uint32_t before = (uint32_t)(packet_leftedge_abs - mydata_offset);
1663 uint32_t after = (uint32_t)(mydata_rightedge_abs - packet_rightedge_abs);
1664 SCLogDebug(
"before %u after %u", before, after);
1669 if (before >= (chunk_size - p->
payload_len) / 2) {
1671 before = after = (chunk_size - p->
payload_len) / 2;
1680 if (before >= (chunk_size - p->
payload_len) / 2) {
1688 uint32_t skip = (uint32_t)(packet_leftedge_abs - mydata_offset) - before;
1689 uint32_t cut = (uint32_t)(mydata_rightedge_abs - packet_rightedge_abs) - after;
1694 mydata_len -= (skip + cut);
1695 mydata_offset += skip;
1701 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1704 if (return_progress) {
1705 *progress_out = (mydata_offset + mydata_len);
1712 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1713 SCLogDebug(
"last_ack_abs %"PRIu64, last_ack_abs);
1716 if (mydata_offset > last_ack_abs) {
1718 *progress_out = last_ack_abs;
1720 *progress_out = (mydata_offset + mydata_len);
1763 const uint64_t re, uint64_t *progress_out,
bool eof,
bool respect_inspect_depth)
1769 uint64_t progress = progress_in;
1774 const uint8_t *mydata;
1775 uint32_t mydata_len;
1776 uint64_t mydata_offset = 0;
1778 GetRawBuffer(stream, &mydata, &mydata_len, &iter, progress, &mydata_offset);
1779 if (mydata_len == 0) {
1785 SCLogDebug(
"raw progress %"PRIu64, progress);
1786 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1787 stream, &stream->
sb, mydata_len, progress);
1792 if (re < progress) {
1797 SCLogDebug(
"re %" PRIu64
", raw_progress %" PRIu64, re, progress);
1798 SCLogDebug(
"raw_progress + mydata_len %" PRIu64
", re %" PRIu64, progress + mydata_len,
1802 if (progress + mydata_len > re) {
1803 uint32_t check = mydata_len;
1804 mydata_len = re - progress;
1805 BUG_ON(check < mydata_len);
1806 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1807 "data is considered", mydata_len);
1810 if (mydata_len == 0)
1813 SCLogDebug(
"data %p len %u", mydata, mydata_len);
1816 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1819 if (mydata_offset == progress) {
1820 SCLogDebug(
"progress %"PRIu64
" increasing with data len %u to %"PRIu64,
1821 progress, mydata_len, progress_in + mydata_len);
1823 progress += mydata_len;
1824 SCLogDebug(
"raw progress now %"PRIu64, progress);
1827 }
else if (mydata_offset > progress && mydata_offset < re) {
1828 SCLogDebug(
"GAP: data is missing from %"PRIu64
" (%u bytes), setting to first data we have: %"PRIu64, progress, (uint32_t)(mydata_offset - progress), mydata_offset);
1830 progress = mydata_offset;
1831 SCLogDebug(
"raw progress now %"PRIu64, progress);
1834 SCLogDebug(
"not increasing progress, data gap => mydata_offset "
1835 "%"PRIu64
" != progress %"PRIu64, mydata_offset, progress);
1838 if (iter == NULL || r == 1)
1842 *progress_out = progress;
1847 void *cb_data,
const uint64_t
offset,
const bool eof)
1851 SCLogDebug(
"app_progress %" PRIu64, app_progress);
1853 uint64_t unused = 0;
1854 return StreamReassembleRawDo(
1855 ssn, stream, Callback, cb_data,
offset, app_progress, &unused, eof,
false);
1860 uint64_t *progress_out,
bool respect_inspect_depth)
1864 return StreamReassembleRawInline(ssn, p, Callback, cb_data, progress_out);
1875 StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 0)
1887 SCLogDebug(
"respect_inspect_depth %s STREAMTCP_STREAM_FLAG_TRIGGER_RAW %s "
1888 "stream->min_inspect_depth %u",
1889 respect_inspect_depth ?
"true" :
"false",
1906 SCLogDebug(
"applied min inspect depth due to STREAMTCP_STREAM_FLAG_TRIGGER_RAW: progress "
1916 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1917 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1919 return StreamReassembleRawDo(ssn, stream, Callback, cb_data, progress, last_ack_abs,
1925 uint64_t progress_in,
1926 uint64_t *progress_out,
bool eof)
1932 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1933 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1935 return StreamReassembleRawDo(
1936 ssn, stream, Callback, cb_data, progress_in, last_ack_abs, progress_out, eof,
false);
1944 static int StreamTcpReassembleHandleSegmentUpdateACK (
ThreadVars *
tv,
1962 SCLogDebug(
"ssn %p, stream %p, p %p, p->payload_len %"PRIu16
"",
1989 if (stream == &ssn->
client) {
1990 opposing_stream = &ssn->
server;
1992 opposing_stream = &ssn->
client;
1997 if (StreamTcpReassembleHandleSegmentUpdateACK(
tv, ra_ctx, ssn, opposing_stream, p) != 0) {
1998 SCLogDebug(
"StreamTcpReassembleHandleSegmentUpdateACK error");
2006 if (reversed_before_ack_handling != reversed_after_ack_handling) {
2008 stream = opposing_stream;
2014 SCLogDebug(
"calling StreamTcpReassembleHandleSegmentHandleData");
2017 SCLogDebug(
"StreamTcpReassembleHandleSegmentHandleData error");
2027 SCLogDebug(
"ssn %p / stream %p: not calling StreamTcpReassembleHandleSegmentHandleData:"
2028 " p->payload_len %u, STREAMTCP_STREAM_FLAG_NOREASSEMBLY %s",
2038 if ((stream->
flags &
2042 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED, truncate applayer");
2044 SCLogDebug(
"override: direction now UPDATE_DIR_PACKET so we "
2045 "can trigger Truncate");
2053 SCLogDebug(
"inline (%s) or PKT_PSEUDO_STREAM_END (%s)",
2112 if (direction == STREAM_TOSERVER) {
2118 SCLogDebug(
"flagged ssn %p for immediate raw reassembly", ssn);
2129 if (direction == STREAM_TOSERVER) {
2131 SCLogDebug(
"ssn %p: set client.min_inspect_depth to %u", ssn, depth);
2134 SCLogDebug(
"ssn %p: set server.min_inspect_depth to %u", ssn, depth);
2142 #define SET_ISN(stream, setseq) \
2143 (stream)->isn = (setseq); \
2144 (stream)->base_seq = (setseq) + 1
2162 for (; i <
len; i++)
2186 data, data_len) == 0)
2195 #define MISSED_START(isn) \
2196 TcpReassemblyThreadCtx *ra_ctx = NULL; \
2199 memset(&tv, 0, sizeof(tv)); \
2201 StreamTcpUTInit(&ra_ctx); \
2203 StreamTcpUTSetupSession(&ssn); \
2204 StreamTcpUTSetupStream(&ssn.server, (isn)); \
2205 StreamTcpUTSetupStream(&ssn.client, (isn)); \
2207 TcpStream *stream = &ssn.client;
2209 #define MISSED_END \
2210 StreamTcpUTClearSession(&ssn); \
2211 StreamTcpUTDeinit(ra_ctx); \
2214 #define MISSED_STEP(seq, seg, seglen, buf, buflen) \
2215 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen)); \
2216 FAIL_IF(!(VALIDATE(stream, (uint8_t *)(buf), (buflen))));
2218 #define MISSED_ADD_PAYLOAD(seq, seg, seglen) \
2219 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen));
2226 uint64_t last_re = 0;
2230 if (sbb->
offset != last_re) {
2232 if (cnt == pos && last_re ==
offset &&
len == sbb->
offset - last_re) {
2250 uint64_t last_re = 0;
2254 if (sbb->
offset != last_re) {
2260 const uint8_t *buf = NULL;
2261 uint32_t buf_len = 0;
2264 if (
len == buf_len) {
2265 return (memcmp(data, buf,
len) == 0);
2282 static int StreamTcpReassembleTest25 (
void)
2303 static int StreamTcpReassembleTest26 (
void)
2322 static int StreamTcpReassembleTest27 (
void)
2339 static int StreamTcpReassembleTest28 (
void)
2363 static int StreamTcpReassembleTest29 (
void)
2375 static int StreamTcpReassembleTest33(
void)
2384 uint8_t packet[1460] =
"";
2389 memset(&f, 0,
sizeof (
Flow));
2390 memset(&tcph, 0,
sizeof (TCPHdr));
2395 f.
proto = IPPROTO_TCP;
2398 p->
proto = IPPROTO_TCP;
2406 p->
tcph->th_seq = htonl(10);
2407 p->
tcph->th_ack = htonl(31);
2412 p->
tcph->th_seq = htonl(20);
2413 p->
tcph->th_ack = htonl(31);
2418 p->
tcph->th_seq = htonl(40);
2419 p->
tcph->th_ack = htonl(31);
2424 p->
tcph->th_seq = htonl(5);
2425 p->
tcph->th_ack = htonl(31);
2436 static int StreamTcpReassembleTest34(
void)
2445 uint8_t packet[1460] =
"";
2449 memset(&f, 0,
sizeof (
Flow));
2450 memset(&tcph, 0,
sizeof (TCPHdr));
2455 f.
proto = IPPROTO_TCP;
2458 p->
proto = IPPROTO_TCP;
2467 p->
tcph->th_seq = htonl(857961230);
2468 p->
tcph->th_ack = htonl(31);
2473 p->
tcph->th_seq = htonl(857961534);
2474 p->
tcph->th_ack = htonl(31);
2479 p->
tcph->th_seq = htonl(857963582);
2480 p->
tcph->th_ack = htonl(31);
2485 p->
tcph->th_seq = htonl(857960946);
2486 p->
tcph->th_ack = htonl(31);
2505 static int StreamTcpReassembleTest39 (
void)
2515 memset (&f, 0,
sizeof(
Flow));
2517 memset(&stt, 0,
sizeof (stt));
2518 memset(&tcph, 0,
sizeof (TCPHdr));
2522 f.
proto = IPPROTO_TCP;
2529 tcph.th_win = htons(5480);
2554 p->
tcph->th_ack = htonl(1);
2575 p->
tcph->th_ack = htonl(1);
2576 p->
tcph->th_seq = htonl(1);
2597 uint8_t request1[] = { 0x47, 0x45, };
2598 p->
tcph->th_ack = htonl(1);
2599 p->
tcph->th_seq = htonl(1);
2621 p->
tcph->th_ack = htonl(3);
2622 p->
tcph->th_seq = htonl(1);
2644 uint8_t request2[] = {
2645 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
2646 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
2647 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
2648 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
2649 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
2650 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
2651 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
2652 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
2653 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
2654 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
2655 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
2656 p->
tcph->th_ack = htonl(1);
2657 p->
tcph->th_seq = htonl(3);
2680 uint8_t response[] = {
2681 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
2682 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
2683 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
2684 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
2685 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
2686 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
2687 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
2688 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
2689 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
2690 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
2691 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
2692 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
2693 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
2694 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
2695 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
2696 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
2697 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
2698 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
2699 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
2700 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
2701 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
2702 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
2703 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
2704 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
2705 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
2706 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
2707 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
2708 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
2709 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
2710 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
2711 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
2712 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
2713 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
2714 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
2715 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
2716 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
2717 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
2718 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
2719 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
2720 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
2721 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
2722 p->
tcph->th_ack = htonl(88);
2723 p->
tcph->th_seq = htonl(1);
2747 p->
tcph->th_ack = htonl(328);
2748 p->
tcph->th_seq = htonl(88);
2772 p->
tcph->th_ack = htonl(88);
2773 p->
tcph->th_seq = htonl(328);
2797 p->
tcph->th_ack = htonl(328);
2798 p->
tcph->th_seq = htonl(88);
2821 p->
tcph->th_ack = htonl(88);
2822 p->
tcph->th_seq = htonl(328);
2847 p->
tcph->th_ack = htonl(328);
2848 p->
tcph->th_seq = htonl(88);
2872 p->
tcph->th_ack = htonl(90);
2873 p->
tcph->th_seq = htonl(328);
2898 p->
tcph->th_ack = htonl(328);
2899 p->
tcph->th_seq = htonl(90);
2924 p->
tcph->th_ack = htonl(175);
2925 p->
tcph->th_seq = htonl(328);
2951 p->
tcph->th_ack = htonl(175);
2952 p->
tcph->th_seq = htonl(328);
2968 p->
tcph->th_ack = htonl(328);
2969 p->
tcph->th_seq = htonl(175);
2989 static int StreamTcpReassembleTest40 (
void)
2996 memset(&tcph, 0,
sizeof (TCPHdr));
3006 uint8_t httpbuf1[] =
"P";
3007 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3008 uint8_t httpbuf3[] =
"O";
3009 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
3010 uint8_t httpbuf4[] =
"S";
3011 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
3012 uint8_t httpbuf5[] =
"T \r\n";
3013 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
3015 uint8_t httpbuf2[] =
"HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
3016 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3023 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3026 f->
proto = IPPROTO_TCP;
3029 tcph.th_win = htons(5480);
3030 tcph.th_seq = htonl(10);
3031 tcph.th_ack = htonl(10);
3045 tcph.th_seq = htonl(10);
3046 tcph.th_ack = htonl(11);
3055 tcph.th_seq = htonl(11);
3056 tcph.th_ack = htonl(55);
3065 tcph.th_seq = htonl(55);
3066 tcph.th_ack = htonl(12);
3080 tcph.th_seq = htonl(12);
3081 tcph.th_ack = htonl(100);
3090 tcph.th_seq = htonl(100);
3091 tcph.th_ack = htonl(13);
3100 tcph.th_seq = htonl(13);
3101 tcph.th_ack = htonl(145);
3110 tcph.th_seq = htonl(145);
3111 tcph.th_ack = htonl(16);
3127 static int StreamTcpReassembleTest44(
void)
3148 static int StreamTcpReassembleTest45 (
void)
3153 memset(&
tv, 0,
sizeof(
tv));
3154 uint8_t payload[100] = {0};
3155 uint16_t payload_size = 100;
3186 static int StreamTcpReassembleTest46 (
void)
3192 memset(&
tv, 0,
sizeof(
tv));
3193 uint8_t payload[100] = {0};
3194 uint16_t payload_size = 100;
3207 printf(
"STREAMTCP_STREAM_FLAG_NOREASSEMBLY set: ");
3215 printf(
"STREAMTCP_STREAM_FLAG_NOREASSEMBLY set: ");
3235 static int StreamTcpReassembleTest47 (
void)
3243 memset(&tcph, 0,
sizeof (TCPHdr));
3249 uint8_t httpbuf1[] =
"GET /EVILSUFF HTTP/1.1\r\n\r\n";
3250 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3258 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3261 f->
proto = IPPROTO_TCP;
3264 tcph.th_win = htons(5480);
3269 for (cnt=0; cnt < httplen1; cnt++) {
3270 tcph.th_seq = htonl(ssn.
client.
isn + 1 + cnt);
3271 tcph.th_ack = htonl(572799782UL);
3284 tcph.th_seq = htonl(572799782UL);
3285 tcph.th_ack = htonl(ssn.
client.
isn + 1 + cnt);
3304 static int StreamTcpReassembleInlineTest01(
void)
3312 memset(&
tv, 0x00,
sizeof(
tv));
3320 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3323 printf(
"couldn't get a packet: ");
3326 p->
tcph->th_seq = htonl(12);
3330 printf(
"failed to add segment 1: ");
3334 printf(
"failed to add segment 2: ");
3338 printf(
"failed to add segment 3: ");
3354 static int StreamTcpReassembleInlineTest02(
void)
3362 memset(&
tv, 0x00,
sizeof(
tv));
3370 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3373 printf(
"couldn't get a packet: ");
3376 p->
tcph->th_seq = htonl(12);
3380 printf(
"failed to add segment 1: ");
3384 printf(
"failed to add segment 2: ");
3388 printf(
"failed to add segment 3: ");
3393 printf(
"failed to add segment 4: ");
3410 static int StreamTcpReassembleInlineTest03(
void)
3418 memset(&
tv, 0x00,
sizeof(
tv));
3428 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3431 printf(
"couldn't get a packet: ");
3434 p->
tcph->th_seq = htonl(12);
3439 printf(
"failed to add segment 1: ");
3443 printf(
"failed to add segment 2: ");
3447 printf(
"failed to add segment 3: ");
3452 printf(
"failed to add segment 4: ");
3457 p->
tcph->th_seq = htonl(17);
3471 static int StreamTcpReassembleInlineTest04(
void)
3479 memset(&
tv, 0x00,
sizeof(
tv));
3489 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3492 printf(
"couldn't get a packet: ");
3495 p->
tcph->th_seq = htonl(12);
3500 printf(
"failed to add segment 1: ");
3504 printf(
"failed to add segment 2: ");
3508 printf(
"failed to add segment 3: ");
3513 printf(
"failed to add segment 4: ");
3518 p->
tcph->th_seq = htonl(17);
3533 static int StreamTcpReassembleInlineTest08(
void)
3537 memset(&
tv, 0x00,
sizeof(
tv));
3549 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3552 p->
tcph->th_seq = htonl(12);
3562 p->
tcph->th_seq = htonl(17);
3581 static int StreamTcpReassembleInlineTest09(
void)
3589 memset(&
tv, 0x00,
sizeof(
tv));
3599 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3602 printf(
"couldn't get a packet: ");
3605 p->
tcph->th_seq = htonl(17);
3610 printf(
"failed to add segment 1: ");
3614 printf(
"failed to add segment 2: ");
3618 printf(
"failed to add segment 3: ");
3626 printf(
"failed to add segment 4: ");
3631 p->
tcph->th_seq = htonl(12);
3648 static int StreamTcpReassembleInlineTest10(
void)
3657 memset(&
tv, 0x00,
sizeof(
tv));
3668 f =
UTHBuildFlow(AF_INET,
"1.1.1.1",
"2.2.2.2", 1024, 80);
3672 f->
proto = IPPROTO_TCP;
3674 uint8_t stream_payload1[] =
"GE";
3675 uint8_t stream_payload2[] =
"T /";
3676 uint8_t stream_payload3[] =
"HTTP/1.0\r\n\r\n";
3678 p =
UTHBuildPacketReal(stream_payload3, 12, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
3680 printf(
"couldn't get a packet: ");
3683 p->
tcph->th_seq = htonl(7);
3688 printf(
"failed to add segment 1: ");
3695 printf(
"StreamTcpReassembleAppLayer failed: ");
3701 printf(
"expected ra_app_base_seq 1, got %u: ", ssn.
client.
base_seq);
3706 printf(
"failed to add segment 2: ");
3710 printf(
"failed to add segment 3: ");
3717 printf(
"StreamTcpReassembleAppLayer failed: ");
3734 static int StreamTcpReassembleInsertTest01(
void)
3741 memset(&
tv, 0x00,
sizeof(
tv));
3749 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3752 p->
tcph->th_seq = htonl(12);
3771 static int StreamTcpReassembleInsertTest02(
void)
3778 memset(&
tv, 0x00,
sizeof(
tv));
3785 for (i = 2; i < 10; i++) {
3796 printf(
"failed to add segment 1: ");
3801 printf(
"failed to add segment 2: ");
3814 static int StreamTcpReassembleInsertTest03(
void)
3821 memset(&
tv, 0x00,
sizeof(
tv));
3828 printf(
"failed to add segment 2: ");
3833 for (i = 2; i < 10; i++) {
3844 printf(
"failed to add segment 2: ");
3865 UtRegisterTest(
"StreamTcpReassembleTest25 -- Gap at Start Reassembly Test",
3866 StreamTcpReassembleTest25);
3867 UtRegisterTest(
"StreamTcpReassembleTest26 -- Gap at middle Reassembly Test",
3868 StreamTcpReassembleTest26);
3869 UtRegisterTest(
"StreamTcpReassembleTest27 -- Gap at after Reassembly Test",
3870 StreamTcpReassembleTest27);
3871 UtRegisterTest(
"StreamTcpReassembleTest28 -- Gap at Start IDS missed packet Reassembly Test",
3872 StreamTcpReassembleTest28);
3873 UtRegisterTest(
"StreamTcpReassembleTest29 -- Gap at Middle IDS missed packet Reassembly Test",
3874 StreamTcpReassembleTest29);
3876 StreamTcpReassembleTest33);
3878 StreamTcpReassembleTest34);
3880 StreamTcpReassembleTest39);
3882 StreamTcpReassembleTest40);
3884 StreamTcpReassembleTest44);
3886 StreamTcpReassembleTest45);
3888 StreamTcpReassembleTest46);
3889 UtRegisterTest(
"StreamTcpReassembleTest47 -- TCP Sequence Wraparound Test",
3890 StreamTcpReassembleTest47);
3892 UtRegisterTest(
"StreamTcpReassembleInlineTest01 -- inline RAW ra",
3893 StreamTcpReassembleInlineTest01);
3894 UtRegisterTest(
"StreamTcpReassembleInlineTest02 -- inline RAW ra 2",
3895 StreamTcpReassembleInlineTest02);
3896 UtRegisterTest(
"StreamTcpReassembleInlineTest03 -- inline RAW ra 3",
3897 StreamTcpReassembleInlineTest03);
3898 UtRegisterTest(
"StreamTcpReassembleInlineTest04 -- inline RAW ra 4",
3899 StreamTcpReassembleInlineTest04);
3900 UtRegisterTest(
"StreamTcpReassembleInlineTest08 -- inline RAW ra 8 cleanup",
3901 StreamTcpReassembleInlineTest08);
3902 UtRegisterTest(
"StreamTcpReassembleInlineTest09 -- inline RAW ra 9 GAP cleanup",
3903 StreamTcpReassembleInlineTest09);
3905 UtRegisterTest(
"StreamTcpReassembleInlineTest10 -- inline APP ra 10",
3906 StreamTcpReassembleInlineTest10);
3908 UtRegisterTest(
"StreamTcpReassembleInsertTest01 -- insert with overlap",
3909 StreamTcpReassembleInsertTest01);
3910 UtRegisterTest(
"StreamTcpReassembleInsertTest02 -- insert with overlap",
3911 StreamTcpReassembleInsertTest02);
3912 UtRegisterTest(
"StreamTcpReassembleInsertTest03 -- insert with overlap",
3913 StreamTcpReassembleInsertTest03);
3918 StreamTcpReassembleRawRegisterTests();