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);
577 TcpSegmentPoolInit, NULL,
578 TcpSegmentPoolCleanup, NULL);
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?");
649 uint32_t
seq, uint32_t size)
667 SCLogDebug(
"segment entirely before base_seq, weird: base %u, seq %u, re %u",
681 SCLogDebug(
"seq + size %u, base %u, seg_depth %"PRIu64
" limit %u", (
seq + size),
686 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
690 SCLogDebug(
"NOT STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
693 SCLogDebug(
"full depth not yet reached: %"PRIu64
" <= %"PRIu32,
694 (stream->base_seq_offset + stream->
base_seq + size),
761 SCLogDebug(
"ssn %p: both app and raw reassembly disabled, not reassembling", ssn);
768 SCLogDebug(
"ssn %p: check depth returned %"PRIu32, ssn, size);
777 SCLogDebug(
"ssn %p: depth reached, not reassembling", ssn);
815 SCLogDebug(
"StreamTcpReassembleInsertSegment failed");
827 flag |= STREAM_START;
835 flag |= STREAM_MIDSTREAM;
842 if (&ssn->
client == stream) {
843 flag |= STREAM_TOSERVER;
845 flag |= STREAM_TOCLIENT;
848 flag |= STREAM_DEPTH;
859 static int StreamTcpReassembleRawCheckLimit(
const TcpSession *ssn,
865 #define STREAMTCP_STREAM_FLAG_FLUSH_FLAGS \
866 ( STREAMTCP_STREAM_FLAG_DEPTH_REACHED \
867 | STREAMTCP_STREAM_FLAG_TRIGGER_RAW \
868 | STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED)
872 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_DEPTH_REACHED "
873 "is set, so not expecting any new data segments");
876 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_TRIGGER_RAW is set");
879 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED is set, "
880 "so no new segments will be considered");
884 #undef STREAMTCP_STREAM_FLAG_FLUSH_FLAGS
893 const uint64_t last_ack_abs = GetAbsLastAck(stream);
899 if (chunk_size <= diff) {
902 SCLogDebug(
"%s min chunk len not yet reached: "
903 "last_ack %" PRIu32
", ra_raw_base_seq %" PRIu32
", %" PRIu32
" < "
920 const char *dirstr = NULL;
922 if (direction == STREAM_TOSERVER) {
946 const uint64_t right_edge =
948 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
949 " (use: %s). Stream right edge: %" PRIu64,
953 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
958 const uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
959 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
960 " (use: %s). Stream right edge: %" PRIu64,
964 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
969 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NONE", dirstr);
974 static uint64_t GetStreamSize(
TcpStream *stream)
979 uint64_t last_ack_abs = GetAbsLastAck(stream);
980 uint64_t last_re = 0;
986 const uint64_t seg_abs =
988 if (last_re != 0 && last_re < seg_abs) {
989 const char *gacked = NULL;
990 if (last_ack_abs >= seg_abs) {
991 gacked =
"fully ack'd";
992 }
else if (last_ack_abs > last_re) {
993 gacked =
"partly ack'd";
995 gacked =
"not yet ack'd";
997 SCLogDebug(
" -> gap of size %" PRIu64
", ack:%s", seg_abs - last_re, gacked);
1000 const char *acked = NULL;
1001 if (last_ack_abs >= seg_abs + (uint64_t)
TCP_SEG_LEN(seg)) {
1002 acked =
"fully ack'd";
1003 }
else if (last_ack_abs > seg_abs) {
1004 acked =
"partly ack'd";
1006 acked =
"not yet ack'd";
1009 SCLogDebug(
"%u -> seg %p seq %u abs %" PRIu64
" size %u abs %" PRIu64
" (%" PRIu64
1028 size = GetStreamSize(&ssn->
client);
1029 size += GetStreamSize(&ssn->
server);
1044 for ( ; blk != NULL; blk = SBB_RB_NEXT(blk)) {
1058 GetAbsLastAck(stream) > (cur_blk->
offset + cur_blk->
len)) {
1073 static bool GetAppBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1074 uint64_t
offset,
const bool check_for_gap)
1076 const uint8_t *mydata;
1077 uint32_t mydata_len;
1078 bool gap_ahead =
false;
1086 *data_len = mydata_len;
1104 gap_ahead = check_for_gap && GapAhead(stream, blk);
1108 SCLogDebug(
"gap, want data at offset %"PRIu64
", "
1109 "got data at %"PRIu64
". GAP of size %"PRIu64,
1116 SCLogDebug(
"get data from offset %"PRIu64
". SBB %"PRIu64
"/%u",
1119 SCLogDebug(
"data %p, data_len %u", *data, *data_len);
1121 gap_ahead = check_for_gap && GapAhead(stream, blk);
1140 const uint64_t last_ack_abs = GetAbsLastAck(stream) - (uint64_t)ackadded;
1147 if (last_ack_abs > app_progress) {
1154 "next_seq %u < last_ack %u, but no data in list",
1158 const uint64_t next_seq_abs =
1161 if (blk->
offset > next_seq_abs && blk->
offset < last_ack_abs) {
1164 "next_seq %u < last_ack %u, but ACK'd data beyond gap.",
1172 "last_ack_abs %" PRIu64
" > app_progress %" PRIu64
", "
1173 "but we have no data.",
1174 p->
pcap_cnt, last_ack_abs, app_progress);
1178 "last_ack_abs %"PRIu64
" <= app_progress %"PRIu64,
1179 p->
pcap_cnt, last_ack_abs, app_progress);
1183 static inline uint32_t AdjustToAcked(
const Packet *p,
1185 const uint64_t app_progress,
const uint32_t data_len)
1187 uint32_t adjusted = data_len;
1198 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1202 if (app_progress <= last_ack_abs && app_progress + data_len > last_ack_abs) {
1203 uint32_t check = data_len;
1204 adjusted = last_ack_abs - app_progress;
1205 BUG_ON(adjusted > check);
1206 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1207 "data is considered", adjusted);
1226 SCLogDebug(
"app progress %"PRIu64, app_progress);
1228 uint64_t last_ack_abs = GetAbsLastAck(*stream);
1229 SCLogDebug(
"last_ack %u (abs %" PRIu64
"), base_seq %u", (*stream)->last_ack, last_ack_abs,
1230 (*stream)->base_seq);
1232 const uint8_t *mydata;
1233 uint32_t mydata_len;
1234 bool last_was_gap =
false;
1237 const uint8_t
flags = StreamGetAppLayerFlags(ssn, *stream, p);
1238 bool check_for_gap_ahead = ((*stream)->data_required > 0);
1240 GetAppBuffer(*stream, &mydata, &mydata_len, app_progress, check_for_gap_ahead);
1242 if (last_was_gap && mydata_len == 0) {
1245 last_was_gap =
false;
1248 mydata_len = AdjustToAcked(p, ssn, *stream, app_progress, mydata_len);
1250 if (mydata == NULL && mydata_len > 0 && CheckGap(ssn, *stream, p)) {
1251 SCLogDebug(
"sending GAP to app-layer (size: %u)", mydata_len);
1254 StreamGetAppLayerFlags(ssn, *stream, p) | STREAM_GAP, dir);
1255 AppLayerProfilingStore(ra_ctx->
app_tctx, p);
1268 if ((*stream)->data_required > 0) {
1269 if ((*stream)->data_required > mydata_len) {
1270 (*stream)->data_required -= mydata_len;
1272 (*stream)->data_required = 0;
1277 if (no_progress_update)
1279 last_was_gap =
true;
1282 }
else if (
flags & STREAM_DEPTH) {
1285 if (mydata == NULL && mydata_len > 0) {
1288 }
else if (mydata == NULL || (mydata_len == 0 && ((
flags & STREAM_EOF) == 0))) {
1301 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1302 *stream, &(*stream)->sb, mydata_len, app_progress);
1306 if (mydata_len < (*stream)->data_required) {
1309 SCLogDebug(
"GAP while expecting more data (expect %u, gap size %u)",
1310 (*stream)->data_required, mydata_len);
1311 (*stream)->app_progress_rel += mydata_len;
1312 (*stream)->data_required -= mydata_len;
1322 (*stream)->data_required = 0;
1327 tv, ra_ctx, p, p->
flow, ssn, stream, (uint8_t *)mydata, mydata_len,
flags, dir);
1328 AppLayerProfilingStore(ra_ctx->
app_tctx, p);
1333 app_progress = new_app_progress;
1334 if (
flags & STREAM_DEPTH)
1363 SCLogDebug(
"stream no reassembly flag set or app-layer disabled.");
1369 GetSessionSize(ssn, p);
1381 StreamGetAppLayerFlags(ssn, stream, p), dir);
1382 AppLayerProfilingStore(ra_ctx->
app_tctx, p);
1389 return ReassembleUpdateAppLayer(
tv, ra_ctx, ssn, &stream, p, dir);
1395 static int GetRawBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1398 const uint8_t *mydata;
1399 uint32_t mydata_len;
1403 uint64_t roffset =
offset;
1411 *data_len = mydata_len;
1412 *data_offset = roffset;
1414 SCLogDebug(
"multiblob %s. Want offset %"PRIu64,
1415 *iter == NULL ?
"starting" :
"continuing",
offset);
1416 if (*iter == NULL) {
1421 if (*iter == NULL) {
1428 SCLogDebug(
"getting multiple blobs. Iter %p, %"PRIu64
"/%u", *iter, (*iter)->offset, (*iter)->len);
1433 if ((*iter)->offset <
offset) {
1434 uint64_t delta =
offset - (*iter)->offset;
1435 if (delta < mydata_len) {
1436 *data = mydata + delta;
1437 *data_len = mydata_len - delta;
1448 *data_len = mydata_len;
1449 *data_offset = (*iter)->offset;
1452 *iter = SBB_RB_NEXT(*iter);
1483 const uint64_t segs_re_abs =
1488 if (StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 1) {
1525 }
else if (progress == 0) {
1530 target = GetAbsLastAck(stream);
1539 SCLogDebug(
"p->pcap_cnt %"PRIu64
": progress %"PRIu64
" app %"PRIu64
" raw %"PRIu64
" tcp win %"PRIu32,
1548 SCLogDebug(
"ssn %p: STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED set, "
1549 "now that detect ran also set STREAMTCP_STREAM_FLAG_DISABLE_RAW", ssn);
1595 SCLogDebug(
"packet payload len %u, so chunk_size adjusted to %u",
1597 }
else if (((chunk_size / 3 ) * 2) < p->
payload_len) {
1599 SCLogDebug(
"packet payload len %u, so chunk_size adjusted to %u",
1604 uint64_t packet_rightedge_abs = packet_leftedge_abs + p->
payload_len;
1605 SCLogDebug(
"packet_leftedge_abs %"PRIu64
", rightedge %"PRIu64,
1606 packet_leftedge_abs, packet_rightedge_abs);
1608 const uint8_t *mydata = NULL;
1609 uint32_t mydata_len = 0;
1610 uint64_t mydata_offset = 0;
1612 bool return_progress =
false;
1617 return_progress =
true;
1620 SCLogDebug(
"finding our SBB from offset %"PRIu64, packet_leftedge_abs);
1627 mydata_offset = sbb->
offset;
1632 uint64_t mydata_rightedge_abs = mydata_offset + mydata_len;
1633 if ((mydata == NULL || mydata_len == 0) ||
1634 (mydata_offset >= packet_rightedge_abs ||
1635 packet_leftedge_abs >= mydata_rightedge_abs) ||
1636 (packet_leftedge_abs < mydata_offset ||
1637 packet_rightedge_abs > mydata_rightedge_abs))
1642 mydata_offset = packet_leftedge_abs;
1646 SCLogDebug(
"chunk_size %u mydata_len %u", chunk_size, mydata_len);
1647 if (mydata_len > chunk_size) {
1648 uint32_t excess = mydata_len - chunk_size;
1649 SCLogDebug(
"chunk_size %u mydata_len %u excess %u", chunk_size, mydata_len, excess);
1651 if (mydata_rightedge_abs == packet_rightedge_abs) {
1653 mydata_len -= excess;
1654 mydata_offset += excess;
1655 SCLogDebug(
"cutting front of the buffer with %u", excess);
1656 }
else if (mydata_offset == packet_leftedge_abs) {
1657 mydata_len -= excess;
1658 SCLogDebug(
"cutting tail of the buffer with %u", excess);
1660 uint32_t before = (uint32_t)(packet_leftedge_abs - mydata_offset);
1661 uint32_t after = (uint32_t)(mydata_rightedge_abs - packet_rightedge_abs);
1662 SCLogDebug(
"before %u after %u", before, after);
1667 if (before >= (chunk_size - p->
payload_len) / 2) {
1669 before = after = (chunk_size - p->
payload_len) / 2;
1678 if (before >= (chunk_size - p->
payload_len) / 2) {
1686 uint32_t skip = (uint32_t)(packet_leftedge_abs - mydata_offset) - before;
1687 uint32_t cut = (uint32_t)(mydata_rightedge_abs - packet_rightedge_abs) - after;
1692 mydata_len -= (skip + cut);
1693 mydata_offset += skip;
1699 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1702 if (return_progress) {
1703 *progress_out = (mydata_offset + mydata_len);
1710 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1711 SCLogDebug(
"last_ack_abs %"PRIu64, last_ack_abs);
1714 if (mydata_offset > last_ack_abs) {
1716 *progress_out = last_ack_abs;
1718 *progress_out = (mydata_offset + mydata_len);
1761 const uint64_t re, uint64_t *progress_out,
bool eof,
bool respect_inspect_depth)
1767 uint64_t progress = progress_in;
1772 const uint8_t *mydata;
1773 uint32_t mydata_len;
1774 uint64_t mydata_offset = 0;
1776 GetRawBuffer(stream, &mydata, &mydata_len, &iter, progress, &mydata_offset);
1777 if (mydata_len == 0) {
1783 SCLogDebug(
"raw progress %"PRIu64, progress);
1784 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1785 stream, &stream->
sb, mydata_len, progress);
1790 if (re < progress) {
1795 SCLogDebug(
"re %" PRIu64
", raw_progress %" PRIu64, re, progress);
1796 SCLogDebug(
"raw_progress + mydata_len %" PRIu64
", re %" PRIu64, progress + mydata_len,
1800 if (progress + mydata_len > re) {
1801 uint32_t check = mydata_len;
1802 mydata_len = re - progress;
1803 BUG_ON(check < mydata_len);
1804 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1805 "data is considered", mydata_len);
1808 if (mydata_len == 0)
1811 SCLogDebug(
"data %p len %u", mydata, mydata_len);
1814 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1817 if (mydata_offset == progress) {
1818 SCLogDebug(
"progress %"PRIu64
" increasing with data len %u to %"PRIu64,
1819 progress, mydata_len, progress_in + mydata_len);
1821 progress += mydata_len;
1822 SCLogDebug(
"raw progress now %"PRIu64, progress);
1825 }
else if (mydata_offset > progress && mydata_offset < re) {
1826 SCLogDebug(
"GAP: data is missing from %"PRIu64
" (%u bytes), setting to first data we have: %"PRIu64, progress, (uint32_t)(mydata_offset - progress), mydata_offset);
1828 progress = mydata_offset;
1829 SCLogDebug(
"raw progress now %"PRIu64, progress);
1832 SCLogDebug(
"not increasing progress, data gap => mydata_offset "
1833 "%"PRIu64
" != progress %"PRIu64, mydata_offset, progress);
1836 if (iter == NULL || r == 1)
1840 *progress_out = progress;
1845 void *cb_data,
const uint64_t
offset,
const bool eof)
1849 SCLogDebug(
"app_progress %" PRIu64, app_progress);
1851 uint64_t unused = 0;
1852 return StreamReassembleRawDo(
1853 ssn, stream, Callback, cb_data,
offset, app_progress, &unused, eof,
false);
1858 uint64_t *progress_out,
bool respect_inspect_depth)
1862 return StreamReassembleRawInline(ssn, p, Callback, cb_data, progress_out);
1873 StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 0)
1885 SCLogDebug(
"respect_inspect_depth %s STREAMTCP_STREAM_FLAG_TRIGGER_RAW %s "
1886 "stream->min_inspect_depth %u",
1887 respect_inspect_depth ?
"true" :
"false",
1904 SCLogDebug(
"applied min inspect depth due to STREAMTCP_STREAM_FLAG_TRIGGER_RAW: progress "
1914 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1915 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1917 return StreamReassembleRawDo(ssn, stream, Callback, cb_data, progress, last_ack_abs,
1923 uint64_t *progress_out,
const bool eof)
1929 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1930 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1932 return StreamReassembleRawDo(
1933 ssn, stream, Callback, cb_data, progress_in, last_ack_abs, progress_out, eof,
false);
1941 static int StreamTcpReassembleHandleSegmentUpdateACK (
ThreadVars *
tv,
1959 SCLogDebug(
"ssn %p, stream %p, p %p, p->payload_len %"PRIu16
"",
1986 if (stream == &ssn->
client) {
1987 opposing_stream = &ssn->
server;
1989 opposing_stream = &ssn->
client;
1994 if (StreamTcpReassembleHandleSegmentUpdateACK(
tv, ra_ctx, ssn, opposing_stream, p) != 0) {
1995 SCLogDebug(
"StreamTcpReassembleHandleSegmentUpdateACK error");
2003 if (reversed_before_ack_handling != reversed_after_ack_handling) {
2005 stream = opposing_stream;
2011 SCLogDebug(
"calling StreamTcpReassembleHandleSegmentHandleData");
2014 SCLogDebug(
"StreamTcpReassembleHandleSegmentHandleData error");
2024 SCLogDebug(
"ssn %p / stream %p: not calling StreamTcpReassembleHandleSegmentHandleData:"
2025 " p->payload_len %u, STREAMTCP_STREAM_FLAG_NOREASSEMBLY %s",
2035 if ((stream->
flags &
2039 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED, truncate applayer");
2041 SCLogDebug(
"override: direction now UPDATE_DIR_PACKET so we "
2042 "can trigger Truncate");
2050 SCLogDebug(
"inline (%s) or PKT_PSEUDO_STREAM_END (%s)",
2109 if (direction == STREAM_TOSERVER) {
2115 SCLogDebug(
"flagged ssn %p for immediate raw reassembly", ssn);
2126 if (direction == STREAM_TOSERVER) {
2128 SCLogDebug(
"ssn %p: set client.min_inspect_depth to %u", ssn, depth);
2131 SCLogDebug(
"ssn %p: set server.min_inspect_depth to %u", ssn, depth);
2139 #define SET_ISN(stream, setseq) \
2140 (stream)->isn = (setseq); \
2141 (stream)->base_seq = (setseq) + 1
2159 for (; i <
len; i++)
2183 data, data_len) == 0)
2192 #define MISSED_START(isn) \
2193 TcpReassemblyThreadCtx *ra_ctx = NULL; \
2196 memset(&tv, 0, sizeof(tv)); \
2198 StreamTcpUTInit(&ra_ctx); \
2200 StreamTcpUTSetupSession(&ssn); \
2201 StreamTcpUTSetupStream(&ssn.server, (isn)); \
2202 StreamTcpUTSetupStream(&ssn.client, (isn)); \
2204 TcpStream *stream = &ssn.client;
2206 #define MISSED_END \
2207 StreamTcpUTClearSession(&ssn); \
2208 StreamTcpUTDeinit(ra_ctx); \
2211 #define MISSED_STEP(seq, seg, seglen, buf, buflen) \
2212 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen)); \
2213 FAIL_IF(!(VALIDATE(stream, (uint8_t *)(buf), (buflen))));
2215 #define MISSED_ADD_PAYLOAD(seq, seg, seglen) \
2216 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen));
2223 uint64_t last_re = 0;
2227 if (sbb->
offset != last_re) {
2247 uint64_t last_re = 0;
2251 if (sbb->
offset != last_re) {
2257 const uint8_t *buf = NULL;
2258 uint32_t buf_len = 0;
2261 if (
len == buf_len) {
2262 return (memcmp(data, buf,
len) == 0);
2279 static int StreamTcpReassembleTest25 (
void)
2300 static int StreamTcpReassembleTest26 (
void)
2319 static int StreamTcpReassembleTest27 (
void)
2336 static int StreamTcpReassembleTest28 (
void)
2360 static int StreamTcpReassembleTest29 (
void)
2372 static int StreamTcpReassembleTest33(
void)
2381 uint8_t packet[1460] =
"";
2386 memset(&f, 0,
sizeof (
Flow));
2387 memset(&tcph, 0,
sizeof (TCPHdr));
2392 f.
proto = IPPROTO_TCP;
2395 p->
proto = IPPROTO_TCP;
2403 p->
tcph->th_seq = htonl(10);
2404 p->
tcph->th_ack = htonl(31);
2409 p->
tcph->th_seq = htonl(20);
2410 p->
tcph->th_ack = htonl(31);
2415 p->
tcph->th_seq = htonl(40);
2416 p->
tcph->th_ack = htonl(31);
2421 p->
tcph->th_seq = htonl(5);
2422 p->
tcph->th_ack = htonl(31);
2433 static int StreamTcpReassembleTest34(
void)
2442 uint8_t packet[1460] =
"";
2446 memset(&f, 0,
sizeof (
Flow));
2447 memset(&tcph, 0,
sizeof (TCPHdr));
2452 f.
proto = IPPROTO_TCP;
2455 p->
proto = IPPROTO_TCP;
2464 p->
tcph->th_seq = htonl(857961230);
2465 p->
tcph->th_ack = htonl(31);
2470 p->
tcph->th_seq = htonl(857961534);
2471 p->
tcph->th_ack = htonl(31);
2476 p->
tcph->th_seq = htonl(857963582);
2477 p->
tcph->th_ack = htonl(31);
2482 p->
tcph->th_seq = htonl(857960946);
2483 p->
tcph->th_ack = htonl(31);
2502 static int StreamTcpReassembleTest39 (
void)
2512 memset (&f, 0,
sizeof(
Flow));
2514 memset(&stt, 0,
sizeof (stt));
2515 memset(&tcph, 0,
sizeof (TCPHdr));
2519 f.
proto = IPPROTO_TCP;
2526 tcph.th_win = htons(5480);
2551 p->
tcph->th_ack = htonl(1);
2572 p->
tcph->th_ack = htonl(1);
2573 p->
tcph->th_seq = htonl(1);
2594 uint8_t request1[] = { 0x47, 0x45, };
2595 p->
tcph->th_ack = htonl(1);
2596 p->
tcph->th_seq = htonl(1);
2618 p->
tcph->th_ack = htonl(3);
2619 p->
tcph->th_seq = htonl(1);
2641 uint8_t request2[] = {
2642 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
2643 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
2644 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
2645 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
2646 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
2647 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
2648 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
2649 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
2650 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
2651 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
2652 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
2653 p->
tcph->th_ack = htonl(1);
2654 p->
tcph->th_seq = htonl(3);
2677 uint8_t response[] = {
2678 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
2679 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
2680 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
2681 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
2682 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
2683 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
2684 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
2685 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
2686 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
2687 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
2688 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
2689 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
2690 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
2691 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
2692 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
2693 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
2694 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
2695 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
2696 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
2697 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
2698 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
2699 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
2700 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
2701 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
2702 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
2703 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
2704 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
2705 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
2706 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
2707 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
2708 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
2709 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
2710 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
2711 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
2712 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
2713 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
2714 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
2715 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
2716 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
2717 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
2718 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
2719 p->
tcph->th_ack = htonl(88);
2720 p->
tcph->th_seq = htonl(1);
2744 p->
tcph->th_ack = htonl(328);
2745 p->
tcph->th_seq = htonl(88);
2769 p->
tcph->th_ack = htonl(88);
2770 p->
tcph->th_seq = htonl(328);
2794 p->
tcph->th_ack = htonl(328);
2795 p->
tcph->th_seq = htonl(88);
2818 p->
tcph->th_ack = htonl(88);
2819 p->
tcph->th_seq = htonl(328);
2844 p->
tcph->th_ack = htonl(328);
2845 p->
tcph->th_seq = htonl(88);
2869 p->
tcph->th_ack = htonl(90);
2870 p->
tcph->th_seq = htonl(328);
2895 p->
tcph->th_ack = htonl(328);
2896 p->
tcph->th_seq = htonl(90);
2921 p->
tcph->th_ack = htonl(175);
2922 p->
tcph->th_seq = htonl(328);
2948 p->
tcph->th_ack = htonl(175);
2949 p->
tcph->th_seq = htonl(328);
2965 p->
tcph->th_ack = htonl(328);
2966 p->
tcph->th_seq = htonl(175);
2986 static int StreamTcpReassembleTest40 (
void)
2993 memset(&tcph, 0,
sizeof (TCPHdr));
3003 uint8_t httpbuf1[] =
"P";
3004 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3005 uint8_t httpbuf3[] =
"O";
3006 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
3007 uint8_t httpbuf4[] =
"S";
3008 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
3009 uint8_t httpbuf5[] =
"T \r\n";
3010 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
3012 uint8_t httpbuf2[] =
"HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
3013 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3020 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3023 f->
proto = IPPROTO_TCP;
3026 tcph.th_win = htons(5480);
3027 tcph.th_seq = htonl(10);
3028 tcph.th_ack = htonl(10);
3042 tcph.th_seq = htonl(10);
3043 tcph.th_ack = htonl(11);
3052 tcph.th_seq = htonl(11);
3053 tcph.th_ack = htonl(55);
3062 tcph.th_seq = htonl(55);
3063 tcph.th_ack = htonl(12);
3077 tcph.th_seq = htonl(12);
3078 tcph.th_ack = htonl(100);
3087 tcph.th_seq = htonl(100);
3088 tcph.th_ack = htonl(13);
3097 tcph.th_seq = htonl(13);
3098 tcph.th_ack = htonl(145);
3107 tcph.th_seq = htonl(145);
3108 tcph.th_ack = htonl(16);
3124 static int StreamTcpReassembleTest44(
void)
3145 static int StreamTcpReassembleTest45 (
void)
3150 memset(&
tv, 0,
sizeof(
tv));
3151 uint8_t payload[100] = {0};
3152 uint16_t payload_size = 100;
3183 static int StreamTcpReassembleTest46 (
void)
3189 memset(&
tv, 0,
sizeof(
tv));
3190 uint8_t payload[100] = {0};
3191 uint16_t payload_size = 100;
3204 printf(
"STREAMTCP_STREAM_FLAG_NOREASSEMBLY set: ");
3212 printf(
"STREAMTCP_STREAM_FLAG_NOREASSEMBLY set: ");
3232 static int StreamTcpReassembleTest47 (
void)
3240 memset(&tcph, 0,
sizeof (TCPHdr));
3246 uint8_t httpbuf1[] =
"GET /EVILSUFF HTTP/1.1\r\n\r\n";
3247 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3255 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3258 f->
proto = IPPROTO_TCP;
3261 tcph.th_win = htons(5480);
3268 tcph.th_ack = htonl(572799782UL);
3281 tcph.th_seq = htonl(572799782UL);
3301 static int StreamTcpReassembleInlineTest01(
void)
3309 memset(&
tv, 0x00,
sizeof(
tv));
3317 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3320 printf(
"couldn't get a packet: ");
3323 p->
tcph->th_seq = htonl(12);
3327 printf(
"failed to add segment 1: ");
3331 printf(
"failed to add segment 2: ");
3335 printf(
"failed to add segment 3: ");
3351 static int StreamTcpReassembleInlineTest02(
void)
3359 memset(&
tv, 0x00,
sizeof(
tv));
3367 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3370 printf(
"couldn't get a packet: ");
3373 p->
tcph->th_seq = htonl(12);
3377 printf(
"failed to add segment 1: ");
3381 printf(
"failed to add segment 2: ");
3385 printf(
"failed to add segment 3: ");
3390 printf(
"failed to add segment 4: ");
3407 static int StreamTcpReassembleInlineTest03(
void)
3415 memset(&
tv, 0x00,
sizeof(
tv));
3425 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3428 printf(
"couldn't get a packet: ");
3431 p->
tcph->th_seq = htonl(12);
3436 printf(
"failed to add segment 1: ");
3440 printf(
"failed to add segment 2: ");
3444 printf(
"failed to add segment 3: ");
3449 printf(
"failed to add segment 4: ");
3454 p->
tcph->th_seq = htonl(17);
3468 static int StreamTcpReassembleInlineTest04(
void)
3476 memset(&
tv, 0x00,
sizeof(
tv));
3486 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3489 printf(
"couldn't get a packet: ");
3492 p->
tcph->th_seq = htonl(12);
3497 printf(
"failed to add segment 1: ");
3501 printf(
"failed to add segment 2: ");
3505 printf(
"failed to add segment 3: ");
3510 printf(
"failed to add segment 4: ");
3515 p->
tcph->th_seq = htonl(17);
3530 static int StreamTcpReassembleInlineTest08(
void)
3534 memset(&
tv, 0x00,
sizeof(
tv));
3546 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3549 p->
tcph->th_seq = htonl(12);
3559 p->
tcph->th_seq = htonl(17);
3578 static int StreamTcpReassembleInlineTest09(
void)
3586 memset(&
tv, 0x00,
sizeof(
tv));
3596 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3599 printf(
"couldn't get a packet: ");
3602 p->
tcph->th_seq = htonl(17);
3607 printf(
"failed to add segment 1: ");
3611 printf(
"failed to add segment 2: ");
3615 printf(
"failed to add segment 3: ");
3623 printf(
"failed to add segment 4: ");
3628 p->
tcph->th_seq = htonl(12);
3645 static int StreamTcpReassembleInlineTest10(
void)
3654 memset(&
tv, 0x00,
sizeof(
tv));
3665 f =
UTHBuildFlow(AF_INET,
"1.1.1.1",
"2.2.2.2", 1024, 80);
3669 f->
proto = IPPROTO_TCP;
3671 uint8_t stream_payload1[] =
"GE";
3672 uint8_t stream_payload2[] =
"T /";
3673 uint8_t stream_payload3[] =
"HTTP/1.0\r\n\r\n";
3675 p =
UTHBuildPacketReal(stream_payload3, 12, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
3677 printf(
"couldn't get a packet: ");
3680 p->
tcph->th_seq = htonl(7);
3685 printf(
"failed to add segment 1: ");
3692 printf(
"StreamTcpReassembleAppLayer failed: ");
3698 printf(
"expected ra_app_base_seq 1, got %u: ", ssn.
client.
base_seq);
3703 printf(
"failed to add segment 2: ");
3707 printf(
"failed to add segment 3: ");
3714 printf(
"StreamTcpReassembleAppLayer failed: ");
3731 static int StreamTcpReassembleInsertTest01(
void)
3738 memset(&
tv, 0x00,
sizeof(
tv));
3746 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3749 p->
tcph->th_seq = htonl(12);
3768 static int StreamTcpReassembleInsertTest02(
void)
3775 memset(&
tv, 0x00,
sizeof(
tv));
3782 for (i = 2; i < 10; i++) {
3793 printf(
"failed to add segment 1: ");
3798 printf(
"failed to add segment 2: ");
3811 static int StreamTcpReassembleInsertTest03(
void)
3818 memset(&
tv, 0x00,
sizeof(
tv));
3825 printf(
"failed to add segment 2: ");
3830 for (i = 2; i < 10; i++) {
3841 printf(
"failed to add segment 2: ");
3862 UtRegisterTest(
"StreamTcpReassembleTest25 -- Gap at Start Reassembly Test",
3863 StreamTcpReassembleTest25);
3864 UtRegisterTest(
"StreamTcpReassembleTest26 -- Gap at middle Reassembly Test",
3865 StreamTcpReassembleTest26);
3866 UtRegisterTest(
"StreamTcpReassembleTest27 -- Gap at after Reassembly Test",
3867 StreamTcpReassembleTest27);
3868 UtRegisterTest(
"StreamTcpReassembleTest28 -- Gap at Start IDS missed packet Reassembly Test",
3869 StreamTcpReassembleTest28);
3870 UtRegisterTest(
"StreamTcpReassembleTest29 -- Gap at Middle IDS missed packet Reassembly Test",
3871 StreamTcpReassembleTest29);
3873 StreamTcpReassembleTest33);
3875 StreamTcpReassembleTest34);
3877 StreamTcpReassembleTest39);
3879 StreamTcpReassembleTest40);
3881 StreamTcpReassembleTest44);
3883 StreamTcpReassembleTest45);
3885 StreamTcpReassembleTest46);
3886 UtRegisterTest(
"StreamTcpReassembleTest47 -- TCP Sequence Wraparound Test",
3887 StreamTcpReassembleTest47);
3889 UtRegisterTest(
"StreamTcpReassembleInlineTest01 -- inline RAW ra",
3890 StreamTcpReassembleInlineTest01);
3891 UtRegisterTest(
"StreamTcpReassembleInlineTest02 -- inline RAW ra 2",
3892 StreamTcpReassembleInlineTest02);
3893 UtRegisterTest(
"StreamTcpReassembleInlineTest03 -- inline RAW ra 3",
3894 StreamTcpReassembleInlineTest03);
3895 UtRegisterTest(
"StreamTcpReassembleInlineTest04 -- inline RAW ra 4",
3896 StreamTcpReassembleInlineTest04);
3897 UtRegisterTest(
"StreamTcpReassembleInlineTest08 -- inline RAW ra 8 cleanup",
3898 StreamTcpReassembleInlineTest08);
3899 UtRegisterTest(
"StreamTcpReassembleInlineTest09 -- inline RAW ra 9 GAP cleanup",
3900 StreamTcpReassembleInlineTest09);
3902 UtRegisterTest(
"StreamTcpReassembleInlineTest10 -- inline APP ra 10",
3903 StreamTcpReassembleInlineTest10);
3905 UtRegisterTest(
"StreamTcpReassembleInsertTest01 -- insert with overlap",
3906 StreamTcpReassembleInsertTest01);
3907 UtRegisterTest(
"StreamTcpReassembleInsertTest02 -- insert with overlap",
3908 StreamTcpReassembleInsertTest02);
3909 UtRegisterTest(
"StreamTcpReassembleInsertTest03 -- insert with overlap",
3910 StreamTcpReassembleInsertTest03);
3915 StreamTcpReassembleRawRegisterTests();