75 static SCMutex segment_pool_memuse_mutex;
76 static uint64_t segment_pool_memuse = 0;
77 static uint64_t segment_pool_memcnt = 0;
89 static int g_tcp_session_dump_enabled = 0;
93 return g_tcp_session_dump_enabled == 1;
98 g_tcp_session_dump_enabled = 1;
134 BUG_ON(presize > UINT_MAX);
143 BUG_ON(postsize > presize);
167 if (
unlikely((g_eps_stream_reassembly_memcap != UINT64_MAX &&
168 g_eps_stream_reassembly_memcap ==
t_pcapcnt))) {
174 if (memcapcopy == 0 ||
175 (uint64_t)((uint64_t)size +
SC_ATOMIC_GET(ra_memuse)) <= memcapcopy)
187 if (size == 0 || (uint64_t)
SC_ATOMIC_GET(ra_memuse) < size) {
211 static void *ReassembleCalloc(
size_t n,
size_t size)
231 if (size > orig_size) {
244 if (size > orig_size) {
255 static void ReassembleFree(
void *ptr,
size_t size)
262 static void *TcpSegmentPoolAlloc(
void)
286 "TcpSegmentPcapHdrStorage");
295 "packet header data within "
296 "TcpSegmentPcapHdrStorage");
311 static int TcpSegmentPoolInit(
void *data,
void *initdata)
339 segment_pool_memcnt++;
340 SCLogDebug(
"segment_pool_memcnt %"PRIu64
"", segment_pool_memcnt);
349 static void TcpSegmentPoolCleanup(
void *ptr)
370 segment_pool_memcnt--;
371 SCLogDebug(
"segment_pool_memcnt %"PRIu64
"", segment_pool_memcnt);
408 static inline uint64_t GetAbsLastAck(
const TcpStream *stream)
410 if (STREAM_LASTACK_GT_BASESEQ(stream)) {
422 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
429 uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
431 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
473 static int StreamTcpReassemblyConfig(
bool quiet)
475 uint32_t segment_prealloc = 2048;
478 uint32_t prealloc = 0;
485 segment_prealloc = prealloc;
488 SCLogConfig(
"stream.reassembly \"segment-prealloc\": %u", segment_prealloc);
491 int overlap_diff_data = 0;
492 (void)
ConfGetBool(
"stream.reassembly.check-overlap-different-data", &overlap_diff_data);
493 if (overlap_diff_data) {
500 uint16_t max_regions = 8;
511 SCLogConfig(
"stream.reassembly \"max-regions\": %u", max_regions);
529 if (StreamTcpReassemblyConfig(quiet) < 0)
551 if (segment_pool_memuse > 0)
552 SCLogDebug(
"segment_pool_memuse %" PRIu64
" segment_pool_memcnt %" PRIu64
"",
553 segment_pool_memuse, segment_pool_memcnt);
574 TcpSegmentPoolInit, NULL,
575 TcpSegmentPoolCleanup, NULL);
577 SCLogDebug(
"pool size %d, thread segment_thread_pool_id %d",
583 SCLogDebug(
"pool size %d, thread segment_thread_pool_id %d",
589 SCLogError(
"failed to setup/expand stream segment pool. Expand stream.reassembly.memcap?");
609 static void StreamTcpReassembleExceptionPolicyStatsIncr(
655 uint32_t
seq, uint32_t size)
673 SCLogDebug(
"segment entirely before base_seq, weird: base %u, seq %u, re %u",
687 SCLogDebug(
"seq + size %u, base %u, seg_depth %"PRIu64
" limit %u", (
seq + size),
692 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
696 SCLogDebug(
"NOT STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
699 SCLogDebug(
"full depth not yet reached: %"PRIu64
" <= %"PRIu32,
700 (stream->base_seq_offset + stream->
base_seq + size),
767 SCLogDebug(
"ssn %p: both app and raw reassembly disabled, not reassembling", ssn);
771 uint16_t *urg_offset;
778 const TCPHdr *tcph = PacketGetTCP(p);
782 uint8_t urg_data = 0;
792 if ((*urg_offset) < UINT16_MAX) {
796 if ((*urg_offset) == UINT16_MAX) {
813 (*urg_offset) == UINT16_MAX &&
829 uint32_t size = StreamTcpReassembleCheckDepth(ssn, stream, seg_seq,
payload_len);
830 SCLogDebug(
"ssn %p: check depth returned %"PRIu32, ssn, size);
839 SCLogDebug(
"ssn %p: depth reached, not reassembling", ssn);
877 SCLogDebug(
"StreamTcpReassembleInsertSegment failed");
889 flag |= STREAM_START;
897 flag |= STREAM_MIDSTREAM;
904 if (&ssn->
client == stream) {
905 flag |= STREAM_TOSERVER;
907 flag |= STREAM_TOCLIENT;
910 flag |= STREAM_DEPTH;
921 static int StreamTcpReassembleRawCheckLimit(
const TcpSession *ssn,
927 #define STREAMTCP_STREAM_FLAG_FLUSH_FLAGS \
928 ( STREAMTCP_STREAM_FLAG_DEPTH_REACHED \
929 | STREAMTCP_STREAM_FLAG_TRIGGER_RAW \
930 | STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED)
934 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_DEPTH_REACHED "
935 "is set, so not expecting any new data segments");
938 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_TRIGGER_RAW is set");
941 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED is set, "
942 "so no new segments will be considered");
946 #undef STREAMTCP_STREAM_FLAG_FLUSH_FLAGS
955 const uint64_t last_ack_abs = GetAbsLastAck(stream);
961 if (chunk_size <= diff) {
964 SCLogDebug(
"%s min chunk len not yet reached: "
965 "last_ack %" PRIu32
", ra_raw_base_seq %" PRIu32
", %" PRIu32
" < "
982 const char *dirstr = NULL;
984 if (direction == STREAM_TOSERVER) {
1008 const uint64_t right_edge =
1010 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
1011 " (use: %s). Stream right edge: %" PRIu64,
1015 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
1020 const uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
1021 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
1022 " (use: %s). Stream right edge: %" PRIu64,
1026 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
1031 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NONE", dirstr);
1036 static uint64_t GetStreamSize(
TcpStream *stream)
1041 uint64_t last_ack_abs = GetAbsLastAck(stream);
1042 uint64_t last_re = 0;
1048 const uint64_t seg_abs =
1050 if (last_re != 0 && last_re < seg_abs) {
1051 const char *gacked = NULL;
1052 if (last_ack_abs >= seg_abs) {
1053 gacked =
"fully ack'd";
1054 }
else if (last_ack_abs > last_re) {
1055 gacked =
"partly ack'd";
1057 gacked =
"not yet ack'd";
1059 SCLogDebug(
" -> gap of size %" PRIu64
", ack:%s", seg_abs - last_re, gacked);
1062 const char *acked = NULL;
1063 if (last_ack_abs >= seg_abs + (uint64_t)
TCP_SEG_LEN(seg)) {
1064 acked =
"fully ack'd";
1065 }
else if (last_ack_abs > seg_abs) {
1066 acked =
"partly ack'd";
1068 acked =
"not yet ack'd";
1071 SCLogDebug(
"%u -> seg %p seq %u abs %" PRIu64
" size %u abs %" PRIu64
" (%" PRIu64
1090 size = GetStreamSize(&ssn->
client);
1091 size += GetStreamSize(&ssn->
server);
1104 GetAbsLastAck(stream) > (cur_blk->
offset + cur_blk->
len)) {
1119 static bool GetAppBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1120 uint64_t
offset,
const bool check_for_gap)
1122 const uint8_t *mydata;
1123 uint32_t mydata_len;
1124 bool gap_ahead =
false;
1132 *data_len = mydata_len;
1151 gap_ahead = check_for_gap && GapAhead(stream, blk);
1155 SCLogDebug(
"gap, want data at offset %"PRIu64
", "
1156 "got data at %"PRIu64
". GAP of size %"PRIu64,
1163 SCLogDebug(
"get data from offset %"PRIu64
". SBB %"PRIu64
"/%u",
1166 SCLogDebug(
"data %p, data_len %u", *data, *data_len);
1168 gap_ahead = check_for_gap && GapAhead(stream, blk);
1187 const uint64_t last_ack_abs = GetAbsLastAck(stream) - (uint64_t)ackadded;
1194 if (last_ack_abs > app_progress) {
1201 "next_seq %u < last_ack %u, but no data in list",
1205 const uint64_t next_seq_abs =
1208 if (blk->
offset > next_seq_abs && blk->
offset < last_ack_abs) {
1211 "next_seq %u < last_ack %u, but ACK'd data beyond gap.",
1219 "last_ack_abs %" PRIu64
" > app_progress %" PRIu64
", "
1220 "but we have no data.",
1221 p->
pcap_cnt, last_ack_abs, app_progress);
1225 "last_ack_abs %"PRIu64
" <= app_progress %"PRIu64,
1226 p->
pcap_cnt, last_ack_abs, app_progress);
1230 static inline uint32_t AdjustToAcked(
const Packet *p,
1232 const uint64_t app_progress,
const uint32_t data_len)
1234 uint32_t adjusted = data_len;
1245 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1249 if (app_progress <= last_ack_abs && app_progress + data_len > last_ack_abs) {
1250 uint32_t check = data_len;
1251 adjusted = (uint32_t)(last_ack_abs - app_progress);
1252 BUG_ON(adjusted > check);
1253 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1254 "data is considered", adjusted);
1271 SCLogDebug(
"app progress %"PRIu64, app_progress);
1273 uint64_t last_ack_abs = GetAbsLastAck(*stream);
1274 SCLogDebug(
"last_ack %u (abs %" PRIu64
"), base_seq %u", (*stream)->last_ack, last_ack_abs,
1275 (*stream)->base_seq);
1277 const uint8_t *mydata;
1278 uint32_t mydata_len;
1279 bool last_was_gap =
false;
1282 const uint8_t
flags = StreamGetAppLayerFlags(ssn, *stream, p);
1283 bool check_for_gap_ahead = ((*stream)->data_required > 0);
1285 GetAppBuffer(*stream, &mydata, &mydata_len, app_progress, check_for_gap_ahead);
1287 if (last_was_gap && mydata_len == 0) {
1290 last_was_gap =
false;
1293 mydata_len = AdjustToAcked(p, ssn, *stream, app_progress, mydata_len);
1295 if (mydata == NULL && mydata_len > 0 && CheckGap(ssn, *stream, p)) {
1296 SCLogDebug(
"sending GAP to app-layer (size: %u)", mydata_len);
1299 StreamGetAppLayerFlags(ssn, *stream, p) | STREAM_GAP, app_update_dir);
1313 if ((*stream)->data_required > 0) {
1314 if ((*stream)->data_required > mydata_len) {
1315 (*stream)->data_required -= mydata_len;
1317 (*stream)->data_required = 0;
1322 if (no_progress_update)
1324 last_was_gap =
true;
1327 }
else if (
flags & STREAM_DEPTH) {
1330 if (mydata == NULL && mydata_len > 0) {
1333 }
else if (mydata == NULL || (mydata_len == 0 && ((
flags & STREAM_EOF) == 0))) {
1346 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1347 *stream, &(*stream)->sb, mydata_len, app_progress);
1351 if (mydata_len < (*stream)->data_required) {
1354 SCLogDebug(
"GAP while expecting more data (expect %u, gap size %u)",
1355 (*stream)->data_required, mydata_len);
1356 (*stream)->app_progress_rel += mydata_len;
1357 (*stream)->data_required -= mydata_len;
1367 (*stream)->data_required = 0;
1372 mydata_len,
flags, app_update_dir);
1378 app_progress = new_app_progress;
1379 if (
flags & STREAM_DEPTH)
1407 SCLogDebug(
"stream no reassembly flag set or app-layer disabled.");
1413 GetSessionSize(ssn, p);
1425 StreamGetAppLayerFlags(ssn, stream, p), app_update_dir);
1433 return ReassembleUpdateAppLayer(
tv, ra_ctx, ssn, &stream, p, app_update_dir);
1439 static int GetRawBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1442 const uint8_t *mydata;
1443 uint32_t mydata_len;
1447 uint64_t roffset =
offset;
1455 *data_len = mydata_len;
1456 *data_offset = roffset;
1458 SCLogDebug(
"multiblob %s. Want offset %"PRIu64,
1459 *iter == NULL ?
"starting" :
"continuing",
offset);
1460 if (*iter == NULL) {
1465 if (*iter == NULL) {
1472 SCLogDebug(
"getting multiple blobs. Iter %p, %"PRIu64
"/%u", *iter, (*iter)->offset, (*iter)->len);
1477 if ((*iter)->offset <
offset) {
1478 uint64_t delta =
offset - (*iter)->offset;
1479 if (delta < mydata_len) {
1480 *data = mydata + delta;
1481 *data_len = (uint32_t)(mydata_len - delta);
1492 *data_len = mydata_len;
1493 *data_offset = (*iter)->offset;
1496 *iter = SBB_RB_NEXT(*iter);
1527 const uint64_t segs_re_abs =
1532 if (StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 1) {
1570 }
else if (progress == 0) {
1575 target = GetAbsLastAck(stream);
1585 SCLogDebug(
"p->pcap_cnt %"PRIu64
": progress %"PRIu64
" app %"PRIu64
" raw %"PRIu64
" tcp win %"PRIu32,
1594 SCLogDebug(
"ssn %p: STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED set, "
1595 "now that detect ran also set STREAMTCP_STREAM_FLAG_DISABLE_RAW", ssn);
1641 SCLogDebug(
"packet payload len %u, so chunk_size adjusted to %u",
1643 }
else if (((chunk_size / 3 ) * 2) < p->
payload_len) {
1645 SCLogDebug(
"packet payload len %u, so chunk_size adjusted to %u",
1649 const TCPHdr *tcph = PacketGetTCP(p);
1650 uint64_t packet_leftedge_abs =
1652 uint64_t packet_rightedge_abs = packet_leftedge_abs + p->
payload_len;
1653 SCLogDebug(
"packet_leftedge_abs %"PRIu64
", rightedge %"PRIu64,
1654 packet_leftedge_abs, packet_rightedge_abs);
1656 const uint8_t *mydata = NULL;
1657 uint32_t mydata_len = 0;
1658 uint64_t mydata_offset = 0;
1660 bool return_progress =
false;
1665 return_progress =
true;
1668 SCLogDebug(
"finding our SBB from offset %"PRIu64, packet_leftedge_abs);
1675 mydata_offset = sbb->
offset;
1680 uint64_t mydata_rightedge_abs = mydata_offset + mydata_len;
1681 if ((mydata == NULL || mydata_len == 0) ||
1682 (mydata_offset >= packet_rightedge_abs ||
1683 packet_leftedge_abs >= mydata_rightedge_abs) ||
1684 (packet_leftedge_abs < mydata_offset ||
1685 packet_rightedge_abs > mydata_rightedge_abs))
1690 mydata_offset = packet_leftedge_abs;
1694 SCLogDebug(
"chunk_size %u mydata_len %u", chunk_size, mydata_len);
1695 if (mydata_len > chunk_size) {
1696 uint32_t excess = mydata_len - chunk_size;
1697 SCLogDebug(
"chunk_size %u mydata_len %u excess %u", chunk_size, mydata_len, excess);
1699 if (mydata_rightedge_abs == packet_rightedge_abs) {
1701 mydata_len -= excess;
1702 mydata_offset += excess;
1703 SCLogDebug(
"cutting front of the buffer with %u", excess);
1704 }
else if (mydata_offset == packet_leftedge_abs) {
1705 mydata_len -= excess;
1706 SCLogDebug(
"cutting tail of the buffer with %u", excess);
1708 uint32_t before = (uint32_t)(packet_leftedge_abs - mydata_offset);
1709 uint32_t after = (uint32_t)(mydata_rightedge_abs - packet_rightedge_abs);
1710 SCLogDebug(
"before %u after %u", before, after);
1715 if (before >= (chunk_size - p->
payload_len) / 2) {
1717 before = after = (chunk_size - p->
payload_len) / 2;
1726 if (before >= (chunk_size - p->
payload_len) / 2) {
1734 uint32_t skip = (uint32_t)(packet_leftedge_abs - mydata_offset) - before;
1735 uint32_t cut = (uint32_t)(mydata_rightedge_abs - packet_rightedge_abs) - after;
1740 mydata_len -= (skip + cut);
1741 mydata_offset += skip;
1747 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1750 if (return_progress) {
1751 *progress_out = (mydata_offset + mydata_len);
1758 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1759 SCLogDebug(
"last_ack_abs %"PRIu64, last_ack_abs);
1762 if (mydata_offset > last_ack_abs) {
1764 *progress_out = last_ack_abs;
1766 *progress_out = (mydata_offset + mydata_len);
1809 const uint64_t re, uint64_t *progress_out,
bool eof,
bool respect_inspect_depth)
1815 uint64_t progress = progress_in;
1820 const uint8_t *mydata;
1821 uint32_t mydata_len;
1822 uint64_t mydata_offset = 0;
1824 GetRawBuffer(stream, &mydata, &mydata_len, &iter, progress, &mydata_offset);
1825 if (mydata_len == 0) {
1831 SCLogDebug(
"raw progress %"PRIu64, progress);
1832 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1833 stream, &stream->
sb, mydata_len, progress);
1838 if (re < progress) {
1843 SCLogDebug(
"re %" PRIu64
", raw_progress %" PRIu64, re, progress);
1844 SCLogDebug(
"raw_progress + mydata_len %" PRIu64
", re %" PRIu64, progress + mydata_len,
1848 if (progress + mydata_len > re) {
1849 uint32_t check = mydata_len;
1850 mydata_len = (uint32_t)(re - progress);
1851 BUG_ON(check < mydata_len);
1852 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1853 "data is considered", mydata_len);
1856 if (mydata_len == 0)
1859 SCLogDebug(
"data %p len %u", mydata, mydata_len);
1862 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1865 if (mydata_offset == progress) {
1866 SCLogDebug(
"progress %"PRIu64
" increasing with data len %u to %"PRIu64,
1867 progress, mydata_len, progress_in + mydata_len);
1869 progress += mydata_len;
1870 SCLogDebug(
"raw progress now %"PRIu64, progress);
1873 }
else if (mydata_offset > progress && mydata_offset < re) {
1874 SCLogDebug(
"GAP: data is missing from %"PRIu64
" (%u bytes), setting to first data we have: %"PRIu64, progress, (uint32_t)(mydata_offset - progress), mydata_offset);
1876 progress = mydata_offset;
1877 SCLogDebug(
"raw progress now %"PRIu64, progress);
1880 SCLogDebug(
"not increasing progress, data gap => mydata_offset "
1881 "%"PRIu64
" != progress %"PRIu64, mydata_offset, progress);
1884 if (iter == NULL || r == 1)
1888 *progress_out = progress;
1893 void *cb_data,
const uint64_t
offset,
const bool eof)
1897 SCLogDebug(
"app_progress %" PRIu64, app_progress);
1899 uint64_t unused = 0;
1900 return StreamReassembleRawDo(
1901 ssn, stream, Callback, cb_data,
offset, app_progress, &unused, eof,
false);
1906 uint64_t *progress_out,
bool respect_inspect_depth)
1910 return StreamReassembleRawInline(ssn, p, Callback, cb_data, progress_out);
1921 StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 0)
1933 SCLogDebug(
"respect_inspect_depth %s STREAMTCP_STREAM_FLAG_TRIGGER_RAW %s "
1934 "stream->min_inspect_depth %u",
1935 respect_inspect_depth ?
"true" :
"false",
1952 SCLogDebug(
"applied min inspect depth due to STREAMTCP_STREAM_FLAG_TRIGGER_RAW: progress "
1962 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1963 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1965 return StreamReassembleRawDo(ssn, stream, Callback, cb_data, progress, last_ack_abs,
1971 uint64_t *progress_out,
const bool eof)
1977 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1978 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1980 return StreamReassembleRawDo(
1981 ssn, stream, Callback, cb_data, progress_in, last_ack_abs, progress_out, eof,
false);
1989 static int StreamTcpReassembleHandleSegmentUpdateACK (
ThreadVars *
tv,
2006 const TCPHdr *tcph = PacketGetTCP(p);
2008 SCLogDebug(
"ssn %p, stream %p, p %p, p->payload_len %"PRIu16
"",
2038 if (stream == &ssn->
client) {
2039 opposing_stream = &ssn->
server;
2041 opposing_stream = &ssn->
client;
2046 if (StreamTcpReassembleHandleSegmentUpdateACK(
tv, ra_ctx, ssn, opposing_stream, p) != 0) {
2047 SCLogDebug(
"StreamTcpReassembleHandleSegmentUpdateACK error");
2055 if (reversed_before_ack_handling != reversed_after_ack_handling) {
2057 stream = opposing_stream;
2063 SCLogDebug(
"calling StreamTcpReassembleHandleSegmentHandleData");
2066 SCLogDebug(
"StreamTcpReassembleHandleSegmentHandleData error");
2070 StreamTcpReassembleExceptionPolicyStatsIncr(
2078 SCLogDebug(
"ssn %p / stream %p: not calling StreamTcpReassembleHandleSegmentHandleData:"
2079 " p->payload_len %u, STREAMTCP_STREAM_FLAG_NOREASSEMBLY %s",
2089 if ((stream->
flags &
2093 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED, truncate applayer");
2095 SCLogDebug(
"override: direction now UPDATE_DIR_PACKET so we "
2096 "can trigger Truncate");
2104 SCLogDebug(
"inline (%s) or PKT_PSEUDO_STREAM_END (%s)",
2163 if (direction == STREAM_TOSERVER) {
2169 SCLogDebug(
"flagged ssn %p for immediate raw reassembly", ssn);
2180 if (direction == STREAM_TOSERVER) {
2182 SCLogDebug(
"ssn %p: set client.min_inspect_depth to %u", ssn, depth);
2185 SCLogDebug(
"ssn %p: set server.min_inspect_depth to %u", ssn, depth);
2193 #define SET_ISN(stream, setseq) \
2194 (stream)->isn = (setseq); \
2195 (stream)->base_seq = (setseq) + 1
2213 for (; i <
len; i++)
2227 data, data_len) == 0)
2236 #define MISSED_START(isn) \
2237 TcpReassemblyThreadCtx *ra_ctx = NULL; \
2240 memset(&tv, 0, sizeof(tv)); \
2242 StreamTcpUTInit(&ra_ctx); \
2244 StreamTcpUTSetupSession(&ssn); \
2245 StreamTcpUTSetupStream(&ssn.server, (isn)); \
2246 StreamTcpUTSetupStream(&ssn.client, (isn)); \
2248 TcpStream *stream = &ssn.client;
2250 #define MISSED_END \
2251 StreamTcpUTClearSession(&ssn); \
2252 StreamTcpUTDeinit(ra_ctx); \
2255 #define MISSED_STEP(seq, seg, seglen, buf, buflen) \
2256 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen)); \
2257 FAIL_IF(!(VALIDATE(stream, (uint8_t *)(buf), (buflen))));
2259 #define MISSED_ADD_PAYLOAD(seq, seg, seglen) \
2260 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen));
2267 uint64_t last_re = 0;
2271 if (sbb->
offset != last_re) {
2291 uint64_t last_re = 0;
2295 if (sbb->
offset != last_re) {
2301 const uint8_t *buf = NULL;
2302 uint32_t buf_len = 0;
2305 if (
len == buf_len) {
2306 return (memcmp(data, buf,
len) == 0);
2323 static int StreamTcpReassembleTest25 (
void)
2344 static int StreamTcpReassembleTest26 (
void)
2363 static int StreamTcpReassembleTest27 (
void)
2380 static int StreamTcpReassembleTest28 (
void)
2404 static int StreamTcpReassembleTest29 (
void)
2416 static int StreamTcpReassembleTest33(
void)
2425 uint8_t packet[1460] =
"";
2430 memset(&f, 0,
sizeof (
Flow));
2431 memset(&tcph, 0,
sizeof (
TCPHdr));
2436 f.
proto = IPPROTO_TCP;
2439 p->
proto = IPPROTO_TCP;
2477 static int StreamTcpReassembleTest34(
void)
2486 uint8_t packet[1460] =
"";
2490 memset(&f, 0,
sizeof (
Flow));
2491 memset(&tcph, 0,
sizeof (
TCPHdr));
2496 f.
proto = IPPROTO_TCP;
2499 p->
proto = IPPROTO_TCP;
2508 tcph.
th_seq = htonl(857961230);
2514 tcph.
th_seq = htonl(857961534);
2520 tcph.
th_seq = htonl(857963582);
2526 tcph.
th_seq = htonl(857960946);
2546 static int StreamTcpReassembleTest39 (
void)
2556 memset (&f, 0,
sizeof(
Flow));
2558 memset(&stt, 0,
sizeof (stt));
2559 memset(&tcph, 0,
sizeof (
TCPHdr));
2563 f.
proto = IPPROTO_TCP;
2570 tcph.
th_win = htons(5480);
2638 uint8_t request1[] = { 0x47, 0x45, };
2685 uint8_t request2[] = {
2686 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
2687 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
2688 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
2689 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
2690 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
2691 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
2692 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
2693 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
2694 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
2695 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
2696 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
2721 uint8_t response[] = {
2722 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
2723 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
2724 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
2725 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
2726 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
2727 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
2728 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
2729 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
2730 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
2731 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
2732 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
2733 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
2734 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
2735 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
2736 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
2737 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
2738 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
2739 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
2740 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
2741 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
2742 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
2743 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
2744 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
2745 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
2746 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
2747 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
2748 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
2749 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
2750 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
2751 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
2752 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
2753 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
2754 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
2755 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
2756 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
2757 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
2758 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
2759 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
2760 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
2761 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
2762 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
2788 tcph.
th_ack = htonl(328);
2814 tcph.
th_seq = htonl(328);
2838 tcph.
th_ack = htonl(328);
2863 tcph.
th_seq = htonl(328);
2888 tcph.
th_ack = htonl(328);
2914 tcph.
th_seq = htonl(328);
2939 tcph.
th_ack = htonl(328);
2965 tcph.
th_ack = htonl(175);
2966 tcph.
th_seq = htonl(328);
2992 tcph.
th_ack = htonl(175);
2993 tcph.
th_seq = htonl(328);
3009 tcph.
th_ack = htonl(328);
3010 tcph.
th_seq = htonl(175);
3030 static int StreamTcpReassembleTest40 (
void)
3037 memset(&tcph, 0,
sizeof (
TCPHdr));
3047 uint8_t httpbuf1[] =
"P";
3048 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3049 uint8_t httpbuf3[] =
"O";
3050 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
3051 uint8_t httpbuf4[] =
"S";
3052 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
3053 uint8_t httpbuf5[] =
"T \r\n";
3054 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
3056 uint8_t httpbuf2[] =
"HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
3057 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3064 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3067 f->
proto = IPPROTO_TCP;
3070 tcph.
th_win = htons(5480);
3122 tcph.
th_ack = htonl(100);
3131 tcph.
th_seq = htonl(100);
3142 tcph.
th_ack = htonl(145);
3151 tcph.
th_seq = htonl(145);
3168 static int StreamTcpReassembleTest44(
void)
3189 static int StreamTcpReassembleTest45 (
void)
3194 memset(&
tv, 0,
sizeof(
tv));
3195 uint8_t payload[100] = {0};
3196 uint16_t payload_size = 100;
3227 static int StreamTcpReassembleTest46 (
void)
3233 memset(&
tv, 0,
sizeof(
tv));
3234 uint8_t payload[100] = {0};
3235 uint16_t payload_size = 100;
3248 printf(
"STREAMTCP_STREAM_FLAG_NOREASSEMBLY set: ");
3256 printf(
"STREAMTCP_STREAM_FLAG_NOREASSEMBLY set: ");
3276 static int StreamTcpReassembleTest47 (
void)
3284 memset(&tcph, 0,
sizeof (
TCPHdr));
3291 uint8_t httpbuf1[] =
"GET /EVILSUFF HTTP/1.1\r\n\r\n";
3292 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3300 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3303 f->
proto = IPPROTO_TCP;
3306 tcph.
th_win = htons(5480);
3313 tcph.
th_ack = htonl(572799782UL);
3325 tcph.
th_seq = htonl(572799782UL);
3344 static int StreamTcpReassembleInlineTest01(
void)
3352 memset(&
tv, 0x00,
sizeof(
tv));
3360 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3363 printf(
"couldn't get a packet: ");
3370 printf(
"failed to add segment 1: ");
3374 printf(
"failed to add segment 2: ");
3378 printf(
"failed to add segment 3: ");
3394 static int StreamTcpReassembleInlineTest02(
void)
3402 memset(&
tv, 0x00,
sizeof(
tv));
3410 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3413 printf(
"couldn't get a packet: ");
3420 printf(
"failed to add segment 1: ");
3424 printf(
"failed to add segment 2: ");
3428 printf(
"failed to add segment 3: ");
3433 printf(
"failed to add segment 4: ");
3450 static int StreamTcpReassembleInlineTest03(
void)
3458 memset(&
tv, 0x00,
sizeof(
tv));
3468 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3471 printf(
"couldn't get a packet: ");
3479 printf(
"failed to add segment 1: ");
3483 printf(
"failed to add segment 2: ");
3487 printf(
"failed to add segment 3: ");
3492 printf(
"failed to add segment 4: ");
3511 static int StreamTcpReassembleInlineTest04(
void)
3519 memset(&
tv, 0x00,
sizeof(
tv));
3529 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3532 printf(
"couldn't get a packet: ");
3540 printf(
"failed to add segment 1: ");
3544 printf(
"failed to add segment 2: ");
3548 printf(
"failed to add segment 3: ");
3553 printf(
"failed to add segment 4: ");
3573 static int StreamTcpReassembleInlineTest08(
void)
3577 memset(&
tv, 0x00,
sizeof(
tv));
3589 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3621 static int StreamTcpReassembleInlineTest09(
void)
3629 memset(&
tv, 0x00,
sizeof(
tv));
3639 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3642 printf(
"couldn't get a packet: ");
3650 printf(
"failed to add segment 1: ");
3654 printf(
"failed to add segment 2: ");
3658 printf(
"failed to add segment 3: ");
3666 printf(
"failed to add segment 4: ");
3688 static int StreamTcpReassembleInlineTest10(
void)
3697 memset(&
tv, 0x00,
sizeof(
tv));
3708 f =
UTHBuildFlow(AF_INET,
"1.1.1.1",
"2.2.2.2", 1024, 80);
3712 f->
proto = IPPROTO_TCP;
3714 uint8_t stream_payload1[] =
"GE";
3715 uint8_t stream_payload2[] =
"T /";
3716 uint8_t stream_payload3[] =
"HTTP/1.0\r\n\r\n";
3718 p =
UTHBuildPacketReal(stream_payload3, 12, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
3720 printf(
"couldn't get a packet: ");
3728 printf(
"failed to add segment 1: ");
3735 printf(
"StreamTcpReassembleAppLayer failed: ");
3741 printf(
"expected ra_app_base_seq 1, got %u: ", ssn.
client.
base_seq);
3746 printf(
"failed to add segment 2: ");
3750 printf(
"failed to add segment 3: ");
3757 printf(
"StreamTcpReassembleAppLayer failed: ");
3774 static int StreamTcpReassembleInsertTest01(
void)
3781 memset(&
tv, 0x00,
sizeof(
tv));
3789 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3811 static int StreamTcpReassembleInsertTest02(
void)
3818 memset(&
tv, 0x00,
sizeof(
tv));
3825 for (i = 2; i < 10; i++) {
3836 printf(
"failed to add segment 1: ");
3841 printf(
"failed to add segment 2: ");
3854 static int StreamTcpReassembleInsertTest03(
void)
3861 memset(&
tv, 0x00,
sizeof(
tv));
3868 printf(
"failed to add segment 2: ");
3873 for (i = 2; i < 10; i++) {
3884 printf(
"failed to add segment 2: ");
3905 UtRegisterTest(
"StreamTcpReassembleTest25 -- Gap at Start Reassembly Test",
3906 StreamTcpReassembleTest25);
3907 UtRegisterTest(
"StreamTcpReassembleTest26 -- Gap at middle Reassembly Test",
3908 StreamTcpReassembleTest26);
3909 UtRegisterTest(
"StreamTcpReassembleTest27 -- Gap at after Reassembly Test",
3910 StreamTcpReassembleTest27);
3911 UtRegisterTest(
"StreamTcpReassembleTest28 -- Gap at Start IDS missed packet Reassembly Test",
3912 StreamTcpReassembleTest28);
3913 UtRegisterTest(
"StreamTcpReassembleTest29 -- Gap at Middle IDS missed packet Reassembly Test",
3914 StreamTcpReassembleTest29);
3916 StreamTcpReassembleTest33);
3918 StreamTcpReassembleTest34);
3920 StreamTcpReassembleTest39);
3922 StreamTcpReassembleTest40);
3924 StreamTcpReassembleTest44);
3926 StreamTcpReassembleTest45);
3928 StreamTcpReassembleTest46);
3929 UtRegisterTest(
"StreamTcpReassembleTest47 -- TCP Sequence Wraparound Test",
3930 StreamTcpReassembleTest47);
3932 UtRegisterTest(
"StreamTcpReassembleInlineTest01 -- inline RAW ra",
3933 StreamTcpReassembleInlineTest01);
3934 UtRegisterTest(
"StreamTcpReassembleInlineTest02 -- inline RAW ra 2",
3935 StreamTcpReassembleInlineTest02);
3936 UtRegisterTest(
"StreamTcpReassembleInlineTest03 -- inline RAW ra 3",
3937 StreamTcpReassembleInlineTest03);
3938 UtRegisterTest(
"StreamTcpReassembleInlineTest04 -- inline RAW ra 4",
3939 StreamTcpReassembleInlineTest04);
3940 UtRegisterTest(
"StreamTcpReassembleInlineTest08 -- inline RAW ra 8 cleanup",
3941 StreamTcpReassembleInlineTest08);
3942 UtRegisterTest(
"StreamTcpReassembleInlineTest09 -- inline RAW ra 9 GAP cleanup",
3943 StreamTcpReassembleInlineTest09);
3945 UtRegisterTest(
"StreamTcpReassembleInlineTest10 -- inline APP ra 10",
3946 StreamTcpReassembleInlineTest10);
3948 UtRegisterTest(
"StreamTcpReassembleInsertTest01 -- insert with overlap",
3949 StreamTcpReassembleInsertTest01);
3950 UtRegisterTest(
"StreamTcpReassembleInsertTest02 -- insert with overlap",
3951 StreamTcpReassembleInsertTest02);
3952 UtRegisterTest(
"StreamTcpReassembleInsertTest03 -- insert with overlap",
3953 StreamTcpReassembleInsertTest03);
3958 StreamTcpReassembleRawRegisterTests();