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)
225 if (size > orig_size) {
236 if (size > orig_size) {
247 static void ReassembleFree(
void *ptr,
size_t size)
254 static void *TcpSegmentPoolAlloc(
void)
278 "TcpSegmentPcapHdrStorage");
287 "packet header data within "
288 "TcpSegmentPcapHdrStorage");
303 static int TcpSegmentPoolInit(
void *data,
void *initdata)
331 segment_pool_memcnt++;
332 SCLogDebug(
"segment_pool_memcnt %"PRIu64
"", segment_pool_memcnt);
341 static void TcpSegmentPoolCleanup(
void *ptr)
362 segment_pool_memcnt--;
363 SCLogDebug(
"segment_pool_memcnt %"PRIu64
"", segment_pool_memcnt);
400 static inline uint64_t GetAbsLastAck(
const TcpStream *stream)
402 if (STREAM_LASTACK_GT_BASESEQ(stream)) {
411 return GetAbsLastAck(stream);
419 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
426 uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
428 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
470 static int StreamTcpReassemblyConfig(
bool quiet)
472 uint32_t segment_prealloc = 2048;
475 uint32_t prealloc = 0;
482 segment_prealloc = prealloc;
485 SCLogConfig(
"stream.reassembly \"segment-prealloc\": %u", segment_prealloc);
488 int overlap_diff_data = 0;
489 (void)
ConfGetBool(
"stream.reassembly.check-overlap-different-data", &overlap_diff_data);
490 if (overlap_diff_data) {
497 uint16_t max_regions = 8;
508 SCLogConfig(
"stream.reassembly \"max-regions\": %u", max_regions);
526 if (StreamTcpReassemblyConfig(quiet) < 0)
548 if (segment_pool_memuse > 0)
549 SCLogDebug(
"segment_pool_memuse %" PRIu64
"", segment_pool_memuse);
572 TcpSegmentPoolInit, NULL,
573 TcpSegmentPoolCleanup, NULL);
575 SCLogDebug(
"pool size %d, thread segment_thread_pool_id %d",
581 SCLogDebug(
"pool size %d, thread segment_thread_pool_id %d",
587 SCLogError(
"failed to setup/expand stream segment pool. Expand stream.reassembly.memcap?");
644 uint32_t
seq, uint32_t size)
662 SCLogDebug(
"segment entirely before base_seq, weird: base %u, seq %u, re %u",
676 SCLogDebug(
"seq + size %u, base %u, seg_depth %"PRIu64
" limit %u", (
seq + size),
681 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
685 SCLogDebug(
"NOT STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
688 SCLogDebug(
"full depth not yet reached: %"PRIu64
" <= %"PRIu32,
689 (stream->base_seq_offset + stream->
base_seq + size),
756 SCLogDebug(
"ssn %p: both app and raw reassembly disabled, not reassembling", ssn);
763 SCLogDebug(
"ssn %p: check depth returned %"PRIu32, ssn, size);
772 SCLogDebug(
"ssn %p: depth reached, not reassembling", ssn);
810 SCLogDebug(
"StreamTcpReassembleInsertSegment failed");
822 flag |= STREAM_START;
830 flag |= STREAM_MIDSTREAM;
837 if (&ssn->
client == stream) {
838 flag |= STREAM_TOSERVER;
840 flag |= STREAM_TOCLIENT;
843 flag |= STREAM_DEPTH;
854 static int StreamTcpReassembleRawCheckLimit(
const TcpSession *ssn,
860 #define STREAMTCP_STREAM_FLAG_FLUSH_FLAGS \
861 ( STREAMTCP_STREAM_FLAG_DEPTH_REACHED \
862 | STREAMTCP_STREAM_FLAG_TRIGGER_RAW \
863 | STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED)
867 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_DEPTH_REACHED "
868 "is set, so not expecting any new data segments");
871 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_TRIGGER_RAW is set");
874 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED is set, "
875 "so no new segments will be considered");
879 #undef STREAMTCP_STREAM_FLAG_FLUSH_FLAGS
888 const uint64_t last_ack_abs = GetAbsLastAck(stream);
894 if (chunk_size <= diff) {
897 SCLogDebug(
"%s min chunk len not yet reached: "
898 "last_ack %" PRIu32
", ra_raw_base_seq %" PRIu32
", %" PRIu32
" < "
915 const char *dirstr = NULL;
917 if (direction == STREAM_TOSERVER) {
941 const uint64_t right_edge =
943 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
944 " (use: %s). Stream right edge: %" PRIu64,
948 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
953 const uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
954 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
955 " (use: %s). Stream right edge: %" PRIu64,
959 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
964 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NONE", dirstr);
969 static uint64_t GetStreamSize(
TcpStream *stream)
974 uint64_t last_ack_abs = GetAbsLastAck(stream);
975 uint64_t last_re = 0;
981 const uint64_t seg_abs =
983 if (last_re != 0 && last_re < seg_abs) {
984 const char *gacked = NULL;
985 if (last_ack_abs >= seg_abs) {
986 gacked =
"fully ack'd";
987 }
else if (last_ack_abs > last_re) {
988 gacked =
"partly ack'd";
990 gacked =
"not yet ack'd";
992 SCLogDebug(
" -> gap of size %" PRIu64
", ack:%s", seg_abs - last_re, gacked);
995 const char *acked = NULL;
996 if (last_ack_abs >= seg_abs + (uint64_t)
TCP_SEG_LEN(seg)) {
997 acked =
"fully ack'd";
998 }
else if (last_ack_abs > seg_abs) {
999 acked =
"partly ack'd";
1001 acked =
"not yet ack'd";
1004 SCLogDebug(
"%u -> seg %p seq %u abs %" PRIu64
" size %u abs %" PRIu64
" (%" PRIu64
1013 SCLogDebug(
"size %"PRIu64
", cnt %"PRIu32, size, cnt);
1023 size = GetStreamSize(&ssn->
client);
1024 size += GetStreamSize(&ssn->
server);
1039 for ( ; blk != NULL; blk = SBB_RB_NEXT(blk)) {
1053 GetAbsLastAck(stream) > (cur_blk->
offset + cur_blk->
len)) {
1068 static bool GetAppBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1069 uint64_t
offset,
const bool check_for_gap)
1071 const uint8_t *mydata;
1072 uint32_t mydata_len;
1073 bool gap_ahead =
false;
1081 *data_len = mydata_len;
1099 gap_ahead = check_for_gap && GapAhead(stream, blk);
1103 SCLogDebug(
"gap, want data at offset %"PRIu64
", "
1104 "got data at %"PRIu64
". GAP of size %"PRIu64,
1111 SCLogDebug(
"get data from offset %"PRIu64
". SBB %"PRIu64
"/%u",
1114 SCLogDebug(
"data %p, data_len %u", *data, *data_len);
1116 gap_ahead = check_for_gap && GapAhead(stream, blk);
1135 const uint64_t last_ack_abs = GetAbsLastAck(stream) - (uint64_t)ackadded;
1142 if (last_ack_abs > app_progress) {
1149 "next_seq %u < last_ack %u, but no data in list",
1153 const uint64_t next_seq_abs =
1156 if (blk->
offset > next_seq_abs && blk->
offset < last_ack_abs) {
1159 "next_seq %u < last_ack %u, but ACK'd data beyond gap.",
1167 "last_ack_abs %" PRIu64
" > app_progress %" PRIu64
", "
1168 "but we have no data.",
1169 p->
pcap_cnt, last_ack_abs, app_progress);
1173 "last_ack_abs %"PRIu64
" <= app_progress %"PRIu64,
1174 p->
pcap_cnt, last_ack_abs, app_progress);
1178 static inline uint32_t AdjustToAcked(
const Packet *p,
1180 const uint64_t app_progress,
const uint32_t data_len)
1182 uint32_t adjusted = data_len;
1193 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1197 if (app_progress <= last_ack_abs && app_progress + data_len > last_ack_abs) {
1198 uint32_t check = data_len;
1199 adjusted = last_ack_abs - app_progress;
1200 BUG_ON(adjusted > check);
1201 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1202 "data is considered", adjusted);
1221 SCLogDebug(
"app progress %"PRIu64, app_progress);
1223 uint64_t last_ack_abs = GetAbsLastAck(*stream);
1224 SCLogDebug(
"last_ack %u (abs %" PRIu64
"), base_seq %u", (*stream)->last_ack, last_ack_abs,
1225 (*stream)->base_seq);
1227 const uint8_t *mydata;
1228 uint32_t mydata_len;
1229 bool last_was_gap =
false;
1232 const uint8_t
flags = StreamGetAppLayerFlags(ssn, *stream, p);
1233 bool check_for_gap_ahead = ((*stream)->data_required > 0);
1235 GetAppBuffer(*stream, &mydata, &mydata_len, app_progress, check_for_gap_ahead);
1237 if (last_was_gap && mydata_len == 0) {
1240 last_was_gap =
false;
1243 mydata_len = AdjustToAcked(p, ssn, *stream, app_progress, mydata_len);
1245 if (mydata == NULL && mydata_len > 0 && CheckGap(ssn, *stream, p)) {
1246 SCLogDebug(
"sending GAP to app-layer (size: %u)", mydata_len);
1250 StreamGetAppLayerFlags(ssn, *stream, p)|STREAM_GAP);
1251 AppLayerProfilingStore(ra_ctx->
app_tctx, p);
1264 if ((*stream)->data_required > 0) {
1265 if ((*stream)->data_required > mydata_len) {
1266 (*stream)->data_required -= mydata_len;
1268 (*stream)->data_required = 0;
1273 if (no_progress_update)
1275 last_was_gap =
true;
1278 }
else if (
flags & STREAM_DEPTH) {
1281 if (mydata == NULL && mydata_len > 0) {
1284 }
else if (mydata == NULL || (mydata_len == 0 && ((
flags & STREAM_EOF) == 0))) {
1297 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1298 *stream, &(*stream)->sb, mydata_len, app_progress);
1302 if (mydata_len < (*stream)->data_required) {
1305 SCLogDebug(
"GAP while expecting more data (expect %u, gap size %u)",
1306 (*stream)->data_required, mydata_len);
1307 (*stream)->app_progress_rel += mydata_len;
1308 (*stream)->data_required -= mydata_len;
1318 (*stream)->data_required = 0;
1323 (uint8_t *)mydata, mydata_len,
flags);
1324 AppLayerProfilingStore(ra_ctx->
app_tctx, p);
1329 app_progress = new_app_progress;
1330 if (
flags & STREAM_DEPTH)
1359 SCLogDebug(
"stream no reassembly flag set or app-layer disabled.");
1365 GetSessionSize(ssn, p);
1378 StreamGetAppLayerFlags(ssn, stream, p));
1379 AppLayerProfilingStore(ra_ctx->
app_tctx, p);
1386 return ReassembleUpdateAppLayer(
tv, ra_ctx, ssn, &stream, p, dir);
1392 static int GetRawBuffer(
TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1395 const uint8_t *mydata;
1396 uint32_t mydata_len;
1400 uint64_t roffset =
offset;
1408 *data_len = mydata_len;
1409 *data_offset = roffset;
1411 SCLogDebug(
"multiblob %s. Want offset %"PRIu64,
1412 *iter == NULL ?
"starting" :
"continuing",
offset);
1413 if (*iter == NULL) {
1418 if (*iter == NULL) {
1425 SCLogDebug(
"getting multiple blobs. Iter %p, %"PRIu64
"/%u", *iter, (*iter)->offset, (*iter)->len);
1430 if ((*iter)->offset <
offset) {
1431 uint64_t delta =
offset - (*iter)->offset;
1432 if (delta < mydata_len) {
1433 *data = mydata + delta;
1434 *data_len = mydata_len - delta;
1445 *data_len = mydata_len;
1446 *data_offset = (*iter)->offset;
1449 *iter = SBB_RB_NEXT(*iter);
1480 const uint64_t segs_re_abs =
1485 if (StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 1) {
1534 uint64_t tcp_window = stream->
window;
1544 }
else if (progress == 0) {
1545 uint64_t tcp_window = stream->
window;
1546 const uint64_t stream_right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
1547 if (tcp_window < stream_right_edge) {
1548 uint64_t new_raw = stream_right_edge - tcp_window;
1557 SCLogDebug(
"p->pcap_cnt %"PRIu64
": progress %"PRIu64
" app %"PRIu64
" raw %"PRIu64
" tcp win %"PRIu32,
1566 SCLogDebug(
"ssn %p: STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED set, "
1567 "now that detect ran also set STREAMTCP_STREAM_FLAG_DISABLE_RAW", ssn);
1613 SCLogDebug(
"packet payload len %u, so chunk_size adjusted to %u",
1615 }
else if (((chunk_size / 3 ) * 2) < p->
payload_len) {
1617 SCLogDebug(
"packet payload len %u, so chunk_size adjusted to %u",
1622 uint64_t packet_rightedge_abs = packet_leftedge_abs + p->
payload_len;
1623 SCLogDebug(
"packet_leftedge_abs %"PRIu64
", rightedge %"PRIu64,
1624 packet_leftedge_abs, packet_rightedge_abs);
1626 const uint8_t *mydata = NULL;
1627 uint32_t mydata_len = 0;
1628 uint64_t mydata_offset = 0;
1630 bool return_progress =
false;
1635 return_progress =
true;
1638 SCLogDebug(
"finding our SBB from offset %"PRIu64, packet_leftedge_abs);
1645 mydata_offset = sbb->
offset;
1650 uint64_t mydata_rightedge_abs = mydata_offset + mydata_len;
1651 if ((mydata == NULL || mydata_len == 0) ||
1652 (mydata_offset >= packet_rightedge_abs ||
1653 packet_leftedge_abs >= mydata_rightedge_abs) ||
1654 (packet_leftedge_abs < mydata_offset ||
1655 packet_rightedge_abs > mydata_rightedge_abs))
1660 mydata_offset = packet_leftedge_abs;
1664 SCLogDebug(
"chunk_size %u mydata_len %u", chunk_size, mydata_len);
1665 if (mydata_len > chunk_size) {
1666 uint32_t excess = mydata_len - chunk_size;
1667 SCLogDebug(
"chunk_size %u mydata_len %u excess %u", chunk_size, mydata_len, excess);
1669 if (mydata_rightedge_abs == packet_rightedge_abs) {
1671 mydata_len -= excess;
1672 mydata_offset += excess;
1673 SCLogDebug(
"cutting front of the buffer with %u", excess);
1674 }
else if (mydata_offset == packet_leftedge_abs) {
1675 mydata_len -= excess;
1676 SCLogDebug(
"cutting tail of the buffer with %u", excess);
1678 uint32_t before = (uint32_t)(packet_leftedge_abs - mydata_offset);
1679 uint32_t after = (uint32_t)(mydata_rightedge_abs - packet_rightedge_abs);
1680 SCLogDebug(
"before %u after %u", before, after);
1685 if (before >= (chunk_size - p->
payload_len) / 2) {
1687 before = after = (chunk_size - p->
payload_len) / 2;
1696 if (before >= (chunk_size - p->
payload_len) / 2) {
1704 uint32_t skip = (uint32_t)(packet_leftedge_abs - mydata_offset) - before;
1705 uint32_t cut = (uint32_t)(mydata_rightedge_abs - packet_rightedge_abs) - after;
1710 mydata_len -= (skip + cut);
1711 mydata_offset += skip;
1717 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1720 if (return_progress) {
1721 *progress_out = (mydata_offset + mydata_len);
1728 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1729 SCLogDebug(
"last_ack_abs %"PRIu64, last_ack_abs);
1732 if (mydata_offset > last_ack_abs) {
1734 *progress_out = last_ack_abs;
1736 *progress_out = (mydata_offset + mydata_len);
1779 const uint64_t re, uint64_t *progress_out,
bool eof,
bool respect_inspect_depth)
1785 uint64_t progress = progress_in;
1790 const uint8_t *mydata;
1791 uint32_t mydata_len;
1792 uint64_t mydata_offset = 0;
1794 GetRawBuffer(stream, &mydata, &mydata_len, &iter, progress, &mydata_offset);
1795 if (mydata_len == 0) {
1801 SCLogDebug(
"raw progress %"PRIu64, progress);
1802 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1803 stream, &stream->
sb, mydata_len, progress);
1808 if (re < progress) {
1813 SCLogDebug(
"re %" PRIu64
", raw_progress %" PRIu64, re, progress);
1814 SCLogDebug(
"raw_progress + mydata_len %" PRIu64
", re %" PRIu64, progress + mydata_len,
1818 if (progress + mydata_len > re) {
1819 uint32_t check = mydata_len;
1820 mydata_len = re - progress;
1821 BUG_ON(check < mydata_len);
1822 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1823 "data is considered", mydata_len);
1826 if (mydata_len == 0)
1829 SCLogDebug(
"data %p len %u", mydata, mydata_len);
1832 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1835 if (mydata_offset == progress) {
1836 SCLogDebug(
"progress %"PRIu64
" increasing with data len %u to %"PRIu64,
1837 progress, mydata_len, progress_in + mydata_len);
1839 progress += mydata_len;
1840 SCLogDebug(
"raw progress now %"PRIu64, progress);
1843 }
else if (mydata_offset > progress && mydata_offset < re) {
1844 SCLogDebug(
"GAP: data is missing from %"PRIu64
" (%u bytes), setting to first data we have: %"PRIu64, progress, (uint32_t)(mydata_offset - progress), mydata_offset);
1846 progress = mydata_offset;
1847 SCLogDebug(
"raw progress now %"PRIu64, progress);
1850 SCLogDebug(
"not increasing progress, data gap => mydata_offset "
1851 "%"PRIu64
" != progress %"PRIu64, mydata_offset, progress);
1854 if (iter == NULL || r == 1)
1858 *progress_out = progress;
1863 void *cb_data,
const uint64_t
offset,
const bool eof)
1867 SCLogDebug(
"app_progress %" PRIu64, app_progress);
1869 uint64_t unused = 0;
1870 return StreamReassembleRawDo(
1871 ssn, stream, Callback, cb_data,
offset, app_progress, &unused, eof,
false);
1876 uint64_t *progress_out,
bool respect_inspect_depth)
1880 return StreamReassembleRawInline(ssn, p, Callback, cb_data, progress_out);
1891 StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 0)
1903 SCLogDebug(
"respect_inspect_depth %s STREAMTCP_STREAM_FLAG_TRIGGER_RAW %s "
1904 "stream->min_inspect_depth %u",
1905 respect_inspect_depth ?
"true" :
"false",
1922 SCLogDebug(
"applied min inspect depth due to STREAMTCP_STREAM_FLAG_TRIGGER_RAW: progress "
1932 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1933 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1935 return StreamReassembleRawDo(ssn, stream, Callback, cb_data, progress, last_ack_abs,
1941 uint64_t progress_in,
1942 uint64_t *progress_out,
bool eof)
1948 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1949 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1951 return StreamReassembleRawDo(
1952 ssn, stream, Callback, cb_data, progress_in, last_ack_abs, progress_out, eof,
false);
1960 static int StreamTcpReassembleHandleSegmentUpdateACK (
ThreadVars *
tv,
1978 SCLogDebug(
"ssn %p, stream %p, p %p, p->payload_len %"PRIu16
"",
2005 if (stream == &ssn->
client) {
2006 opposing_stream = &ssn->
server;
2008 opposing_stream = &ssn->
client;
2013 if (StreamTcpReassembleHandleSegmentUpdateACK(
tv, ra_ctx, ssn, opposing_stream, p) != 0) {
2014 SCLogDebug(
"StreamTcpReassembleHandleSegmentUpdateACK error");
2022 if (reversed_before_ack_handling != reversed_after_ack_handling) {
2024 stream = opposing_stream;
2029 SCLogDebug(
"calling StreamTcpReassembleHandleSegmentHandleData");
2032 SCLogDebug(
"StreamTcpReassembleHandleSegmentHandleData error");
2042 SCLogDebug(
"ssn %p / stream %p: not calling StreamTcpReassembleHandleSegmentHandleData:"
2043 " p->payload_len %u, STREAMTCP_STREAM_FLAG_NOREASSEMBLY %s",
2054 if ((stream->
flags &
2058 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED, truncate applayer");
2060 SCLogDebug(
"override: direction now UPDATE_DIR_PACKET so we "
2061 "can trigger Truncate");
2069 SCLogDebug(
"inline (%s) or PKT_PSEUDO_STREAM_END (%s)",
2128 if (direction == STREAM_TOSERVER) {
2134 SCLogDebug(
"flagged ssn %p for immediate raw reassembly", ssn);
2145 if (direction == STREAM_TOSERVER) {
2147 SCLogDebug(
"ssn %p: set client.min_inspect_depth to %u", ssn, depth);
2150 SCLogDebug(
"ssn %p: set server.min_inspect_depth to %u", ssn, depth);
2158 #define SET_ISN(stream, setseq) \
2159 (stream)->isn = (setseq); \
2160 (stream)->base_seq = (setseq) + 1
2178 for (; i <
len; i++)
2202 data, data_len) == 0)
2211 #define MISSED_START(isn) \
2212 TcpReassemblyThreadCtx *ra_ctx = NULL; \
2215 memset(&tv, 0, sizeof(tv)); \
2217 StreamTcpUTInit(&ra_ctx); \
2219 StreamTcpUTSetupSession(&ssn); \
2220 StreamTcpUTSetupStream(&ssn.server, (isn)); \
2221 StreamTcpUTSetupStream(&ssn.client, (isn)); \
2223 TcpStream *stream = &ssn.client;
2225 #define MISSED_END \
2226 StreamTcpUTClearSession(&ssn); \
2227 StreamTcpUTDeinit(ra_ctx); \
2230 #define MISSED_STEP(seq, seg, seglen, buf, buflen) \
2231 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen)); \
2232 FAIL_IF(!(VALIDATE(stream, (uint8_t *)(buf), (buflen))));
2234 #define MISSED_ADD_PAYLOAD(seq, seg, seglen) \
2235 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen));
2242 uint64_t last_re = 0;
2246 if (sbb->
offset != last_re) {
2248 if (cnt == pos && last_re ==
offset &&
len == sbb->
offset - last_re) {
2266 uint64_t last_re = 0;
2270 if (sbb->
offset != last_re) {
2276 const uint8_t *buf = NULL;
2277 uint32_t buf_len = 0;
2280 if (
len == buf_len) {
2281 return (memcmp(data, buf,
len) == 0);
2298 static int StreamTcpReassembleTest25 (
void)
2319 static int StreamTcpReassembleTest26 (
void)
2338 static int StreamTcpReassembleTest27 (
void)
2355 static int StreamTcpReassembleTest28 (
void)
2379 static int StreamTcpReassembleTest29 (
void)
2391 static int StreamTcpReassembleTest33(
void)
2400 uint8_t packet[1460] =
"";
2405 memset(&f, 0,
sizeof (
Flow));
2406 memset(&tcph, 0,
sizeof (TCPHdr));
2411 f.
proto = IPPROTO_TCP;
2414 p->
proto = IPPROTO_TCP;
2422 p->
tcph->th_seq = htonl(10);
2423 p->
tcph->th_ack = htonl(31);
2428 p->
tcph->th_seq = htonl(20);
2429 p->
tcph->th_ack = htonl(31);
2434 p->
tcph->th_seq = htonl(40);
2435 p->
tcph->th_ack = htonl(31);
2440 p->
tcph->th_seq = htonl(5);
2441 p->
tcph->th_ack = htonl(31);
2452 static int StreamTcpReassembleTest34(
void)
2461 uint8_t packet[1460] =
"";
2465 memset(&f, 0,
sizeof (
Flow));
2466 memset(&tcph, 0,
sizeof (TCPHdr));
2471 f.
proto = IPPROTO_TCP;
2474 p->
proto = IPPROTO_TCP;
2483 p->
tcph->th_seq = htonl(857961230);
2484 p->
tcph->th_ack = htonl(31);
2489 p->
tcph->th_seq = htonl(857961534);
2490 p->
tcph->th_ack = htonl(31);
2495 p->
tcph->th_seq = htonl(857963582);
2496 p->
tcph->th_ack = htonl(31);
2501 p->
tcph->th_seq = htonl(857960946);
2502 p->
tcph->th_ack = htonl(31);
2521 static int StreamTcpReassembleTest39 (
void)
2531 memset (&f, 0,
sizeof(
Flow));
2533 memset(&stt, 0,
sizeof (stt));
2534 memset(&tcph, 0,
sizeof (TCPHdr));
2538 f.
proto = IPPROTO_TCP;
2545 tcph.th_win = htons(5480);
2570 p->
tcph->th_ack = htonl(1);
2591 p->
tcph->th_ack = htonl(1);
2592 p->
tcph->th_seq = htonl(1);
2613 uint8_t request1[] = { 0x47, 0x45, };
2614 p->
tcph->th_ack = htonl(1);
2615 p->
tcph->th_seq = htonl(1);
2637 p->
tcph->th_ack = htonl(3);
2638 p->
tcph->th_seq = htonl(1);
2660 uint8_t request2[] = {
2661 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
2662 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
2663 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
2664 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
2665 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
2666 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
2667 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
2668 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
2669 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
2670 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
2671 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
2672 p->
tcph->th_ack = htonl(1);
2673 p->
tcph->th_seq = htonl(3);
2696 uint8_t response[] = {
2697 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
2698 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
2699 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
2700 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
2701 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
2702 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
2703 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
2704 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
2705 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
2706 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
2707 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
2708 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
2709 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
2710 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
2711 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
2712 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
2713 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
2714 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
2715 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
2716 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
2717 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
2718 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
2719 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
2720 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
2721 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
2722 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
2723 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
2724 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
2725 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
2726 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
2727 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
2728 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
2729 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
2730 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
2731 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
2732 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
2733 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
2734 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
2735 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
2736 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
2737 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
2738 p->
tcph->th_ack = htonl(88);
2739 p->
tcph->th_seq = htonl(1);
2763 p->
tcph->th_ack = htonl(328);
2764 p->
tcph->th_seq = htonl(88);
2788 p->
tcph->th_ack = htonl(88);
2789 p->
tcph->th_seq = htonl(328);
2813 p->
tcph->th_ack = htonl(328);
2814 p->
tcph->th_seq = htonl(88);
2837 p->
tcph->th_ack = htonl(88);
2838 p->
tcph->th_seq = htonl(328);
2863 p->
tcph->th_ack = htonl(328);
2864 p->
tcph->th_seq = htonl(88);
2888 p->
tcph->th_ack = htonl(90);
2889 p->
tcph->th_seq = htonl(328);
2914 p->
tcph->th_ack = htonl(328);
2915 p->
tcph->th_seq = htonl(90);
2940 p->
tcph->th_ack = htonl(175);
2941 p->
tcph->th_seq = htonl(328);
2967 p->
tcph->th_ack = htonl(175);
2968 p->
tcph->th_seq = htonl(328);
2984 p->
tcph->th_ack = htonl(328);
2985 p->
tcph->th_seq = htonl(175);
3005 static int StreamTcpReassembleTest40 (
void)
3012 memset(&tcph, 0,
sizeof (TCPHdr));
3022 uint8_t httpbuf1[] =
"P";
3023 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3024 uint8_t httpbuf3[] =
"O";
3025 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
3026 uint8_t httpbuf4[] =
"S";
3027 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
3028 uint8_t httpbuf5[] =
"T \r\n";
3029 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
3031 uint8_t httpbuf2[] =
"HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
3032 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3039 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3042 f->
proto = IPPROTO_TCP;
3045 tcph.th_win = htons(5480);
3046 tcph.th_seq = htonl(10);
3047 tcph.th_ack = htonl(10);
3061 tcph.th_seq = htonl(10);
3062 tcph.th_ack = htonl(11);
3071 tcph.th_seq = htonl(11);
3072 tcph.th_ack = htonl(55);
3081 tcph.th_seq = htonl(55);
3082 tcph.th_ack = htonl(12);
3096 tcph.th_seq = htonl(12);
3097 tcph.th_ack = htonl(100);
3106 tcph.th_seq = htonl(100);
3107 tcph.th_ack = htonl(13);
3116 tcph.th_seq = htonl(13);
3117 tcph.th_ack = htonl(145);
3126 tcph.th_seq = htonl(145);
3127 tcph.th_ack = htonl(16);
3143 static int StreamTcpReassembleTest44(
void)
3164 static int StreamTcpReassembleTest45 (
void)
3169 memset(&
tv, 0,
sizeof(
tv));
3170 uint8_t payload[100] = {0};
3171 uint16_t payload_size = 100;
3202 static int StreamTcpReassembleTest46 (
void)
3208 memset(&
tv, 0,
sizeof(
tv));
3209 uint8_t payload[100] = {0};
3210 uint16_t payload_size = 100;
3223 printf(
"STREAMTCP_STREAM_FLAG_NOREASSEMBLY set: ");
3231 printf(
"STREAMTCP_STREAM_FLAG_NOREASSEMBLY set: ");
3251 static int StreamTcpReassembleTest47 (
void)
3259 memset(&tcph, 0,
sizeof (TCPHdr));
3265 uint8_t httpbuf1[] =
"GET /EVILSUFF HTTP/1.1\r\n\r\n";
3266 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3274 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3277 f->
proto = IPPROTO_TCP;
3280 tcph.th_win = htons(5480);
3285 for (cnt=0; cnt < httplen1; cnt++) {
3286 tcph.th_seq = htonl(ssn.
client.
isn + 1 + cnt);
3287 tcph.th_ack = htonl(572799782UL);
3300 tcph.th_seq = htonl(572799782UL);
3301 tcph.th_ack = htonl(ssn.
client.
isn + 1 + cnt);
3320 static int StreamTcpReassembleInlineTest01(
void)
3328 memset(&
tv, 0x00,
sizeof(
tv));
3336 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3339 printf(
"couldn't get a packet: ");
3342 p->
tcph->th_seq = htonl(12);
3346 printf(
"failed to add segment 1: ");
3350 printf(
"failed to add segment 2: ");
3354 printf(
"failed to add segment 3: ");
3370 static int StreamTcpReassembleInlineTest02(
void)
3378 memset(&
tv, 0x00,
sizeof(
tv));
3386 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3389 printf(
"couldn't get a packet: ");
3392 p->
tcph->th_seq = htonl(12);
3396 printf(
"failed to add segment 1: ");
3400 printf(
"failed to add segment 2: ");
3404 printf(
"failed to add segment 3: ");
3409 printf(
"failed to add segment 4: ");
3426 static int StreamTcpReassembleInlineTest03(
void)
3434 memset(&
tv, 0x00,
sizeof(
tv));
3444 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3447 printf(
"couldn't get a packet: ");
3450 p->
tcph->th_seq = htonl(12);
3455 printf(
"failed to add segment 1: ");
3459 printf(
"failed to add segment 2: ");
3463 printf(
"failed to add segment 3: ");
3468 printf(
"failed to add segment 4: ");
3473 p->
tcph->th_seq = htonl(17);
3487 static int StreamTcpReassembleInlineTest04(
void)
3495 memset(&
tv, 0x00,
sizeof(
tv));
3505 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3508 printf(
"couldn't get a packet: ");
3511 p->
tcph->th_seq = htonl(12);
3516 printf(
"failed to add segment 1: ");
3520 printf(
"failed to add segment 2: ");
3524 printf(
"failed to add segment 3: ");
3529 printf(
"failed to add segment 4: ");
3534 p->
tcph->th_seq = htonl(17);
3549 static int StreamTcpReassembleInlineTest08(
void)
3553 memset(&
tv, 0x00,
sizeof(
tv));
3565 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3568 p->
tcph->th_seq = htonl(12);
3578 p->
tcph->th_seq = htonl(17);
3597 static int StreamTcpReassembleInlineTest09(
void)
3605 memset(&
tv, 0x00,
sizeof(
tv));
3615 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3618 printf(
"couldn't get a packet: ");
3621 p->
tcph->th_seq = htonl(17);
3626 printf(
"failed to add segment 1: ");
3630 printf(
"failed to add segment 2: ");
3634 printf(
"failed to add segment 3: ");
3642 printf(
"failed to add segment 4: ");
3647 p->
tcph->th_seq = htonl(12);
3664 static int StreamTcpReassembleInlineTest10(
void)
3673 memset(&
tv, 0x00,
sizeof(
tv));
3684 f =
UTHBuildFlow(AF_INET,
"1.1.1.1",
"2.2.2.2", 1024, 80);
3688 f->
proto = IPPROTO_TCP;
3690 uint8_t stream_payload1[] =
"GE";
3691 uint8_t stream_payload2[] =
"T /";
3692 uint8_t stream_payload3[] =
"HTTP/1.0\r\n\r\n";
3694 p =
UTHBuildPacketReal(stream_payload3, 12, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
3696 printf(
"couldn't get a packet: ");
3699 p->
tcph->th_seq = htonl(7);
3704 printf(
"failed to add segment 1: ");
3711 printf(
"StreamTcpReassembleAppLayer failed: ");
3717 printf(
"expected ra_app_base_seq 1, got %u: ", ssn.
client.
base_seq);
3722 printf(
"failed to add segment 2: ");
3726 printf(
"failed to add segment 3: ");
3733 printf(
"StreamTcpReassembleAppLayer failed: ");
3750 static int StreamTcpReassembleInsertTest01(
void)
3757 memset(&
tv, 0x00,
sizeof(
tv));
3765 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3768 p->
tcph->th_seq = htonl(12);
3787 static int StreamTcpReassembleInsertTest02(
void)
3794 memset(&
tv, 0x00,
sizeof(
tv));
3801 for (i = 2; i < 10; i++) {
3812 printf(
"failed to add segment 1: ");
3817 printf(
"failed to add segment 2: ");
3830 static int StreamTcpReassembleInsertTest03(
void)
3837 memset(&
tv, 0x00,
sizeof(
tv));
3844 printf(
"failed to add segment 2: ");
3849 for (i = 2; i < 10; i++) {
3860 printf(
"failed to add segment 2: ");
3881 UtRegisterTest(
"StreamTcpReassembleTest25 -- Gap at Start Reassembly Test",
3882 StreamTcpReassembleTest25);
3883 UtRegisterTest(
"StreamTcpReassembleTest26 -- Gap at middle Reassembly Test",
3884 StreamTcpReassembleTest26);
3885 UtRegisterTest(
"StreamTcpReassembleTest27 -- Gap at after Reassembly Test",
3886 StreamTcpReassembleTest27);
3887 UtRegisterTest(
"StreamTcpReassembleTest28 -- Gap at Start IDS missed packet Reassembly Test",
3888 StreamTcpReassembleTest28);
3889 UtRegisterTest(
"StreamTcpReassembleTest29 -- Gap at Middle IDS missed packet Reassembly Test",
3890 StreamTcpReassembleTest29);
3892 StreamTcpReassembleTest33);
3894 StreamTcpReassembleTest34);
3896 StreamTcpReassembleTest39);
3898 StreamTcpReassembleTest40);
3900 StreamTcpReassembleTest44);
3902 StreamTcpReassembleTest45);
3904 StreamTcpReassembleTest46);
3905 UtRegisterTest(
"StreamTcpReassembleTest47 -- TCP Sequence Wraparound Test",
3906 StreamTcpReassembleTest47);
3908 UtRegisterTest(
"StreamTcpReassembleInlineTest01 -- inline RAW ra",
3909 StreamTcpReassembleInlineTest01);
3910 UtRegisterTest(
"StreamTcpReassembleInlineTest02 -- inline RAW ra 2",
3911 StreamTcpReassembleInlineTest02);
3912 UtRegisterTest(
"StreamTcpReassembleInlineTest03 -- inline RAW ra 3",
3913 StreamTcpReassembleInlineTest03);
3914 UtRegisterTest(
"StreamTcpReassembleInlineTest04 -- inline RAW ra 4",
3915 StreamTcpReassembleInlineTest04);
3916 UtRegisterTest(
"StreamTcpReassembleInlineTest08 -- inline RAW ra 8 cleanup",
3917 StreamTcpReassembleInlineTest08);
3918 UtRegisterTest(
"StreamTcpReassembleInlineTest09 -- inline RAW ra 9 GAP cleanup",
3919 StreamTcpReassembleInlineTest09);
3921 UtRegisterTest(
"StreamTcpReassembleInlineTest10 -- inline APP ra 10",
3922 StreamTcpReassembleInlineTest10);
3924 UtRegisterTest(
"StreamTcpReassembleInsertTest01 -- insert with overlap",
3925 StreamTcpReassembleInsertTest01);
3926 UtRegisterTest(
"StreamTcpReassembleInsertTest02 -- insert with overlap",
3927 StreamTcpReassembleInsertTest02);
3928 UtRegisterTest(
"StreamTcpReassembleInsertTest03 -- insert with overlap",
3929 StreamTcpReassembleInsertTest03);
3934 StreamTcpReassembleRawRegisterTests();