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) {
233 if (size > orig_size) {
244 static void ReassembleFree(
void *ptr,
size_t size)
251 static void *TcpSegmentPoolAlloc(
void)
274 "TcpSegmentPcapHdrStorage");
283 "packet header data within "
284 "TcpSegmentPcapHdrStorage");
299 static int TcpSegmentPoolInit(
void *data,
void *initdata)
327 segment_pool_memcnt++;
328 SCLogDebug(
"segment_pool_memcnt %"PRIu64
"", segment_pool_memcnt);
337 static void TcpSegmentPoolCleanup(
void *ptr)
358 segment_pool_memcnt--;
359 SCLogDebug(
"segment_pool_memcnt %"PRIu64
"", segment_pool_memcnt);
396 static inline uint64_t GetAbsLastAck(
const TcpStream *stream)
398 if (STREAM_LASTACK_GT_BASESEQ(stream)) {
407 return GetAbsLastAck(stream);
414 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
456 static int StreamTcpReassemblyConfig(
bool quiet)
458 uint32_t segment_prealloc = 2048;
461 uint32_t prealloc = 0;
464 "%s is invalid", seg->
val);
467 segment_prealloc = prealloc;
470 SCLogConfig(
"stream.reassembly \"segment-prealloc\": %u", segment_prealloc);
473 int overlap_diff_data = 0;
474 (void)
ConfGetBool(
"stream.reassembly.check-overlap-different-data", &overlap_diff_data);
475 if (overlap_diff_data) {
495 if (StreamTcpReassemblyConfig(quiet) < 0)
509 if (segment_thread_pool != NULL) {
511 segment_thread_pool = NULL;
517 if (segment_pool_memuse > 0)
518 SCLogInfo(
"segment_pool_memuse %"PRIu64
"", segment_pool_memuse);
519 if (segment_pool_memcnt > 0)
520 SCLogInfo(
"segment_pool_memcnt %"PRIu64
"", segment_pool_memcnt);
537 if (segment_thread_pool == NULL) {
543 TcpSegmentPoolInit, NULL,
544 TcpSegmentPoolCleanup, NULL);
546 SCLogDebug(
"pool size %d, thread segment_thread_pool_id %d",
552 SCLogDebug(
"pool size %d, thread segment_thread_pool_id %d",
613 uint32_t
seq, uint32_t size)
631 SCLogDebug(
"segment entirely before base_seq, weird: base %u, seq %u, re %u",
645 SCLogDebug(
"seq + size %u, base %u, seg_depth %"PRIu64
" limit %u", (
seq + size),
650 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
654 SCLogDebug(
"NOT STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
657 SCLogDebug(
"full depth not yet reached: %"PRIu64
" <= %"PRIu32,
658 (stream->base_seq_offset + stream->
base_seq + size),
725 SCLogDebug(
"ssn %p: both app and raw reassembly disabled, not reassembling", ssn);
732 SCLogDebug(
"ssn %p: check depth returned %"PRIu32, ssn, size);
739 SCLogDebug(
"ssn %p: depth reached, not reassembling", ssn);
777 SCLogDebug(
"StreamTcpReassembleInsertSegment failed");
789 flag |= STREAM_START;
797 flag |= STREAM_MIDSTREAM;
804 if (&ssn->
client == stream) {
805 flag |= STREAM_TOSERVER;
807 flag |= STREAM_TOCLIENT;
810 flag |= STREAM_DEPTH;
821 static int StreamTcpReassembleRawCheckLimit(
const TcpSession *ssn,
827 #define STREAMTCP_STREAM_FLAG_FLUSH_FLAGS \
828 ( STREAMTCP_STREAM_FLAG_DEPTH_REACHED \
829 | STREAMTCP_STREAM_FLAG_TRIGGER_RAW \
830 | STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED)
834 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_DEPTH_REACHED "
835 "is set, so not expecting any new data segments");
838 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_TRIGGER_RAW is set");
841 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED is set, "
842 "so no new segments will be considered");
846 #undef STREAMTCP_STREAM_FLAG_FLUSH_FLAGS
855 const uint64_t last_ack_abs = GetAbsLastAck(stream);
861 if (chunk_size <= diff) {
864 SCLogDebug(
"%s min chunk len not yet reached: "
865 "last_ack %" PRIu32
", ra_raw_base_seq %" PRIu32
", %" PRIu32
" < "
882 const char *dirstr = NULL;
884 if (direction == STREAM_TOSERVER) {
911 SCLogDebug(
"%s: app %"PRIu64
" (use: %s), raw %"PRIu64
" (use: %s). Stream right edge: %"PRIu64,
918 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
924 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
929 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NONE", dirstr);
934 static uint64_t GetStreamSize(
TcpStream *stream)
939 uint64_t last_ack_abs = GetAbsLastAck(stream);
940 uint64_t last_re = 0;
946 const uint64_t seg_abs =
948 if (last_re != 0 && last_re < seg_abs) {
949 const char *gacked = NULL;
950 if (last_ack_abs >= seg_abs) {
951 gacked =
"fully ack'd";
952 }
else if (last_ack_abs > last_re) {
953 gacked =
"partly ack'd";
955 gacked =
"not yet ack'd";
957 SCLogDebug(
" -> gap of size %" PRIu64
", ack:%s", seg_abs - last_re, gacked);
960 const char *acked = NULL;
961 if (last_ack_abs >= seg_abs + (uint64_t)
TCP_SEG_LEN(seg)) {
962 acked =
"fully ack'd";
963 }
else if (last_ack_abs > seg_abs) {
964 acked =
"partly ack'd";
966 acked =
"not yet ack'd";
969 SCLogDebug(
"%u -> seg %p seq %u abs %" PRIu64
" size %u abs %" PRIu64
" (%" PRIu64
978 SCLogDebug(
"size %"PRIu64
", cnt %"PRIu32, size, cnt);
988 size = GetStreamSize(&ssn->
client);
989 size += GetStreamSize(&ssn->
server);
1004 for ( ; blk != NULL; blk = SBB_RB_NEXT(blk)) {
1018 GetAbsLastAck(stream) > (cur_blk->
offset + cur_blk->
len)) {
1033 static bool GetAppBuffer(
TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1034 uint64_t
offset,
const bool check_for_gap)
1036 const uint8_t *mydata;
1037 uint32_t mydata_len;
1038 bool gap_ahead =
false;
1046 *data_len = mydata_len;
1061 gap_ahead = check_for_gap && GapAhead(stream, blk);
1065 SCLogDebug(
"gap, want data at offset %"PRIu64
", "
1066 "got data at %"PRIu64
". GAP of size %"PRIu64,
1073 SCLogDebug(
"get data from offset %"PRIu64
". SBB %"PRIu64
"/%u",
1076 SCLogDebug(
"data %p, data_len %u", *data, *data_len);
1078 gap_ahead = check_for_gap && GapAhead(stream, blk);
1097 const uint64_t last_ack_abs = GetAbsLastAck(stream) - (uint64_t)ackadded;
1104 if (last_ack_abs > app_progress) {
1111 "next_seq %u < last_ack %u, but no data in list",
1115 const uint64_t next_seq_abs =
1118 if (blk->
offset > next_seq_abs && blk->
offset < last_ack_abs) {
1121 "next_seq %u < last_ack %u, but ACK'd data beyond gap.",
1129 "last_ack_abs %" PRIu64
" > app_progress %" PRIu64
", "
1130 "but we have no data.",
1131 p->
pcap_cnt, last_ack_abs, app_progress);
1135 "last_ack_abs %"PRIu64
" <= app_progress %"PRIu64,
1136 p->
pcap_cnt, last_ack_abs, app_progress);
1140 static inline uint32_t AdjustToAcked(
const Packet *p,
1142 const uint64_t app_progress,
const uint32_t data_len)
1144 uint32_t adjusted = data_len;
1155 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1159 if (app_progress <= last_ack_abs && app_progress + data_len > last_ack_abs) {
1160 uint32_t check = data_len;
1161 adjusted = last_ack_abs - app_progress;
1162 BUG_ON(adjusted > check);
1163 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1164 "data is considered", adjusted);
1183 SCLogDebug(
"app progress %"PRIu64, app_progress);
1184 SCLogDebug(
"last_ack %u, base_seq %u", (*stream)->last_ack, (*stream)->base_seq);
1186 const uint8_t *mydata;
1187 uint32_t mydata_len;
1188 bool last_was_gap =
false;
1191 const uint8_t
flags = StreamGetAppLayerFlags(ssn, *stream, p);
1192 bool check_for_gap_ahead = ((*stream)->data_required > 0);
1194 GetAppBuffer(*stream, &mydata, &mydata_len, app_progress, check_for_gap_ahead);
1195 if (last_was_gap && mydata_len == 0) {
1198 last_was_gap =
false;
1201 mydata_len = AdjustToAcked(p, ssn, *stream, app_progress, mydata_len);
1203 if (mydata == NULL && mydata_len > 0 && CheckGap(ssn, *stream, p)) {
1204 SCLogDebug(
"sending GAP to app-layer (size: %u)", mydata_len);
1208 StreamGetAppLayerFlags(ssn, *stream, p)|STREAM_GAP);
1209 AppLayerProfilingStore(ra_ctx->
app_tctx, p);
1221 if ((*stream)->data_required > 0) {
1222 if ((*stream)->data_required > mydata_len) {
1223 (*stream)->data_required -= mydata_len;
1225 (*stream)->data_required = 0;
1230 if (no_progress_update)
1232 last_was_gap =
true;
1235 }
else if (
flags & STREAM_DEPTH) {
1237 if (mydata == NULL && mydata_len > 0) {
1240 }
else if (mydata == NULL || (mydata_len == 0 && ((
flags & STREAM_EOF) == 0))) {
1252 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1253 *stream, &(*stream)->sb, mydata_len, app_progress);
1256 if (mydata_len < (*stream)->data_required) {
1258 SCLogDebug(
"GAP while expecting more data (expect %u, gap size %u)",
1259 (*stream)->data_required, mydata_len);
1260 (*stream)->app_progress_rel += mydata_len;
1261 (*stream)->data_required -= mydata_len;
1271 (*stream)->data_required = 0;
1275 (uint8_t *)mydata, mydata_len,
flags);
1276 AppLayerProfilingStore(ra_ctx->
app_tctx, p);
1281 app_progress = new_app_progress;
1282 if (
flags & STREAM_DEPTH)
1311 SCLogDebug(
"stream no reassembly flag set or app-layer disabled.");
1317 GetSessionSize(ssn, p);
1330 StreamGetAppLayerFlags(ssn, stream, p));
1331 AppLayerProfilingStore(ra_ctx->
app_tctx, p);
1338 return ReassembleUpdateAppLayer(
tv, ra_ctx, ssn, &stream, p, dir);
1344 static int GetRawBuffer(
TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1347 const uint8_t *mydata;
1348 uint32_t mydata_len;
1352 uint64_t roffset =
offset;
1360 *data_len = mydata_len;
1361 *data_offset = roffset;
1363 SCLogDebug(
"multiblob %s. Want offset %"PRIu64,
1364 *iter == NULL ?
"starting" :
"continuing",
offset);
1365 if (*iter == NULL) {
1370 if (*iter == NULL) {
1377 SCLogDebug(
"getting multiple blobs. Iter %p, %"PRIu64
"/%u", *iter, (*iter)->offset, (*iter)->len);
1382 if ((*iter)->offset <
offset) {
1383 uint64_t delta =
offset - (*iter)->offset;
1384 if (delta < mydata_len) {
1385 *data = mydata + delta;
1386 *data_len = mydata_len - delta;
1397 *data_len = mydata_len;
1398 *data_offset = (*iter)->offset;
1401 *iter = SBB_RB_NEXT(*iter);
1435 if (StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 1) {
1484 uint64_t tcp_window = stream->
window;
1494 }
else if (progress == 0) {
1495 uint64_t tcp_window = stream->
window;
1497 if (tcp_window < stream_right_edge) {
1498 uint64_t new_raw = stream_right_edge - tcp_window;
1507 SCLogDebug(
"p->pcap_cnt %"PRIu64
": progress %"PRIu64
" app %"PRIu64
" raw %"PRIu64
" tcp win %"PRIu32,
1516 SCLogDebug(
"ssn %p: STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED set, "
1517 "now that detect ran also set STREAMTCP_STREAM_FLAG_DISABLE_RAW", ssn);
1563 SCLogDebug(
"packet payload len %u, so chunk_size adjusted to %u",
1565 }
else if (((chunk_size / 3 ) * 2) < p->
payload_len) {
1567 SCLogDebug(
"packet payload len %u, so chunk_size adjusted to %u",
1572 uint64_t packet_rightedge_abs = packet_leftedge_abs + p->
payload_len;
1573 SCLogDebug(
"packet_leftedge_abs %"PRIu64
", rightedge %"PRIu64,
1574 packet_leftedge_abs, packet_rightedge_abs);
1576 const uint8_t *mydata = NULL;
1577 uint32_t mydata_len = 0;
1578 uint64_t mydata_offset = 0;
1580 bool return_progress =
false;
1585 return_progress =
true;
1588 SCLogDebug(
"finding our SBB from offset %"PRIu64, packet_leftedge_abs);
1595 mydata_offset = sbb->
offset;
1600 uint64_t mydata_rightedge_abs = mydata_offset + mydata_len;
1601 if ((mydata == NULL || mydata_len == 0) ||
1602 (mydata_offset >= packet_rightedge_abs ||
1603 packet_leftedge_abs >= mydata_rightedge_abs) ||
1604 (packet_leftedge_abs < mydata_offset ||
1605 packet_rightedge_abs > mydata_rightedge_abs))
1610 mydata_offset = packet_leftedge_abs;
1614 SCLogDebug(
"chunk_size %u mydata_len %u", chunk_size, mydata_len);
1615 if (mydata_len > chunk_size) {
1616 uint32_t excess = mydata_len - chunk_size;
1617 SCLogDebug(
"chunk_size %u mydata_len %u excess %u", chunk_size, mydata_len, excess);
1619 if (mydata_rightedge_abs == packet_rightedge_abs) {
1621 mydata_len -= excess;
1622 mydata_offset += excess;
1623 SCLogDebug(
"cutting front of the buffer with %u", excess);
1624 }
else if (mydata_offset == packet_leftedge_abs) {
1625 mydata_len -= excess;
1626 SCLogDebug(
"cutting tail of the buffer with %u", excess);
1628 uint32_t before = (uint32_t)(packet_leftedge_abs - mydata_offset);
1629 uint32_t after = (uint32_t)(mydata_rightedge_abs - packet_rightedge_abs);
1630 SCLogDebug(
"before %u after %u", before, after);
1635 if (before >= (chunk_size - p->
payload_len) / 2) {
1637 before = after = (chunk_size - p->
payload_len) / 2;
1646 if (before >= (chunk_size - p->
payload_len) / 2) {
1654 uint32_t skip = (uint32_t)(packet_leftedge_abs - mydata_offset) - before;
1655 uint32_t cut = (uint32_t)(mydata_rightedge_abs - packet_rightedge_abs) - after;
1660 mydata_len -= (skip + cut);
1661 mydata_offset += skip;
1667 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1670 if (return_progress) {
1671 *progress_out = (mydata_offset + mydata_len);
1678 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1679 SCLogDebug(
"last_ack_abs %"PRIu64, last_ack_abs);
1682 if (mydata_offset > last_ack_abs) {
1684 *progress_out = last_ack_abs;
1686 *progress_out = (mydata_offset + mydata_len);
1729 const uint64_t re, uint64_t *progress_out,
bool eof,
bool respect_inspect_depth)
1735 uint64_t progress = progress_in;
1740 const uint8_t *mydata;
1741 uint32_t mydata_len;
1742 uint64_t mydata_offset = 0;
1744 GetRawBuffer(stream, &mydata, &mydata_len, &iter, progress, &mydata_offset);
1745 if (mydata_len == 0) {
1751 SCLogDebug(
"raw progress %"PRIu64, progress);
1752 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1753 stream, &stream->
sb, mydata_len, progress);
1758 if (re < progress) {
1763 SCLogDebug(
"re %" PRIu64
", raw_progress %" PRIu64, re, progress);
1764 SCLogDebug(
"raw_progress + mydata_len %" PRIu64
", re %" PRIu64, progress + mydata_len,
1768 if (progress + mydata_len > re) {
1769 uint32_t check = mydata_len;
1770 mydata_len = re - progress;
1771 BUG_ON(check < mydata_len);
1772 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1773 "data is considered", mydata_len);
1776 if (mydata_len == 0)
1779 SCLogDebug(
"data %p len %u", mydata, mydata_len);
1782 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1785 if (mydata_offset == progress) {
1786 SCLogDebug(
"progress %"PRIu64
" increasing with data len %u to %"PRIu64,
1787 progress, mydata_len, progress_in + mydata_len);
1789 progress += mydata_len;
1790 SCLogDebug(
"raw progress now %"PRIu64, progress);
1793 }
else if (mydata_offset > progress && mydata_offset < re) {
1794 SCLogDebug(
"GAP: data is missing from %"PRIu64
" (%u bytes), setting to first data we have: %"PRIu64, progress, (uint32_t)(mydata_offset - progress), mydata_offset);
1796 progress = mydata_offset;
1797 SCLogDebug(
"raw progress now %"PRIu64, progress);
1800 SCLogDebug(
"not increasing progress, data gap => mydata_offset "
1801 "%"PRIu64
" != progress %"PRIu64, mydata_offset, progress);
1804 if (iter == NULL || r == 1)
1808 *progress_out = progress;
1813 void *cb_data,
const uint64_t
offset,
const bool eof)
1817 SCLogDebug(
"app_progress %" PRIu64, app_progress);
1819 uint64_t unused = 0;
1820 return StreamReassembleRawDo(
1821 ssn, stream, Callback, cb_data,
offset, app_progress, &unused, eof,
false);
1826 uint64_t *progress_out,
bool respect_inspect_depth)
1830 return StreamReassembleRawInline(ssn, p, Callback, cb_data, progress_out);
1841 StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 0)
1853 SCLogDebug(
"respect_inspect_depth %s STREAMTCP_STREAM_FLAG_TRIGGER_RAW %s "
1854 "stream->min_inspect_depth %u",
1855 respect_inspect_depth ?
"true" :
"false",
1872 SCLogDebug(
"applied min inspect depth due to STREAMTCP_STREAM_FLAG_TRIGGER_RAW: progress "
1882 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1883 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1885 return StreamReassembleRawDo(ssn, stream, Callback, cb_data, progress, last_ack_abs,
1891 uint64_t progress_in,
1892 uint64_t *progress_out,
bool eof)
1898 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1899 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1901 return StreamReassembleRawDo(
1902 ssn, stream, Callback, cb_data, progress_in, last_ack_abs, progress_out, eof,
false);
1910 static int StreamTcpReassembleHandleSegmentUpdateACK (
ThreadVars *
tv,
1929 SCLogDebug(
"ssn %p, stream %p, p %p, p->payload_len %"PRIu16
"",
1956 if (stream == &ssn->
client) {
1957 opposing_stream = &ssn->
server;
1959 opposing_stream = &ssn->
client;
1964 if (StreamTcpReassembleHandleSegmentUpdateACK(
tv, ra_ctx, ssn, opposing_stream, p) != 0) {
1965 SCLogDebug(
"StreamTcpReassembleHandleSegmentUpdateACK error");
1973 if (reversed_before_ack_handling != reversed_after_ack_handling) {
1975 stream = opposing_stream;
1980 SCLogDebug(
"calling StreamTcpReassembleHandleSegmentHandleData");
1983 SCLogDebug(
"StreamTcpReassembleHandleSegmentHandleData error");
1993 SCLogDebug(
"ssn %p / stream %p: not calling StreamTcpReassembleHandleSegmentHandleData:"
1994 " p->payload_len %u, STREAMTCP_STREAM_FLAG_NOREASSEMBLY %s",
2005 if ((stream->
flags &
2009 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED, truncate applayer");
2011 SCLogDebug(
"override: direction now UPDATE_DIR_PACKET so we "
2012 "can trigger Truncate");
2020 SCLogDebug(
"inline (%s) or PKT_PSEUDO_STREAM_END (%s)",
2071 if (direction == STREAM_TOSERVER) {
2077 SCLogDebug(
"flagged ssn %p for immediate raw reassembly", ssn);
2088 if (direction == STREAM_TOSERVER) {
2090 SCLogDebug(
"ssn %p: set client.min_inspect_depth to %u", ssn, depth);
2093 SCLogDebug(
"ssn %p: set server.min_inspect_depth to %u", ssn, depth);
2101 #define SET_ISN(stream, setseq) \
2102 (stream)->isn = (setseq); \
2103 (stream)->base_seq = (setseq) + 1
2121 for (; i <
len; i++)
2145 data, data_len) == 0)
2154 #define MISSED_START(isn) \
2155 TcpReassemblyThreadCtx *ra_ctx = NULL; \
2158 memset(&tv, 0, sizeof(tv)); \
2160 StreamTcpUTInit(&ra_ctx); \
2162 StreamTcpUTSetupSession(&ssn); \
2163 StreamTcpUTSetupStream(&ssn.server, (isn)); \
2164 StreamTcpUTSetupStream(&ssn.client, (isn)); \
2166 TcpStream *stream = &ssn.client;
2168 #define MISSED_END \
2169 StreamTcpUTClearSession(&ssn); \
2170 StreamTcpUTDeinit(ra_ctx); \
2173 #define MISSED_STEP(seq, seg, seglen, buf, buflen) \
2174 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen)); \
2175 FAIL_IF(!(VALIDATE(stream, (uint8_t *)(buf), (buflen))));
2184 static int StreamTcpReassembleTest25 (
void)
2200 static int StreamTcpReassembleTest26 (
void)
2216 static int StreamTcpReassembleTest27 (
void)
2233 static int StreamTcpReassembleTest28 (
void)
2251 static int StreamTcpReassembleTest29 (
void)
2260 static int StreamTcpReassembleTest33(
void)
2269 uint8_t packet[1460] =
"";
2276 memset(&f, 0,
sizeof (
Flow));
2277 memset(&tcph, 0,
sizeof (TCPHdr));
2282 f.
proto = IPPROTO_TCP;
2285 p->
proto = IPPROTO_TCP;
2293 p->
tcph->th_seq = htonl(10);
2294 p->
tcph->th_ack = htonl(31);
2299 p->
tcph->th_seq = htonl(20);
2300 p->
tcph->th_ack = htonl(31);
2305 p->
tcph->th_seq = htonl(40);
2306 p->
tcph->th_ack = htonl(31);
2311 p->
tcph->th_seq = htonl(5);
2312 p->
tcph->th_ack = htonl(31);
2323 static int StreamTcpReassembleTest34(
void)
2332 uint8_t packet[1460] =
"";
2338 memset(&f, 0,
sizeof (
Flow));
2339 memset(&tcph, 0,
sizeof (TCPHdr));
2344 f.
proto = IPPROTO_TCP;
2347 p->
proto = IPPROTO_TCP;
2356 p->
tcph->th_seq = htonl(857961230);
2357 p->
tcph->th_ack = htonl(31);
2362 p->
tcph->th_seq = htonl(857961534);
2363 p->
tcph->th_ack = htonl(31);
2368 p->
tcph->th_seq = htonl(857963582);
2369 p->
tcph->th_ack = htonl(31);
2374 p->
tcph->th_seq = htonl(857960946);
2375 p->
tcph->th_ack = htonl(31);
2394 static int StreamTcpReassembleTest39 (
void)
2404 memset (&f, 0,
sizeof(
Flow));
2406 memset(&stt, 0,
sizeof (stt));
2407 memset(&tcph, 0,
sizeof (TCPHdr));
2411 f.
proto = IPPROTO_TCP;
2418 tcph.th_win = htons(5480);
2443 p->
tcph->th_ack = htonl(1);
2464 p->
tcph->th_ack = htonl(1);
2465 p->
tcph->th_seq = htonl(1);
2486 uint8_t request1[] = { 0x47, 0x45, };
2487 p->
tcph->th_ack = htonl(1);
2488 p->
tcph->th_seq = htonl(1);
2510 p->
tcph->th_ack = htonl(3);
2511 p->
tcph->th_seq = htonl(1);
2533 uint8_t request2[] = {
2534 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
2535 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
2536 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
2537 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
2538 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
2539 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
2540 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
2541 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
2542 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
2543 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
2544 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
2545 p->
tcph->th_ack = htonl(1);
2546 p->
tcph->th_seq = htonl(3);
2569 uint8_t response[] = {
2570 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
2571 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
2572 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
2573 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
2574 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
2575 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
2576 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
2577 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
2578 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
2579 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
2580 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
2581 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
2582 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
2583 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
2584 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
2585 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
2586 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
2587 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
2588 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
2589 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
2590 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
2591 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
2592 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
2593 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
2594 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
2595 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
2596 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
2597 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
2598 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
2599 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
2600 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
2601 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
2602 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
2603 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
2604 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
2605 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
2606 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
2607 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
2608 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
2609 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
2610 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
2611 p->
tcph->th_ack = htonl(88);
2612 p->
tcph->th_seq = htonl(1);
2636 p->
tcph->th_ack = htonl(328);
2637 p->
tcph->th_seq = htonl(88);
2661 p->
tcph->th_ack = htonl(88);
2662 p->
tcph->th_seq = htonl(328);
2686 p->
tcph->th_ack = htonl(328);
2687 p->
tcph->th_seq = htonl(88);
2710 p->
tcph->th_ack = htonl(88);
2711 p->
tcph->th_seq = htonl(328);
2736 p->
tcph->th_ack = htonl(328);
2737 p->
tcph->th_seq = htonl(88);
2761 p->
tcph->th_ack = htonl(90);
2762 p->
tcph->th_seq = htonl(328);
2787 p->
tcph->th_ack = htonl(328);
2788 p->
tcph->th_seq = htonl(90);
2813 p->
tcph->th_ack = htonl(175);
2814 p->
tcph->th_seq = htonl(328);
2840 p->
tcph->th_ack = htonl(175);
2841 p->
tcph->th_seq = htonl(328);
2857 p->
tcph->th_ack = htonl(328);
2858 p->
tcph->th_seq = htonl(175);
2878 static int StreamTcpReassembleTest40 (
void)
2887 memset(&tcph, 0,
sizeof (TCPHdr));
2897 uint8_t httpbuf1[] =
"P";
2898 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
2899 uint8_t httpbuf3[] =
"O";
2900 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
2901 uint8_t httpbuf4[] =
"S";
2902 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
2903 uint8_t httpbuf5[] =
"T \r\n";
2904 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
2906 uint8_t httpbuf2[] =
"HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
2907 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
2914 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
2917 f->
proto = IPPROTO_TCP;
2920 tcph.th_win = htons(5480);
2921 tcph.th_seq = htonl(10);
2922 tcph.th_ack = htonl(10);
2936 tcph.th_seq = htonl(10);
2937 tcph.th_ack = htonl(11);
2946 tcph.th_seq = htonl(11);
2947 tcph.th_ack = htonl(55);
2956 tcph.th_seq = htonl(55);
2957 tcph.th_ack = htonl(12);
2971 tcph.th_seq = htonl(12);
2972 tcph.th_ack = htonl(100);
2981 tcph.th_seq = htonl(100);
2982 tcph.th_ack = htonl(13);
2991 tcph.th_seq = htonl(13);
2992 tcph.th_ack = htonl(145);
3001 tcph.th_seq = htonl(145);
3002 tcph.th_ack = htonl(16);
3018 static int StreamTcpReassembleTest44(
void)
3039 static int StreamTcpReassembleTest45 (
void)
3044 memset(&
tv, 0,
sizeof(
tv));
3045 uint8_t payload[100] = {0};
3046 uint16_t payload_size = 100;
3077 static int StreamTcpReassembleTest46 (
void)
3083 memset(&
tv, 0,
sizeof(
tv));
3084 uint8_t payload[100] = {0};
3085 uint16_t payload_size = 100;
3098 printf(
"STREAMTCP_STREAM_FLAG_NOREASSEMBLY set: ");
3106 printf(
"STREAMTCP_STREAM_FLAG_NOREASSEMBLY set: ");
3126 static int StreamTcpReassembleTest47 (
void)
3136 memset(&tcph, 0,
sizeof (TCPHdr));
3142 uint8_t httpbuf1[] =
"GET /EVILSUFF HTTP/1.1\r\n\r\n";
3143 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3151 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3154 f->
proto = IPPROTO_TCP;
3157 tcph.th_win = htons(5480);
3162 for (cnt=0; cnt < httplen1; cnt++) {
3163 tcph.th_seq = htonl(ssn.
client.
isn + 1 + cnt);
3164 tcph.th_ack = htonl(572799782UL);
3177 tcph.th_seq = htonl(572799782UL);
3178 tcph.th_ack = htonl(ssn.
client.
isn + 1 + cnt);
3197 static int StreamTcpReassembleInlineTest01(
void)
3205 memset(&
tv, 0x00,
sizeof(
tv));
3213 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3216 printf(
"couldn't get a packet: ");
3219 p->
tcph->th_seq = htonl(12);
3223 printf(
"failed to add segment 1: ");
3227 printf(
"failed to add segment 2: ");
3231 printf(
"failed to add segment 3: ");
3247 static int StreamTcpReassembleInlineTest02(
void)
3255 memset(&
tv, 0x00,
sizeof(
tv));
3263 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3266 printf(
"couldn't get a packet: ");
3269 p->
tcph->th_seq = htonl(12);
3273 printf(
"failed to add segment 1: ");
3277 printf(
"failed to add segment 2: ");
3281 printf(
"failed to add segment 3: ");
3286 printf(
"failed to add segment 4: ");
3303 static int StreamTcpReassembleInlineTest03(
void)
3311 memset(&
tv, 0x00,
sizeof(
tv));
3321 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3324 printf(
"couldn't get a packet: ");
3327 p->
tcph->th_seq = htonl(12);
3332 printf(
"failed to add segment 1: ");
3336 printf(
"failed to add segment 2: ");
3340 printf(
"failed to add segment 3: ");
3345 printf(
"failed to add segment 4: ");
3350 p->
tcph->th_seq = htonl(17);
3364 static int StreamTcpReassembleInlineTest04(
void)
3372 memset(&
tv, 0x00,
sizeof(
tv));
3382 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3385 printf(
"couldn't get a packet: ");
3388 p->
tcph->th_seq = htonl(12);
3393 printf(
"failed to add segment 1: ");
3397 printf(
"failed to add segment 2: ");
3401 printf(
"failed to add segment 3: ");
3406 printf(
"failed to add segment 4: ");
3411 p->
tcph->th_seq = htonl(17);
3426 static int StreamTcpReassembleInlineTest08(
void)
3430 memset(&
tv, 0x00,
sizeof(
tv));
3442 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3445 p->
tcph->th_seq = htonl(12);
3455 p->
tcph->th_seq = htonl(17);
3474 static int StreamTcpReassembleInlineTest09(
void)
3482 memset(&
tv, 0x00,
sizeof(
tv));
3492 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3495 printf(
"couldn't get a packet: ");
3498 p->
tcph->th_seq = htonl(17);
3503 printf(
"failed to add segment 1: ");
3507 printf(
"failed to add segment 2: ");
3511 printf(
"failed to add segment 3: ");
3519 printf(
"failed to add segment 4: ");
3524 p->
tcph->th_seq = htonl(12);
3541 static int StreamTcpReassembleInlineTest10(
void)
3550 memset(&
tv, 0x00,
sizeof(
tv));
3561 f =
UTHBuildFlow(AF_INET,
"1.1.1.1",
"2.2.2.2", 1024, 80);
3565 f->
proto = IPPROTO_TCP;
3567 uint8_t stream_payload1[] =
"GE";
3568 uint8_t stream_payload2[] =
"T /";
3569 uint8_t stream_payload3[] =
"HTTP/1.0\r\n\r\n";
3571 p =
UTHBuildPacketReal(stream_payload3, 12, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
3573 printf(
"couldn't get a packet: ");
3576 p->
tcph->th_seq = htonl(7);
3581 printf(
"failed to add segment 1: ");
3588 printf(
"StreamTcpReassembleAppLayer failed: ");
3594 printf(
"expected ra_app_base_seq 1, got %u: ", ssn.
client.
base_seq);
3599 printf(
"failed to add segment 2: ");
3603 printf(
"failed to add segment 3: ");
3610 printf(
"StreamTcpReassembleAppLayer failed: ");
3627 static int StreamTcpReassembleInsertTest01(
void)
3634 memset(&
tv, 0x00,
sizeof(
tv));
3642 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3645 p->
tcph->th_seq = htonl(12);
3664 static int StreamTcpReassembleInsertTest02(
void)
3671 memset(&
tv, 0x00,
sizeof(
tv));
3678 for (i = 2; i < 10; i++) {
3689 printf(
"failed to add segment 1: ");
3694 printf(
"failed to add segment 2: ");
3707 static int StreamTcpReassembleInsertTest03(
void)
3714 memset(&
tv, 0x00,
sizeof(
tv));
3721 printf(
"failed to add segment 2: ");
3726 for (i = 2; i < 10; i++) {
3737 printf(
"failed to add segment 2: ");
3758 UtRegisterTest(
"StreamTcpReassembleTest25 -- Gap at Start Reassembly Test",
3759 StreamTcpReassembleTest25);
3760 UtRegisterTest(
"StreamTcpReassembleTest26 -- Gap at middle Reassembly Test",
3761 StreamTcpReassembleTest26);
3762 UtRegisterTest(
"StreamTcpReassembleTest27 -- Gap at after Reassembly Test",
3763 StreamTcpReassembleTest27);
3764 UtRegisterTest(
"StreamTcpReassembleTest28 -- Gap at Start IDS missed packet Reassembly Test",
3765 StreamTcpReassembleTest28);
3766 UtRegisterTest(
"StreamTcpReassembleTest29 -- Gap at Middle IDS missed packet Reassembly Test",
3767 StreamTcpReassembleTest29);
3769 StreamTcpReassembleTest33);
3771 StreamTcpReassembleTest34);
3773 StreamTcpReassembleTest39);
3775 StreamTcpReassembleTest40);
3777 StreamTcpReassembleTest44);
3779 StreamTcpReassembleTest45);
3781 StreamTcpReassembleTest46);
3782 UtRegisterTest(
"StreamTcpReassembleTest47 -- TCP Sequence Wraparound Test",
3783 StreamTcpReassembleTest47);
3785 UtRegisterTest(
"StreamTcpReassembleInlineTest01 -- inline RAW ra",
3786 StreamTcpReassembleInlineTest01);
3787 UtRegisterTest(
"StreamTcpReassembleInlineTest02 -- inline RAW ra 2",
3788 StreamTcpReassembleInlineTest02);
3789 UtRegisterTest(
"StreamTcpReassembleInlineTest03 -- inline RAW ra 3",
3790 StreamTcpReassembleInlineTest03);
3791 UtRegisterTest(
"StreamTcpReassembleInlineTest04 -- inline RAW ra 4",
3792 StreamTcpReassembleInlineTest04);
3793 UtRegisterTest(
"StreamTcpReassembleInlineTest08 -- inline RAW ra 8 cleanup",
3794 StreamTcpReassembleInlineTest08);
3795 UtRegisterTest(
"StreamTcpReassembleInlineTest09 -- inline RAW ra 9 GAP cleanup",
3796 StreamTcpReassembleInlineTest09);
3798 UtRegisterTest(
"StreamTcpReassembleInlineTest10 -- inline APP ra 10",
3799 StreamTcpReassembleInlineTest10);
3801 UtRegisterTest(
"StreamTcpReassembleInsertTest01 -- insert with overlap",
3802 StreamTcpReassembleInsertTest01);
3803 UtRegisterTest(
"StreamTcpReassembleInsertTest02 -- insert with overlap",
3804 StreamTcpReassembleInsertTest02);
3805 UtRegisterTest(
"StreamTcpReassembleInsertTest03 -- insert with overlap",
3806 StreamTcpReassembleInsertTest03);
3811 StreamTcpReassembleRawRegisterTests();