75 static SCMutex segment_pool_memuse_mutex;
76 static uint64_t segment_pool_memuse = 0;
77 static uint64_t segment_pool_memcnt = 0;
80 thread_local uint64_t t_pcapcnt = UINT64_MAX;
90 static int g_tcp_session_dump_enabled = 0;
94 return g_tcp_session_dump_enabled == 1;
99 g_tcp_session_dump_enabled = 1;
117 static void StreamTcpReassembleIncrMemuse(uint64_t size)
130 static void StreamTcpReassembleDecrMemuse(uint64_t size)
135 BUG_ON(presize > UINT_MAX);
144 BUG_ON(postsize > presize);
168 if (
unlikely((g_eps_stream_reassembly_memcap != UINT64_MAX &&
169 g_eps_stream_reassembly_memcap == t_pcapcnt))) {
170 SCLogNotice(
"simulating memcap reached condition for packet %" PRIu64, t_pcapcnt);
175 if (memcapcopy == 0 ||
176 (uint64_t)((uint64_t)size +
SC_ATOMIC_GET(ra_memuse)) <= memcapcopy)
188 if (size == 0 || (uint64_t)
SC_ATOMIC_GET(ra_memuse) < size) {
212 static void *ReassembleCalloc(
size_t n,
size_t size)
223 StreamTcpReassembleIncrMemuse(n * size);
232 if (size > orig_size) {
245 if (size > orig_size) {
246 StreamTcpReassembleIncrMemuse(size - orig_size);
248 StreamTcpReassembleDecrMemuse(orig_size - size);
256 static void ReassembleFree(
void *ptr,
size_t size)
259 StreamTcpReassembleDecrMemuse(size);
263 static void *TcpSegmentPoolAlloc(
void)
285 "TcpSegmentPcapHdrStorage");
294 "packet header data within "
295 "TcpSegmentPcapHdrStorage");
301 StreamTcpReassembleIncrMemuse(memuse);
309 static int TcpSegmentPoolInit(
void *data)
327 StreamTcpReassembleIncrMemuse(memuse);
337 segment_pool_memcnt++;
338 SCLogDebug(
"segment_pool_memcnt %"PRIu64
"", segment_pool_memcnt);
342 StreamTcpReassembleIncrMemuse((uint32_t)
sizeof(
TcpSegment));
347 static void TcpSegmentPoolCleanup(
void *ptr)
363 StreamTcpReassembleDecrMemuse((uint32_t)
sizeof(
TcpSegment));
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)) {
419 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
426 uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
428 right_edge =
MIN(GetAbsLastAck(stream), right_edge);
456 f->
alparser, (APP_LAYER_PARSER_EOF_TS | APP_LAYER_PARSER_EOF_TC));
470 static int StreamTcpReassemblyConfig(
bool quiet)
472 uint32_t segment_prealloc = 2048;
475 uint32_t prealloc = 0;
482 segment_prealloc = prealloc;
485 SCLogConfig(
"stream.reassembly \"segment-prealloc\": %u", segment_prealloc);
488 int overlap_diff_data = 0;
489 (void)
SCConfGetBool(
"stream.reassembly.check-overlap-different-data", &overlap_diff_data);
490 if (overlap_diff_data) {
497 uint16_t max_regions = 8;
508 SCLogConfig(
"stream.reassembly \"max-regions\": %u", max_regions);
526 if (StreamTcpReassemblyConfig(quiet) < 0)
548 if (segment_pool_memuse > 0)
549 SCLogDebug(
"segment_pool_memuse %" PRIu64
" segment_pool_memcnt %" PRIu64
"",
550 segment_pool_memuse, segment_pool_memcnt);
569 TcpSegmentPoolInit, TcpSegmentPoolCleanup);
571 SCLogDebug(
"pool size %d, thread segment_thread_pool_id %d",
577 SCLogDebug(
"pool size %d, thread segment_thread_pool_id %d",
583 SCLogError(
"failed to setup/expand stream segment pool. Expand stream.reassembly.memcap?");
603 static void StreamTcpReassembleExceptionPolicyStatsIncr(
649 uint32_t
seq, uint32_t size)
667 SCLogDebug(
"segment entirely before base_seq, weird: base %u, seq %u, re %u",
681 SCLogDebug(
"seq + size %u, base %u, seg_depth %"PRIu64
" limit %u", (
seq + size),
686 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
690 SCLogDebug(
"NOT STREAMTCP_STREAM_FLAG_DEPTH_REACHED");
693 SCLogDebug(
"full depth not yet reached: %"PRIu64
" <= %"PRIu32,
694 (stream->base_seq_offset + stream->
base_seq + size),
761 SCLogDebug(
"ssn %p: both app and raw reassembly disabled, not reassembling", ssn);
765 uint16_t *urg_offset;
772 const TCPHdr *tcph = PacketGetTCP(
p);
776 uint8_t urg_data = 0;
786 if ((*urg_offset) < UINT16_MAX) {
790 if ((*urg_offset) == UINT16_MAX) {
807 (*urg_offset) == UINT16_MAX &&
823 uint32_t size = StreamTcpReassembleCheckDepth(ssn, stream, seg_seq,
payload_len);
824 SCLogDebug(
"ssn %p: check depth returned %"PRIu32, ssn, size);
833 SCLogDebug(
"ssn %p: depth reached, not reassembling", ssn);
870 SCLogDebug(
"StreamTcpReassembleInsertSegment failed");
882 flag |= STREAM_START;
890 flag |= STREAM_MIDSTREAM;
897 if (&ssn->
client == stream) {
898 flag |= STREAM_TOSERVER;
900 flag |= STREAM_TOCLIENT;
903 flag |= STREAM_DEPTH;
914 static bool StreamTcpReassembleRawCheckLimit(
920 #define STREAMTCP_STREAM_FLAG_FLUSH_FLAGS \
921 ( STREAMTCP_STREAM_FLAG_DEPTH_REACHED \
922 | STREAMTCP_STREAM_FLAG_TRIGGER_RAW \
923 | STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED)
927 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_DEPTH_REACHED "
928 "is set, so not expecting any new data segments");
931 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_TRIGGER_RAW is set");
934 SCLogDebug(
"reassembling now as STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED is set, "
935 "so no new segments will be considered");
939 #undef STREAMTCP_STREAM_FLAG_FLUSH_FLAGS
948 const uint64_t last_ack_abs = GetAbsLastAck(stream);
954 if (chunk_size <= diff) {
957 SCLogDebug(
"%s min chunk len not yet reached: "
958 "last_ack %" PRIu32
", ra_raw_base_seq %" PRIu32
", %" PRIu32
" < "
975 const char *dirstr = NULL;
977 if (direction == STREAM_TOSERVER) {
1001 const uint64_t right_edge =
1003 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
1004 " (use: %s). Stream right edge: %" PRIu64,
1008 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
1013 const uint64_t right_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
1014 SCLogDebug(
"%s: app %" PRIu64
" (use: %s), raw %" PRIu64
1015 " (use: %s). Stream right edge: %" PRIu64,
1019 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr);
1024 SCLogDebug(
"%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NONE", dirstr);
1029 static uint64_t GetStreamSize(
TcpStream *stream)
1034 uint64_t last_ack_abs = GetAbsLastAck(stream);
1035 uint64_t last_re = 0;
1041 const uint64_t seg_abs =
1043 if (last_re != 0 && last_re < seg_abs) {
1044 const char *gacked = NULL;
1045 if (last_ack_abs >= seg_abs) {
1046 gacked =
"fully ack'd";
1047 }
else if (last_ack_abs > last_re) {
1048 gacked =
"partly ack'd";
1050 gacked =
"not yet ack'd";
1052 SCLogDebug(
" -> gap of size %" PRIu64
", ack:%s", seg_abs - last_re, gacked);
1055 const char *acked = NULL;
1056 if (last_ack_abs >= seg_abs + (uint64_t)
TCP_SEG_LEN(seg)) {
1057 acked =
"fully ack'd";
1058 }
else if (last_ack_abs > seg_abs) {
1059 acked =
"partly ack'd";
1061 acked =
"not yet ack'd";
1064 SCLogDebug(
"%u -> seg %p seq %u abs %" PRIu64
" size %u abs %" PRIu64
" (%" PRIu64
1083 size = GetStreamSize(&ssn->
client);
1084 size += GetStreamSize(&ssn->
server);
1097 GetAbsLastAck(stream) > (cur_blk->
offset + cur_blk->
len);
1109 static bool GetAppBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1110 uint64_t
offset,
const bool check_for_gap)
1112 const uint8_t *mydata;
1113 uint32_t mydata_len;
1114 bool gap_ahead =
false;
1122 *data_len = mydata_len;
1141 gap_ahead = check_for_gap && GapAhead(stream, blk);
1145 SCLogDebug(
"gap, want data at offset %"PRIu64
", "
1146 "got data at %"PRIu64
". GAP of size %"PRIu64,
1153 SCLogDebug(
"get data from offset %"PRIu64
". SBB %"PRIu64
"/%u",
1156 SCLogDebug(
"data %p, data_len %u", *data, *data_len);
1158 gap_ahead = check_for_gap && GapAhead(stream, blk);
1177 const uint64_t last_ack_abs = GetAbsLastAck(stream) - (uint64_t)ackadded;
1184 if (last_ack_abs > app_progress) {
1191 "next_seq %u < last_ack %u, but no data in list",
1195 const uint64_t next_seq_abs =
1198 if (blk->
offset > next_seq_abs && blk->
offset < last_ack_abs) {
1201 "next_seq %u < last_ack %u, but ACK'd data beyond gap.",
1208 "last_ack_abs %" PRIu64
" > app_progress %" PRIu64
", "
1209 "but we have no data.",
1214 "last_ack_abs %" PRIu64
" <= app_progress %" PRIu64,
1219 static inline uint32_t AdjustToAcked(
const Packet *
p,
1221 const uint64_t app_progress,
const uint32_t data_len)
1223 uint32_t adjusted = data_len;
1234 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1238 if (app_progress <= last_ack_abs && app_progress + data_len > last_ack_abs) {
1239 adjusted = (uint32_t)(last_ack_abs - app_progress);
1241 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1242 "data is considered", adjusted);
1259 SCLogDebug(
"app progress %"PRIu64, app_progress);
1261 uint64_t last_ack_abs = GetAbsLastAck(*stream);
1262 SCLogDebug(
"last_ack %u (abs %" PRIu64
"), base_seq %u", (*stream)->last_ack, last_ack_abs,
1263 (*stream)->base_seq);
1265 const uint8_t *mydata;
1266 uint32_t mydata_len;
1267 bool last_was_gap =
false;
1270 const uint8_t
flags = StreamGetAppLayerFlags(ssn, *stream,
p);
1271 bool check_for_gap_ahead = ((*stream)->data_required > 0);
1273 GetAppBuffer(*stream, &mydata, &mydata_len, app_progress, check_for_gap_ahead);
1275 if (last_was_gap && mydata_len == 0) {
1278 last_was_gap =
false;
1281 mydata_len = AdjustToAcked(
p, ssn, *stream, app_progress, mydata_len);
1283 if (mydata == NULL && mydata_len > 0 && CheckGap(ssn, *stream,
p)) {
1284 SCLogDebug(
"sending GAP to app-layer (size: %u)", mydata_len);
1287 StreamGetAppLayerFlags(ssn, *stream,
p) | STREAM_GAP, app_update_dir);
1301 if ((*stream)->data_required > 0) {
1302 if ((*stream)->data_required > mydata_len) {
1303 (*stream)->data_required -= mydata_len;
1305 (*stream)->data_required = 0;
1310 if (no_progress_update)
1312 last_was_gap =
true;
1315 }
else if (
flags & STREAM_DEPTH) {
1318 if (mydata == NULL && mydata_len > 0) {
1321 }
else if (mydata == NULL || (mydata_len == 0 && ((
flags & STREAM_EOF) == 0))) {
1334 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1335 *stream, &(*stream)->sb, mydata_len, app_progress);
1339 if (mydata_len < (*stream)->data_required) {
1342 SCLogDebug(
"GAP while expecting more data (expect %u, gap size %u)",
1343 (*stream)->data_required, mydata_len);
1344 (*stream)->app_progress_rel += mydata_len;
1345 (*stream)->data_required -= mydata_len;
1355 (*stream)->data_required = 0;
1360 mydata_len,
flags, app_update_dir);
1366 app_progress = new_app_progress;
1367 if (
flags & STREAM_DEPTH)
1395 SCLogDebug(
"stream no reassembly flag set or app-layer disabled.");
1401 GetSessionSize(ssn,
p);
1412 uint8_t stream_flags = StreamGetAppLayerFlags(ssn, stream,
p);
1414 tv, ra_ctx,
p,
p->
flow, ssn, &stream, NULL, 0, stream_flags, app_update_dir);
1422 return ReassembleUpdateAppLayer(
tv, ra_ctx, ssn, &stream,
p, app_update_dir);
1428 static int GetRawBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1431 const uint8_t *mydata;
1432 uint32_t mydata_len;
1437 uint64_t roffset =
offset;
1445 *data_len = mydata_len;
1446 *data_offset = roffset;
1448 SCLogDebug(
"multiblob %s. Want offset %"PRIu64,
1449 *iter == NULL ?
"starting" :
"continuing",
offset);
1450 if (*iter == NULL) {
1455 if (*iter == NULL) {
1462 SCLogDebug(
"getting multiple blobs. Iter %p, %"PRIu64
"/%u", *iter, (*iter)->offset, (*iter)->len);
1467 if ((*iter)->offset <
offset) {
1468 uint64_t delta =
offset - (*iter)->offset;
1469 if (delta < mydata_len) {
1470 *data = mydata + delta;
1471 *data_len = (uint32_t)(mydata_len - delta);
1482 *data_len = mydata_len;
1483 *data_offset = (*iter)->offset;
1486 *iter = SBB_RB_NEXT(*iter);
1517 const uint64_t segs_re_abs =
1522 if (StreamTcpReassembleRawCheckLimit(ssn, stream,
p) == 1) {
1560 }
else if (progress == 0) {
1565 target = GetAbsLastAck(stream);
1575 SCLogDebug(
"pcap_cnt %" PRIu64
": progress %" PRIu64
" app %" PRIu64
" raw %" PRIu64
1576 " tcp win %" PRIu32,
1585 SCLogDebug(
"ssn %p: STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED set, "
1586 "now that detect ran also set STREAMTCP_STREAM_FLAG_DISABLE_RAW", ssn);
1633 "packet payload len %u, so chunk_size adjusted to %u",
p->
payload_len, chunk_size);
1636 const TCPHdr *tcph = PacketGetTCP(
p);
1641 uint64_t packet_rightedge_abs = packet_leftedge_abs +
p->
payload_len;
1642 SCLogDebug(
"packet_leftedge_abs %"PRIu64
", rightedge %"PRIu64,
1643 packet_leftedge_abs, packet_rightedge_abs);
1645 const uint8_t *mydata = NULL;
1646 uint32_t mydata_len = 0;
1647 uint64_t mydata_offset = 0;
1649 bool return_progress =
false;
1654 return_progress =
true;
1657 SCLogDebug(
"finding our SBB from offset %"PRIu64, packet_leftedge_abs);
1664 mydata_offset = sbb->
offset;
1669 uint64_t mydata_rightedge_abs = mydata_offset + mydata_len;
1670 if ((mydata == NULL || mydata_len == 0) ||
1671 (mydata_offset >= packet_rightedge_abs ||
1672 packet_leftedge_abs >= mydata_rightedge_abs) ||
1673 (packet_leftedge_abs < mydata_offset ||
1674 packet_rightedge_abs > mydata_rightedge_abs))
1679 mydata_offset = packet_leftedge_abs;
1683 SCLogDebug(
"chunk_size %u mydata_len %u", chunk_size, mydata_len);
1684 if (mydata_len > chunk_size) {
1685 uint32_t excess = mydata_len - chunk_size;
1686 SCLogDebug(
"chunk_size %u mydata_len %u excess %u", chunk_size, mydata_len, excess);
1688 if (mydata_rightedge_abs == packet_rightedge_abs) {
1690 mydata_len -= excess;
1691 mydata_offset += excess;
1692 SCLogDebug(
"cutting front of the buffer with %u", excess);
1693 }
else if (mydata_offset == packet_leftedge_abs) {
1694 mydata_len -= excess;
1695 SCLogDebug(
"cutting tail of the buffer with %u", excess);
1698 uint32_t abs_before = (uint32_t)(packet_leftedge_abs - mydata_offset);
1700 uint32_t abs_after = (uint32_t)(mydata_rightedge_abs - packet_rightedge_abs);
1701 uint32_t before = abs_before;
1702 uint32_t after = abs_after;
1703 SCLogDebug(
"before %u after %u", before, after);
1728 uint32_t skip = abs_before - before;
1730 uint32_t cut = abs_after - after;
1735 mydata_len -= (skip + cut);
1736 mydata_offset += skip;
1742 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1745 if (return_progress) {
1746 *progress_out = (mydata_offset + mydata_len);
1753 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1754 SCLogDebug(
"last_ack_abs %"PRIu64, last_ack_abs);
1757 if (mydata_offset > last_ack_abs) {
1759 *progress_out = last_ack_abs;
1761 *progress_out = (mydata_offset + mydata_len);
1800 const uint64_t re, uint64_t *progress_out,
bool eof)
1806 uint64_t progress = progress_in;
1811 const uint8_t *mydata;
1812 uint32_t mydata_len;
1813 uint64_t mydata_offset = 0;
1815 GetRawBuffer(stream, &mydata, &mydata_len, &iter, progress, &mydata_offset);
1816 if (mydata_len == 0) {
1822 SCLogDebug(
"raw progress %"PRIu64, progress);
1823 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1824 stream, &stream->
sb, mydata_len, progress);
1829 if (re < progress) {
1834 SCLogDebug(
"re %" PRIu64
", raw_progress %" PRIu64, re, progress);
1835 SCLogDebug(
"raw_progress + mydata_len %" PRIu64
", re %" PRIu64, progress + mydata_len,
1839 if (progress + mydata_len > re) {
1840 #ifdef DEBUG_VALIDATION
1841 uint32_t check = mydata_len;
1843 mydata_len = (uint32_t)(re - progress);
1845 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1846 "data is considered", mydata_len);
1849 if (mydata_len == 0)
1852 SCLogDebug(
"data %p len %u", mydata, mydata_len);
1855 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1858 if (mydata_offset == progress) {
1859 SCLogDebug(
"progress %"PRIu64
" increasing with data len %u to %"PRIu64,
1860 progress, mydata_len, progress_in + mydata_len);
1862 progress += mydata_len;
1863 SCLogDebug(
"raw progress now %"PRIu64, progress);
1866 }
else if (mydata_offset > progress && mydata_offset < re) {
1867 SCLogDebug(
"GAP: data is missing from %"PRIu64
" (%u bytes), setting to first data we have: %"PRIu64, progress, (uint32_t)(mydata_offset - progress), mydata_offset);
1869 progress = mydata_offset;
1870 SCLogDebug(
"raw progress now %"PRIu64, progress);
1874 }
else if (mydata_offset > progress && mydata_offset == re) {
1875 SCLogDebug(
"mydata_offset %" PRIu64
", progress %" PRIu64
", re %" PRIu64,
1876 mydata_offset, progress, re);
1879 SCLogDebug(
"not increasing progress, data gap => mydata_offset "
1880 "%"PRIu64
" != progress %"PRIu64, mydata_offset, progress);
1883 if (iter == NULL || r == 1)
1887 *progress_out = progress;
1892 void *cb_data,
const uint64_t
offset,
const bool eof)
1896 SCLogDebug(
"app_progress %" PRIu64, app_progress);
1898 uint64_t unused = 0;
1899 return StreamReassembleRawDo(
1900 ssn, stream, Callback, cb_data,
offset, app_progress, &unused, eof);
1905 uint64_t *progress_out,
bool respect_inspect_depth)
1909 return StreamReassembleRawInline(ssn,
p, Callback, cb_data, progress_out);
1920 StreamTcpReassembleRawCheckLimit(ssn, stream,
p) == 0)
1932 SCLogDebug(
"respect_inspect_depth %s STREAMTCP_STREAM_FLAG_TRIGGER_RAW %s "
1933 "stream->min_inspect_depth %u",
1934 respect_inspect_depth ?
"true" :
"false",
1951 SCLogDebug(
"applied min inspect depth due to STREAMTCP_STREAM_FLAG_TRIGGER_RAW: progress "
1961 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1962 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1964 return StreamReassembleRawDo(ssn, stream, Callback, cb_data, progress, last_ack_abs,
1970 uint64_t *progress_out,
const bool eof)
1976 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1977 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1979 return StreamReassembleRawDo(
1980 ssn, stream, Callback, cb_data, progress_in, last_ack_abs, progress_out, eof);
1988 static int StreamTcpReassembleHandleSegmentUpdateACK (
ThreadVars *
tv,
2005 const TCPHdr *tcph = PacketGetTCP(
p);
2007 SCLogDebug(
"ssn %p, stream %p, p %p, p->payload_len %"PRIu16
"",
2037 if (stream == &ssn->
client) {
2038 opposing_stream = &ssn->
server;
2040 opposing_stream = &ssn->
client;
2045 if (StreamTcpReassembleHandleSegmentUpdateACK(
tv, ra_ctx, ssn, opposing_stream,
p) != 0) {
2046 SCLogDebug(
"StreamTcpReassembleHandleSegmentUpdateACK error");
2054 if (reversed_before_ack_handling != reversed_after_ack_handling) {
2056 stream = opposing_stream;
2062 SCLogDebug(
"calling StreamTcpReassembleHandleSegmentHandleData");
2065 SCLogDebug(
"StreamTcpReassembleHandleSegmentHandleData error");
2069 StreamTcpReassembleExceptionPolicyStatsIncr(
2077 SCLogDebug(
"ssn %p / stream %p: not calling StreamTcpReassembleHandleSegmentHandleData:"
2078 " p->payload_len %u, STREAMTCP_STREAM_FLAG_NOREASSEMBLY %s",
2088 if ((stream->
flags &
2092 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED, truncate applayer");
2094 SCLogDebug(
"override: direction now UPDATE_DIR_PACKET so we "
2095 "can trigger Truncate");
2103 SCLogDebug(
"inline (%s) or PKT_PSEUDO_STREAM_END (%s)",
2161 if (direction == STREAM_TOSERVER) {
2167 SCLogDebug(
"flagged ssn %p for immediate raw reassembly", ssn);
2178 if (direction == STREAM_TOSERVER) {
2180 SCLogDebug(
"ssn %p: set client.min_inspect_depth to %u", ssn, depth);
2183 SCLogDebug(
"ssn %p: set server.min_inspect_depth to %u", ssn, depth);
2191 #define SET_ISN(stream, setseq) \
2192 (stream)->isn = (setseq); \
2193 (stream)->base_seq = (setseq) + 1
2211 for (; i <
len; i++)
2225 data, data_len) == 0)
2234 #define MISSED_START(isn) \
2235 TcpReassemblyThreadCtx *ra_ctx = NULL; \
2238 memset(&tv, 0, sizeof(tv)); \
2240 StreamTcpUTInit(&ra_ctx); \
2242 StreamTcpUTSetupSession(&ssn); \
2243 StreamTcpUTSetupStream(&ssn.server, (isn)); \
2244 StreamTcpUTSetupStream(&ssn.client, (isn)); \
2246 TcpStream *stream = &ssn.client;
2248 #define MISSED_END \
2249 StreamTcpUTClearSession(&ssn); \
2250 StreamTcpUTDeinit(ra_ctx); \
2253 #define MISSED_STEP(seq, seg, seglen, buf, buflen) \
2254 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen)); \
2255 FAIL_IF(!(VALIDATE(stream, (uint8_t *)(buf), (buflen))));
2257 #define MISSED_ADD_PAYLOAD(seq, seg, seglen) \
2258 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen));
2265 uint64_t last_re = 0;
2269 if (sbb->
offset != last_re) {
2289 uint64_t last_re = 0;
2293 if (sbb->
offset != last_re) {
2299 const uint8_t *buf = NULL;
2300 uint32_t buf_len = 0;
2303 if (
len == buf_len) {
2304 return (memcmp(data, buf,
len) == 0);
2321 static int StreamTcpReassembleTest25 (
void)
2342 static int StreamTcpReassembleTest26 (
void)
2361 static int StreamTcpReassembleTest27 (
void)
2378 static int StreamTcpReassembleTest28 (
void)
2402 static int StreamTcpReassembleTest29 (
void)
2414 static int StreamTcpReassembleTest33(
void)
2423 uint8_t packet[1460] =
"";
2428 memset(&f, 0,
sizeof (
Flow));
2429 memset(&tcph, 0,
sizeof (
TCPHdr));
2434 f.
proto = IPPROTO_TCP;
2476 static int StreamTcpReassembleTest34(
void)
2485 uint8_t packet[1460] =
"";
2489 memset(&f, 0,
sizeof (
Flow));
2490 memset(&tcph, 0,
sizeof (
TCPHdr));
2495 f.
proto = IPPROTO_TCP;
2507 tcph.
th_seq = htonl(857961230);
2513 tcph.
th_seq = htonl(857961534);
2519 tcph.
th_seq = htonl(857963582);
2525 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);
2966 tcph.
th_ack = htonl(175);
2967 tcph.
th_seq = htonl(328);
2994 tcph.
th_ack = htonl(175);
2995 tcph.
th_seq = htonl(328);
3011 tcph.
th_ack = htonl(328);
3012 tcph.
th_seq = htonl(175);
3033 static int StreamTcpReassembleTest40 (
void)
3040 memset(&tcph, 0,
sizeof (
TCPHdr));
3050 uint8_t httpbuf1[] =
"P";
3051 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3052 uint8_t httpbuf3[] =
"O";
3053 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
3054 uint8_t httpbuf4[] =
"S";
3055 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
3056 uint8_t httpbuf5[] =
"T \r\n";
3057 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
3059 uint8_t httpbuf2[] =
"HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
3060 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3067 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3070 f->
proto = IPPROTO_TCP;
3073 tcph.
th_win = htons(5480);
3125 tcph.
th_ack = htonl(100);
3134 tcph.
th_seq = htonl(100);
3145 tcph.
th_ack = htonl(145);
3154 tcph.
th_seq = htonl(145);
3171 static int StreamTcpReassembleTest44(
void)
3175 StreamTcpReassembleIncrMemuse(500);
3177 StreamTcpReassembleDecrMemuse(500);
3193 static int StreamTcpReassembleTest45 (
void)
3198 memset(&
tv, 0,
sizeof(
tv));
3199 uint8_t payload[100] = {0};
3200 uint16_t payload_size = 100;
3231 static int StreamTcpReassembleTest46 (
void)
3236 memset(&
tv, 0,
sizeof(
tv));
3237 uint8_t payload[100] = {0};
3238 uint16_t payload_size = 100;
3269 static int StreamTcpReassembleTest47 (
void)
3277 memset(&tcph, 0,
sizeof (
TCPHdr));
3284 uint8_t httpbuf1[] =
"GET /EVILSUFF HTTP/1.1\r\n\r\n";
3285 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3293 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3296 f->
proto = IPPROTO_TCP;
3299 tcph.
th_win = htons(5480);
3306 tcph.
th_ack = htonl(572799782UL);
3318 tcph.
th_seq = htonl(572799782UL);
3337 static int StreamTcpReassembleInlineTest01(
void)
3344 memset(&
tv, 0x00,
sizeof(
tv));
3352 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3372 static int StreamTcpReassembleInlineTest02(
void)
3379 memset(&
tv, 0x00,
sizeof(
tv));
3387 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3410 static int StreamTcpReassembleInlineTest03(
void)
3417 memset(&
tv, 0x00,
sizeof(
tv));
3427 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3453 static int StreamTcpReassembleInlineTest04(
void)
3460 memset(&
tv, 0x00,
sizeof(
tv));
3470 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3497 static int StreamTcpReassembleInlineTest08(
void)
3501 memset(&
tv, 0x00,
sizeof(
tv));
3513 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3545 static int StreamTcpReassembleInlineTest09(
void)
3552 memset(&
tv, 0x00,
sizeof(
tv));
3562 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3594 static int StreamTcpReassembleInlineTest10(
void)
3601 memset(&
tv, 0x00,
sizeof(
tv));
3615 f->
proto = IPPROTO_TCP;
3617 uint8_t stream_payload1[] =
"GE";
3618 uint8_t stream_payload2[] =
"T /";
3619 uint8_t stream_payload3[] =
"HTTP/1.0\r\n\r\n";
3655 static int StreamTcpReassembleInsertTest01(
void)
3662 memset(&
tv, 0x00,
sizeof(
tv));
3670 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3692 static int StreamTcpReassembleInsertTest02(
void)
3698 memset(&
tv, 0x00,
sizeof(
tv));
3705 for (i = 2; i < 10; i++) {
3726 static int StreamTcpReassembleInsertTest03(
void)
3732 memset(&
tv, 0x00,
sizeof(
tv));
3741 for (i = 2; i < 10; i++) {
3768 UtRegisterTest(
"StreamTcpReassembleTest25 -- Gap at Start Reassembly Test",
3769 StreamTcpReassembleTest25);
3770 UtRegisterTest(
"StreamTcpReassembleTest26 -- Gap at middle Reassembly Test",
3771 StreamTcpReassembleTest26);
3773 "StreamTcpReassembleTest27 -- Gap at after Reassembly Test", StreamTcpReassembleTest27);
3774 UtRegisterTest(
"StreamTcpReassembleTest28 -- Gap at Start IDS missed packet Reassembly Test",
3775 StreamTcpReassembleTest28);
3776 UtRegisterTest(
"StreamTcpReassembleTest29 -- Gap at Middle IDS missed packet Reassembly Test",
3777 StreamTcpReassembleTest29);
3779 StreamTcpReassembleTest33);
3781 StreamTcpReassembleTest34);
3783 StreamTcpReassembleTest39);
3785 StreamTcpReassembleTest40);
3787 StreamTcpReassembleTest44);
3789 StreamTcpReassembleTest45);
3791 StreamTcpReassembleTest46);
3792 UtRegisterTest(
"StreamTcpReassembleTest47 -- TCP Sequence Wraparound Test",
3793 StreamTcpReassembleTest47);
3795 UtRegisterTest(
"StreamTcpReassembleInlineTest01 -- inline RAW ra",
3796 StreamTcpReassembleInlineTest01);
3797 UtRegisterTest(
"StreamTcpReassembleInlineTest02 -- inline RAW ra 2",
3798 StreamTcpReassembleInlineTest02);
3799 UtRegisterTest(
"StreamTcpReassembleInlineTest03 -- inline RAW ra 3",
3800 StreamTcpReassembleInlineTest03);
3801 UtRegisterTest(
"StreamTcpReassembleInlineTest04 -- inline RAW ra 4",
3802 StreamTcpReassembleInlineTest04);
3803 UtRegisterTest(
"StreamTcpReassembleInlineTest08 -- inline RAW ra 8 cleanup",
3804 StreamTcpReassembleInlineTest08);
3805 UtRegisterTest(
"StreamTcpReassembleInlineTest09 -- inline RAW ra 9 GAP cleanup",
3806 StreamTcpReassembleInlineTest09);
3808 UtRegisterTest(
"StreamTcpReassembleInlineTest10 -- inline APP ra 10",
3809 StreamTcpReassembleInlineTest10);
3811 UtRegisterTest(
"StreamTcpReassembleInsertTest01 -- insert with overlap",
3812 StreamTcpReassembleInsertTest01);
3813 UtRegisterTest(
"StreamTcpReassembleInsertTest02 -- insert with overlap",
3814 StreamTcpReassembleInsertTest02);
3815 UtRegisterTest(
"StreamTcpReassembleInsertTest03 -- insert with overlap",
3816 StreamTcpReassembleInsertTest03);
3821 StreamTcpReassembleRawRegisterTests();