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)) {
420 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
427 uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
429 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
471 static int StreamTcpReassemblyConfig(
bool quiet)
473 uint32_t segment_prealloc = 2048;
476 uint32_t prealloc = 0;
483 segment_prealloc = prealloc;
486 SCLogConfig(
"stream.reassembly \"segment-prealloc\": %u", segment_prealloc);
489 int overlap_diff_data = 0;
490 (void)
ConfGetBool(
"stream.reassembly.check-overlap-different-data", &overlap_diff_data);
491 if (overlap_diff_data) {
498 uint16_t max_regions = 8;
509 SCLogConfig(
"stream.reassembly \"max-regions\": %u", max_regions);
527 if (StreamTcpReassemblyConfig(quiet) < 0)
549 if (segment_pool_memuse > 0)
550 SCLogDebug(
"segment_pool_memuse %" PRIu64
" segment_pool_memcnt %" PRIu64
"",
551 segment_pool_memuse, segment_pool_memcnt);
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);
760 const TCPHdr *tcph = PacketGetTCP(p);
766 SCLogDebug(
"ssn %p: check depth returned %"PRIu32, ssn, size);
775 SCLogDebug(
"ssn %p: depth reached, not reassembling", ssn);
813 SCLogDebug(
"StreamTcpReassembleInsertSegment failed");
825 flag |= STREAM_START;
833 flag |= STREAM_MIDSTREAM;
840 if (&ssn->
client == stream) {
841 flag |= STREAM_TOSERVER;
843 flag |= STREAM_TOCLIENT;
846 flag |= STREAM_DEPTH;
857 static int StreamTcpReassembleRawCheckLimit(
const TcpSession *ssn,
863 #define STREAMTCP_STREAM_FLAG_FLUSH_FLAGS \
864 ( STREAMTCP_STREAM_FLAG_DEPTH_REACHED \
865 | STREAMTCP_STREAM_FLAG_TRIGGER_RAW \
866 | STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED)
870 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_DEPTH_REACHED "
871 "is set, so not expecting any new data segments");
874 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_TRIGGER_RAW is set");
877 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED is set, "
878 "so no new segments will be considered");
882 #undef STREAMTCP_STREAM_FLAG_FLUSH_FLAGS
891 const uint64_t last_ack_abs = GetAbsLastAck(stream);
897 if (chunk_size <= diff) {
900 SCLogDebug(
"%s min chunk len not yet reached: "
901 "last_ack %" PRIu32
", ra_raw_base_seq %" PRIu32
", %" PRIu32
" < "
918 const char *dirstr = NULL;
920 if (direction == STREAM_TOSERVER) {
944 const uint64_t right_edge =
946 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
947 " (use: %s). Stream right edge: %" PRIu64,
951 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
956 const uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
957 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
958 " (use: %s). Stream right edge: %" PRIu64,
962 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
967 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NONE", dirstr);
972 static uint64_t GetStreamSize(
TcpStream *stream)
977 uint64_t last_ack_abs = GetAbsLastAck(stream);
978 uint64_t last_re = 0;
984 const uint64_t seg_abs =
986 if (last_re != 0 && last_re < seg_abs) {
987 const char *gacked = NULL;
988 if (last_ack_abs >= seg_abs) {
989 gacked =
"fully ack'd";
990 }
else if (last_ack_abs > last_re) {
991 gacked =
"partly ack'd";
993 gacked =
"not yet ack'd";
995 SCLogDebug(
" -> gap of size %" PRIu64
", ack:%s", seg_abs - last_re, gacked);
998 const char *acked = NULL;
999 if (last_ack_abs >= seg_abs + (uint64_t)
TCP_SEG_LEN(seg)) {
1000 acked =
"fully ack'd";
1001 }
else if (last_ack_abs > seg_abs) {
1002 acked =
"partly ack'd";
1004 acked =
"not yet ack'd";
1007 SCLogDebug(
"%u -> seg %p seq %u abs %" PRIu64
" size %u abs %" PRIu64
" (%" PRIu64
1026 size = GetStreamSize(&ssn->
client);
1027 size += GetStreamSize(&ssn->
server);
1040 GetAbsLastAck(stream) > (cur_blk->
offset + cur_blk->
len)) {
1055 static bool GetAppBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1056 uint64_t
offset,
const bool check_for_gap)
1058 const uint8_t *mydata;
1059 uint32_t mydata_len;
1060 bool gap_ahead =
false;
1068 *data_len = mydata_len;
1087 gap_ahead = check_for_gap && GapAhead(stream, blk);
1091 SCLogDebug(
"gap, want data at offset %"PRIu64
", "
1092 "got data at %"PRIu64
". GAP of size %"PRIu64,
1099 SCLogDebug(
"get data from offset %"PRIu64
". SBB %"PRIu64
"/%u",
1102 SCLogDebug(
"data %p, data_len %u", *data, *data_len);
1104 gap_ahead = check_for_gap && GapAhead(stream, blk);
1123 const uint64_t last_ack_abs = GetAbsLastAck(stream) - (uint64_t)ackadded;
1130 if (last_ack_abs > app_progress) {
1137 "next_seq %u < last_ack %u, but no data in list",
1141 const uint64_t next_seq_abs =
1144 if (blk->
offset > next_seq_abs && blk->
offset < last_ack_abs) {
1147 "next_seq %u < last_ack %u, but ACK'd data beyond gap.",
1155 "last_ack_abs %" PRIu64
" > app_progress %" PRIu64
", "
1156 "but we have no data.",
1157 p->
pcap_cnt, last_ack_abs, app_progress);
1161 "last_ack_abs %"PRIu64
" <= app_progress %"PRIu64,
1162 p->
pcap_cnt, last_ack_abs, app_progress);
1166 static inline uint32_t AdjustToAcked(
const Packet *p,
1168 const uint64_t app_progress,
const uint32_t data_len)
1170 uint32_t adjusted = data_len;
1181 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1185 if (app_progress <= last_ack_abs && app_progress + data_len > last_ack_abs) {
1186 uint32_t check = data_len;
1187 adjusted = (uint32_t)(last_ack_abs - app_progress);
1188 BUG_ON(adjusted > check);
1189 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1190 "data is considered", adjusted);
1207 SCLogDebug(
"app progress %"PRIu64, app_progress);
1209 uint64_t last_ack_abs = GetAbsLastAck(*stream);
1210 SCLogDebug(
"last_ack %u (abs %" PRIu64
"), base_seq %u", (*stream)->last_ack, last_ack_abs,
1211 (*stream)->base_seq);
1213 const uint8_t *mydata;
1214 uint32_t mydata_len;
1215 bool last_was_gap =
false;
1218 const uint8_t
flags = StreamGetAppLayerFlags(ssn, *stream, p);
1219 bool check_for_gap_ahead = ((*stream)->data_required > 0);
1221 GetAppBuffer(*stream, &mydata, &mydata_len, app_progress, check_for_gap_ahead);
1223 if (last_was_gap && mydata_len == 0) {
1226 last_was_gap =
false;
1229 mydata_len = AdjustToAcked(p, ssn, *stream, app_progress, mydata_len);
1231 if (mydata == NULL && mydata_len > 0 && CheckGap(ssn, *stream, p)) {
1232 SCLogDebug(
"sending GAP to app-layer (size: %u)", mydata_len);
1235 StreamGetAppLayerFlags(ssn, *stream, p) | STREAM_GAP, app_update_dir);
1249 if ((*stream)->data_required > 0) {
1250 if ((*stream)->data_required > mydata_len) {
1251 (*stream)->data_required -= mydata_len;
1253 (*stream)->data_required = 0;
1258 if (no_progress_update)
1260 last_was_gap =
true;
1263 }
else if (
flags & STREAM_DEPTH) {
1266 if (mydata == NULL && mydata_len > 0) {
1269 }
else if (mydata == NULL || (mydata_len == 0 && ((
flags & STREAM_EOF) == 0))) {
1282 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1283 *stream, &(*stream)->sb, mydata_len, app_progress);
1287 if (mydata_len < (*stream)->data_required) {
1290 SCLogDebug(
"GAP while expecting more data (expect %u, gap size %u)",
1291 (*stream)->data_required, mydata_len);
1292 (*stream)->app_progress_rel += mydata_len;
1293 (*stream)->data_required -= mydata_len;
1303 (*stream)->data_required = 0;
1308 mydata_len,
flags, app_update_dir);
1314 app_progress = new_app_progress;
1315 if (
flags & STREAM_DEPTH)
1343 SCLogDebug(
"stream no reassembly flag set or app-layer disabled.");
1349 GetSessionSize(ssn, p);
1361 StreamGetAppLayerFlags(ssn, stream, p), app_update_dir);
1369 return ReassembleUpdateAppLayer(
tv, ra_ctx, ssn, &stream, p, app_update_dir);
1375 static int GetRawBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1378 const uint8_t *mydata;
1379 uint32_t mydata_len;
1383 uint64_t roffset =
offset;
1391 *data_len = mydata_len;
1392 *data_offset = roffset;
1394 SCLogDebug(
"multiblob %s. Want offset %"PRIu64,
1395 *iter == NULL ?
"starting" :
"continuing",
offset);
1396 if (*iter == NULL) {
1401 if (*iter == NULL) {
1408 SCLogDebug(
"getting multiple blobs. Iter %p, %"PRIu64
"/%u", *iter, (*iter)->offset, (*iter)->len);
1413 if ((*iter)->offset <
offset) {
1414 uint64_t delta =
offset - (*iter)->offset;
1415 if (delta < mydata_len) {
1416 *data = mydata + delta;
1417 *data_len = (uint32_t)(mydata_len - delta);
1428 *data_len = mydata_len;
1429 *data_offset = (*iter)->offset;
1432 *iter = SBB_RB_NEXT(*iter);
1463 const uint64_t segs_re_abs =
1468 if (StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 1) {
1506 }
else if (progress == 0) {
1511 target = GetAbsLastAck(stream);
1521 SCLogDebug(
"p->pcap_cnt %"PRIu64
": progress %"PRIu64
" app %"PRIu64
" raw %"PRIu64
" tcp win %"PRIu32,
1530 SCLogDebug(
"ssn %p: STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED set, "
1531 "now that detect ran also set STREAMTCP_STREAM_FLAG_DISABLE_RAW", ssn);
1577 SCLogDebug(
"packet payload len %u, so chunk_size adjusted to %u",
1579 }
else if (((chunk_size / 3 ) * 2) < p->
payload_len) {
1581 SCLogDebug(
"packet payload len %u, so chunk_size adjusted to %u",
1585 const TCPHdr *tcph = PacketGetTCP(p);
1586 uint64_t packet_leftedge_abs =
1588 uint64_t packet_rightedge_abs = packet_leftedge_abs + p->
payload_len;
1589 SCLogDebug(
"packet_leftedge_abs %"PRIu64
", rightedge %"PRIu64,
1590 packet_leftedge_abs, packet_rightedge_abs);
1592 const uint8_t *mydata = NULL;
1593 uint32_t mydata_len = 0;
1594 uint64_t mydata_offset = 0;
1596 bool return_progress =
false;
1601 return_progress =
true;
1604 SCLogDebug(
"finding our SBB from offset %"PRIu64, packet_leftedge_abs);
1611 mydata_offset = sbb->
offset;
1616 uint64_t mydata_rightedge_abs = mydata_offset + mydata_len;
1617 if ((mydata == NULL || mydata_len == 0) ||
1618 (mydata_offset >= packet_rightedge_abs ||
1619 packet_leftedge_abs >= mydata_rightedge_abs) ||
1620 (packet_leftedge_abs < mydata_offset ||
1621 packet_rightedge_abs > mydata_rightedge_abs))
1626 mydata_offset = packet_leftedge_abs;
1630 SCLogDebug(
"chunk_size %u mydata_len %u", chunk_size, mydata_len);
1631 if (mydata_len > chunk_size) {
1632 uint32_t excess = mydata_len - chunk_size;
1633 SCLogDebug(
"chunk_size %u mydata_len %u excess %u", chunk_size, mydata_len, excess);
1635 if (mydata_rightedge_abs == packet_rightedge_abs) {
1637 mydata_len -= excess;
1638 mydata_offset += excess;
1639 SCLogDebug(
"cutting front of the buffer with %u", excess);
1640 }
else if (mydata_offset == packet_leftedge_abs) {
1641 mydata_len -= excess;
1642 SCLogDebug(
"cutting tail of the buffer with %u", excess);
1644 uint32_t before = (uint32_t)(packet_leftedge_abs - mydata_offset);
1645 uint32_t after = (uint32_t)(mydata_rightedge_abs - packet_rightedge_abs);
1646 SCLogDebug(
"before %u after %u", before, after);
1651 if (before >= (chunk_size - p->
payload_len) / 2) {
1653 before = after = (chunk_size - p->
payload_len) / 2;
1662 if (before >= (chunk_size - p->
payload_len) / 2) {
1670 uint32_t skip = (uint32_t)(packet_leftedge_abs - mydata_offset) - before;
1671 uint32_t cut = (uint32_t)(mydata_rightedge_abs - packet_rightedge_abs) - after;
1676 mydata_len -= (skip + cut);
1677 mydata_offset += skip;
1683 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1686 if (return_progress) {
1687 *progress_out = (mydata_offset + mydata_len);
1694 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1695 SCLogDebug(
"last_ack_abs %"PRIu64, last_ack_abs);
1698 if (mydata_offset > last_ack_abs) {
1700 *progress_out = last_ack_abs;
1702 *progress_out = (mydata_offset + mydata_len);
1745 const uint64_t re, uint64_t *progress_out,
bool eof,
bool respect_inspect_depth)
1751 uint64_t progress = progress_in;
1756 const uint8_t *mydata;
1757 uint32_t mydata_len;
1758 uint64_t mydata_offset = 0;
1760 GetRawBuffer(stream, &mydata, &mydata_len, &iter, progress, &mydata_offset);
1761 if (mydata_len == 0) {
1767 SCLogDebug(
"raw progress %"PRIu64, progress);
1768 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1769 stream, &stream->
sb, mydata_len, progress);
1774 if (re < progress) {
1779 SCLogDebug(
"re %" PRIu64
", raw_progress %" PRIu64, re, progress);
1780 SCLogDebug(
"raw_progress + mydata_len %" PRIu64
", re %" PRIu64, progress + mydata_len,
1784 if (progress + mydata_len > re) {
1785 uint32_t check = mydata_len;
1786 mydata_len = (uint32_t)(re - progress);
1787 BUG_ON(check < mydata_len);
1788 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1789 "data is considered", mydata_len);
1792 if (mydata_len == 0)
1795 SCLogDebug(
"data %p len %u", mydata, mydata_len);
1798 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1801 if (mydata_offset == progress) {
1802 SCLogDebug(
"progress %"PRIu64
" increasing with data len %u to %"PRIu64,
1803 progress, mydata_len, progress_in + mydata_len);
1805 progress += mydata_len;
1806 SCLogDebug(
"raw progress now %"PRIu64, progress);
1809 }
else if (mydata_offset > progress && mydata_offset < re) {
1810 SCLogDebug(
"GAP: data is missing from %"PRIu64
" (%u bytes), setting to first data we have: %"PRIu64, progress, (uint32_t)(mydata_offset - progress), mydata_offset);
1812 progress = mydata_offset;
1813 SCLogDebug(
"raw progress now %"PRIu64, progress);
1816 SCLogDebug(
"not increasing progress, data gap => mydata_offset "
1817 "%"PRIu64
" != progress %"PRIu64, mydata_offset, progress);
1820 if (iter == NULL || r == 1)
1824 *progress_out = progress;
1829 void *cb_data,
const uint64_t
offset,
const bool eof)
1833 SCLogDebug(
"app_progress %" PRIu64, app_progress);
1835 uint64_t unused = 0;
1836 return StreamReassembleRawDo(
1837 ssn, stream, Callback, cb_data,
offset, app_progress, &unused, eof,
false);
1842 uint64_t *progress_out,
bool respect_inspect_depth)
1846 return StreamReassembleRawInline(ssn, p, Callback, cb_data, progress_out);
1857 StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 0)
1869 SCLogDebug(
"respect_inspect_depth %s STREAMTCP_STREAM_FLAG_TRIGGER_RAW %s "
1870 "stream->min_inspect_depth %u",
1871 respect_inspect_depth ?
"true" :
"false",
1888 SCLogDebug(
"applied min inspect depth due to STREAMTCP_STREAM_FLAG_TRIGGER_RAW: progress "
1898 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1899 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1901 return StreamReassembleRawDo(ssn, stream, Callback, cb_data, progress, last_ack_abs,
1907 uint64_t *progress_out,
const bool eof)
1913 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1914 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1916 return StreamReassembleRawDo(
1917 ssn, stream, Callback, cb_data, progress_in, last_ack_abs, progress_out, eof,
false);
1925 static int StreamTcpReassembleHandleSegmentUpdateACK (
ThreadVars *
tv,
1936 static void StreamTcpReassembleExceptionPolicyStatsIncr(
1951 const TCPHdr *tcph = PacketGetTCP(p);
1953 SCLogDebug(
"ssn %p, stream %p, p %p, p->payload_len %"PRIu16
"",
1983 if (stream == &ssn->
client) {
1984 opposing_stream = &ssn->
server;
1986 opposing_stream = &ssn->
client;
1991 if (StreamTcpReassembleHandleSegmentUpdateACK(
tv, ra_ctx, ssn, opposing_stream, p) != 0) {
1992 SCLogDebug(
"StreamTcpReassembleHandleSegmentUpdateACK error");
2000 if (reversed_before_ack_handling != reversed_after_ack_handling) {
2002 stream = opposing_stream;
2008 SCLogDebug(
"calling StreamTcpReassembleHandleSegmentHandleData");
2011 SCLogDebug(
"StreamTcpReassembleHandleSegmentHandleData error");
2015 StreamTcpReassembleExceptionPolicyStatsIncr(
2023 SCLogDebug(
"ssn %p / stream %p: not calling StreamTcpReassembleHandleSegmentHandleData:"
2024 " p->payload_len %u, STREAMTCP_STREAM_FLAG_NOREASSEMBLY %s",
2034 if ((stream->
flags &
2038 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED, truncate applayer");
2040 SCLogDebug(
"override: direction now UPDATE_DIR_PACKET so we "
2041 "can trigger Truncate");
2049 SCLogDebug(
"inline (%s) or PKT_PSEUDO_STREAM_END (%s)",
2108 if (direction == STREAM_TOSERVER) {
2114 SCLogDebug(
"flagged ssn %p for immediate raw reassembly", ssn);
2125 if (direction == STREAM_TOSERVER) {
2127 SCLogDebug(
"ssn %p: set client.min_inspect_depth to %u", ssn, depth);
2130 SCLogDebug(
"ssn %p: set server.min_inspect_depth to %u", ssn, depth);
2138 #define SET_ISN(stream, setseq) \
2139 (stream)->isn = (setseq); \
2140 (stream)->base_seq = (setseq) + 1
2158 for (; i <
len; i++)
2172 data, data_len) == 0)
2181 #define MISSED_START(isn) \
2182 TcpReassemblyThreadCtx *ra_ctx = NULL; \
2185 memset(&tv, 0, sizeof(tv)); \
2187 StreamTcpUTInit(&ra_ctx); \
2189 StreamTcpUTSetupSession(&ssn); \
2190 StreamTcpUTSetupStream(&ssn.server, (isn)); \
2191 StreamTcpUTSetupStream(&ssn.client, (isn)); \
2193 TcpStream *stream = &ssn.client;
2195 #define MISSED_END \
2196 StreamTcpUTClearSession(&ssn); \
2197 StreamTcpUTDeinit(ra_ctx); \
2200 #define MISSED_STEP(seq, seg, seglen, buf, buflen) \
2201 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen)); \
2202 FAIL_IF(!(VALIDATE(stream, (uint8_t *)(buf), (buflen))));
2204 #define MISSED_ADD_PAYLOAD(seq, seg, seglen) \
2205 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen));
2212 uint64_t last_re = 0;
2216 if (sbb->
offset != last_re) {
2236 uint64_t last_re = 0;
2240 if (sbb->
offset != last_re) {
2246 const uint8_t *buf = NULL;
2247 uint32_t buf_len = 0;
2250 if (
len == buf_len) {
2251 return (memcmp(data, buf,
len) == 0);
2268 static int StreamTcpReassembleTest25 (
void)
2289 static int StreamTcpReassembleTest26 (
void)
2308 static int StreamTcpReassembleTest27 (
void)
2325 static int StreamTcpReassembleTest28 (
void)
2349 static int StreamTcpReassembleTest29 (
void)
2361 static int StreamTcpReassembleTest33(
void)
2370 uint8_t packet[1460] =
"";
2375 memset(&f, 0,
sizeof (
Flow));
2376 memset(&tcph, 0,
sizeof (
TCPHdr));
2381 f.
proto = IPPROTO_TCP;
2384 p->
proto = IPPROTO_TCP;
2422 static int StreamTcpReassembleTest34(
void)
2431 uint8_t packet[1460] =
"";
2435 memset(&f, 0,
sizeof (
Flow));
2436 memset(&tcph, 0,
sizeof (
TCPHdr));
2441 f.
proto = IPPROTO_TCP;
2444 p->
proto = IPPROTO_TCP;
2453 tcph.
th_seq = htonl(857961230);
2459 tcph.
th_seq = htonl(857961534);
2465 tcph.
th_seq = htonl(857963582);
2471 tcph.
th_seq = htonl(857960946);
2491 static int StreamTcpReassembleTest39 (
void)
2501 memset (&f, 0,
sizeof(
Flow));
2503 memset(&stt, 0,
sizeof (stt));
2504 memset(&tcph, 0,
sizeof (
TCPHdr));
2508 f.
proto = IPPROTO_TCP;
2515 tcph.
th_win = htons(5480);
2583 uint8_t request1[] = { 0x47, 0x45, };
2630 uint8_t request2[] = {
2631 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
2632 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
2633 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
2634 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
2635 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
2636 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
2637 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
2638 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
2639 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
2640 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
2641 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
2666 uint8_t response[] = {
2667 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
2668 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
2669 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
2670 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
2671 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
2672 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
2673 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
2674 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
2675 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
2676 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
2677 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
2678 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
2679 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
2680 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
2681 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
2682 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
2683 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
2684 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
2685 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
2686 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
2687 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
2688 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
2689 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
2690 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
2691 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
2692 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
2693 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
2694 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
2695 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
2696 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
2697 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
2698 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
2699 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
2700 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
2701 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
2702 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
2703 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
2704 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
2705 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
2706 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
2707 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
2733 tcph.
th_ack = htonl(328);
2759 tcph.
th_seq = htonl(328);
2783 tcph.
th_ack = htonl(328);
2808 tcph.
th_seq = htonl(328);
2833 tcph.
th_ack = htonl(328);
2859 tcph.
th_seq = htonl(328);
2884 tcph.
th_ack = htonl(328);
2910 tcph.
th_ack = htonl(175);
2911 tcph.
th_seq = htonl(328);
2937 tcph.
th_ack = htonl(175);
2938 tcph.
th_seq = htonl(328);
2954 tcph.
th_ack = htonl(328);
2955 tcph.
th_seq = htonl(175);
2975 static int StreamTcpReassembleTest40 (
void)
2982 memset(&tcph, 0,
sizeof (
TCPHdr));
2992 uint8_t httpbuf1[] =
"P";
2993 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
2994 uint8_t httpbuf3[] =
"O";
2995 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
2996 uint8_t httpbuf4[] =
"S";
2997 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
2998 uint8_t httpbuf5[] =
"T \r\n";
2999 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
3001 uint8_t httpbuf2[] =
"HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
3002 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3009 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3012 f->
proto = IPPROTO_TCP;
3015 tcph.
th_win = htons(5480);
3067 tcph.
th_ack = htonl(100);
3076 tcph.
th_seq = htonl(100);
3087 tcph.
th_ack = htonl(145);
3096 tcph.
th_seq = htonl(145);
3113 static int StreamTcpReassembleTest44(
void)
3134 static int StreamTcpReassembleTest45 (
void)
3139 memset(&
tv, 0,
sizeof(
tv));
3140 uint8_t payload[100] = {0};
3141 uint16_t payload_size = 100;
3172 static int StreamTcpReassembleTest46 (
void)
3178 memset(&
tv, 0,
sizeof(
tv));
3179 uint8_t payload[100] = {0};
3180 uint16_t payload_size = 100;
3193 printf(
"STREAMTCP_STREAM_FLAG_NOREASSEMBLY set: ");
3201 printf(
"STREAMTCP_STREAM_FLAG_NOREASSEMBLY set: ");
3221 static int StreamTcpReassembleTest47 (
void)
3229 memset(&tcph, 0,
sizeof (
TCPHdr));
3236 uint8_t httpbuf1[] =
"GET /EVILSUFF HTTP/1.1\r\n\r\n";
3237 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3245 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3248 f->
proto = IPPROTO_TCP;
3251 tcph.
th_win = htons(5480);
3258 tcph.
th_ack = htonl(572799782UL);
3270 tcph.
th_seq = htonl(572799782UL);
3289 static int StreamTcpReassembleInlineTest01(
void)
3297 memset(&
tv, 0x00,
sizeof(
tv));
3305 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3308 printf(
"couldn't get a packet: ");
3315 printf(
"failed to add segment 1: ");
3319 printf(
"failed to add segment 2: ");
3323 printf(
"failed to add segment 3: ");
3339 static int StreamTcpReassembleInlineTest02(
void)
3347 memset(&
tv, 0x00,
sizeof(
tv));
3355 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3358 printf(
"couldn't get a packet: ");
3365 printf(
"failed to add segment 1: ");
3369 printf(
"failed to add segment 2: ");
3373 printf(
"failed to add segment 3: ");
3378 printf(
"failed to add segment 4: ");
3395 static int StreamTcpReassembleInlineTest03(
void)
3403 memset(&
tv, 0x00,
sizeof(
tv));
3413 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3416 printf(
"couldn't get a packet: ");
3424 printf(
"failed to add segment 1: ");
3428 printf(
"failed to add segment 2: ");
3432 printf(
"failed to add segment 3: ");
3437 printf(
"failed to add segment 4: ");
3456 static int StreamTcpReassembleInlineTest04(
void)
3464 memset(&
tv, 0x00,
sizeof(
tv));
3474 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3477 printf(
"couldn't get a packet: ");
3485 printf(
"failed to add segment 1: ");
3489 printf(
"failed to add segment 2: ");
3493 printf(
"failed to add segment 3: ");
3498 printf(
"failed to add segment 4: ");
3518 static int StreamTcpReassembleInlineTest08(
void)
3522 memset(&
tv, 0x00,
sizeof(
tv));
3534 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3566 static int StreamTcpReassembleInlineTest09(
void)
3574 memset(&
tv, 0x00,
sizeof(
tv));
3584 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3587 printf(
"couldn't get a packet: ");
3595 printf(
"failed to add segment 1: ");
3599 printf(
"failed to add segment 2: ");
3603 printf(
"failed to add segment 3: ");
3611 printf(
"failed to add segment 4: ");
3633 static int StreamTcpReassembleInlineTest10(
void)
3642 memset(&
tv, 0x00,
sizeof(
tv));
3653 f =
UTHBuildFlow(AF_INET,
"1.1.1.1",
"2.2.2.2", 1024, 80);
3657 f->
proto = IPPROTO_TCP;
3659 uint8_t stream_payload1[] =
"GE";
3660 uint8_t stream_payload2[] =
"T /";
3661 uint8_t stream_payload3[] =
"HTTP/1.0\r\n\r\n";
3663 p =
UTHBuildPacketReal(stream_payload3, 12, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
3665 printf(
"couldn't get a packet: ");
3673 printf(
"failed to add segment 1: ");
3680 printf(
"StreamTcpReassembleAppLayer failed: ");
3686 printf(
"expected ra_app_base_seq 1, got %u: ", ssn.
client.
base_seq);
3691 printf(
"failed to add segment 2: ");
3695 printf(
"failed to add segment 3: ");
3702 printf(
"StreamTcpReassembleAppLayer failed: ");
3719 static int StreamTcpReassembleInsertTest01(
void)
3726 memset(&
tv, 0x00,
sizeof(
tv));
3734 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3756 static int StreamTcpReassembleInsertTest02(
void)
3763 memset(&
tv, 0x00,
sizeof(
tv));
3770 for (i = 2; i < 10; i++) {
3781 printf(
"failed to add segment 1: ");
3786 printf(
"failed to add segment 2: ");
3799 static int StreamTcpReassembleInsertTest03(
void)
3806 memset(&
tv, 0x00,
sizeof(
tv));
3813 printf(
"failed to add segment 2: ");
3818 for (i = 2; i < 10; i++) {
3829 printf(
"failed to add segment 2: ");
3850 UtRegisterTest(
"StreamTcpReassembleTest25 -- Gap at Start Reassembly Test",
3851 StreamTcpReassembleTest25);
3852 UtRegisterTest(
"StreamTcpReassembleTest26 -- Gap at middle Reassembly Test",
3853 StreamTcpReassembleTest26);
3854 UtRegisterTest(
"StreamTcpReassembleTest27 -- Gap at after Reassembly Test",
3855 StreamTcpReassembleTest27);
3856 UtRegisterTest(
"StreamTcpReassembleTest28 -- Gap at Start IDS missed packet Reassembly Test",
3857 StreamTcpReassembleTest28);
3858 UtRegisterTest(
"StreamTcpReassembleTest29 -- Gap at Middle IDS missed packet Reassembly Test",
3859 StreamTcpReassembleTest29);
3861 StreamTcpReassembleTest33);
3863 StreamTcpReassembleTest34);
3865 StreamTcpReassembleTest39);
3867 StreamTcpReassembleTest40);
3869 StreamTcpReassembleTest44);
3871 StreamTcpReassembleTest45);
3873 StreamTcpReassembleTest46);
3874 UtRegisterTest(
"StreamTcpReassembleTest47 -- TCP Sequence Wraparound Test",
3875 StreamTcpReassembleTest47);
3877 UtRegisterTest(
"StreamTcpReassembleInlineTest01 -- inline RAW ra",
3878 StreamTcpReassembleInlineTest01);
3879 UtRegisterTest(
"StreamTcpReassembleInlineTest02 -- inline RAW ra 2",
3880 StreamTcpReassembleInlineTest02);
3881 UtRegisterTest(
"StreamTcpReassembleInlineTest03 -- inline RAW ra 3",
3882 StreamTcpReassembleInlineTest03);
3883 UtRegisterTest(
"StreamTcpReassembleInlineTest04 -- inline RAW ra 4",
3884 StreamTcpReassembleInlineTest04);
3885 UtRegisterTest(
"StreamTcpReassembleInlineTest08 -- inline RAW ra 8 cleanup",
3886 StreamTcpReassembleInlineTest08);
3887 UtRegisterTest(
"StreamTcpReassembleInlineTest09 -- inline RAW ra 9 GAP cleanup",
3888 StreamTcpReassembleInlineTest09);
3890 UtRegisterTest(
"StreamTcpReassembleInlineTest10 -- inline APP ra 10",
3891 StreamTcpReassembleInlineTest10);
3893 UtRegisterTest(
"StreamTcpReassembleInsertTest01 -- insert with overlap",
3894 StreamTcpReassembleInsertTest01);
3895 UtRegisterTest(
"StreamTcpReassembleInsertTest02 -- insert with overlap",
3896 StreamTcpReassembleInsertTest02);
3897 UtRegisterTest(
"StreamTcpReassembleInsertTest03 -- insert with overlap",
3898 StreamTcpReassembleInsertTest03);
3903 StreamTcpReassembleRawRegisterTests();