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);
1042 for ( ; blk != NULL; blk = SBB_RB_NEXT(blk)) {
1056 GetAbsLastAck(stream) > (cur_blk->
offset + cur_blk->
len)) {
1071 static bool GetAppBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1072 uint64_t
offset,
const bool check_for_gap)
1074 const uint8_t *mydata;
1075 uint32_t mydata_len;
1076 bool gap_ahead =
false;
1084 *data_len = mydata_len;
1102 gap_ahead = check_for_gap && GapAhead(stream, blk);
1106 SCLogDebug(
"gap, want data at offset %"PRIu64
", "
1107 "got data at %"PRIu64
". GAP of size %"PRIu64,
1114 SCLogDebug(
"get data from offset %"PRIu64
". SBB %"PRIu64
"/%u",
1117 SCLogDebug(
"data %p, data_len %u", *data, *data_len);
1119 gap_ahead = check_for_gap && GapAhead(stream, blk);
1138 const uint64_t last_ack_abs = GetAbsLastAck(stream) - (uint64_t)ackadded;
1145 if (last_ack_abs > app_progress) {
1152 "next_seq %u < last_ack %u, but no data in list",
1156 const uint64_t next_seq_abs =
1159 if (blk->
offset > next_seq_abs && blk->
offset < last_ack_abs) {
1162 "next_seq %u < last_ack %u, but ACK'd data beyond gap.",
1170 "last_ack_abs %" PRIu64
" > app_progress %" PRIu64
", "
1171 "but we have no data.",
1172 p->
pcap_cnt, last_ack_abs, app_progress);
1176 "last_ack_abs %"PRIu64
" <= app_progress %"PRIu64,
1177 p->
pcap_cnt, last_ack_abs, app_progress);
1181 static inline uint32_t AdjustToAcked(
const Packet *p,
1183 const uint64_t app_progress,
const uint32_t data_len)
1185 uint32_t adjusted = data_len;
1196 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1200 if (app_progress <= last_ack_abs && app_progress + data_len > last_ack_abs) {
1201 uint32_t check = data_len;
1202 adjusted = last_ack_abs - app_progress;
1203 BUG_ON(adjusted > check);
1204 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1205 "data is considered", adjusted);
1222 SCLogDebug(
"app progress %"PRIu64, app_progress);
1224 uint64_t last_ack_abs = GetAbsLastAck(*stream);
1225 SCLogDebug(
"last_ack %u (abs %" PRIu64
"), base_seq %u", (*stream)->last_ack, last_ack_abs,
1226 (*stream)->base_seq);
1228 const uint8_t *mydata;
1229 uint32_t mydata_len;
1230 bool last_was_gap =
false;
1233 const uint8_t
flags = StreamGetAppLayerFlags(ssn, *stream, p);
1234 bool check_for_gap_ahead = ((*stream)->data_required > 0);
1236 GetAppBuffer(*stream, &mydata, &mydata_len, app_progress, check_for_gap_ahead);
1238 if (last_was_gap && mydata_len == 0) {
1241 last_was_gap =
false;
1244 mydata_len = AdjustToAcked(p, ssn, *stream, app_progress, mydata_len);
1246 if (mydata == NULL && mydata_len > 0 && CheckGap(ssn, *stream, p)) {
1247 SCLogDebug(
"sending GAP to app-layer (size: %u)", mydata_len);
1250 StreamGetAppLayerFlags(ssn, *stream, p) | STREAM_GAP, app_update_dir);
1264 if ((*stream)->data_required > 0) {
1265 if ((*stream)->data_required > mydata_len) {
1266 (*stream)->data_required -= mydata_len;
1268 (*stream)->data_required = 0;
1273 if (no_progress_update)
1275 last_was_gap =
true;
1278 }
else if (
flags & STREAM_DEPTH) {
1281 if (mydata == NULL && mydata_len > 0) {
1284 }
else if (mydata == NULL || (mydata_len == 0 && ((
flags & STREAM_EOF) == 0))) {
1297 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1298 *stream, &(*stream)->sb, mydata_len, app_progress);
1302 if (mydata_len < (*stream)->data_required) {
1305 SCLogDebug(
"GAP while expecting more data (expect %u, gap size %u)",
1306 (*stream)->data_required, mydata_len);
1307 (*stream)->app_progress_rel += mydata_len;
1308 (*stream)->data_required -= mydata_len;
1318 (*stream)->data_required = 0;
1323 mydata_len,
flags, app_update_dir);
1329 app_progress = new_app_progress;
1330 if (
flags & STREAM_DEPTH)
1358 SCLogDebug(
"stream no reassembly flag set or app-layer disabled.");
1364 GetSessionSize(ssn, p);
1376 StreamGetAppLayerFlags(ssn, stream, p), app_update_dir);
1384 return ReassembleUpdateAppLayer(
tv, ra_ctx, ssn, &stream, p, app_update_dir);
1390 static int GetRawBuffer(
const TcpStream *stream,
const uint8_t **data, uint32_t *data_len,
1393 const uint8_t *mydata;
1394 uint32_t mydata_len;
1398 uint64_t roffset =
offset;
1406 *data_len = mydata_len;
1407 *data_offset = roffset;
1409 SCLogDebug(
"multiblob %s. Want offset %"PRIu64,
1410 *iter == NULL ?
"starting" :
"continuing",
offset);
1411 if (*iter == NULL) {
1416 if (*iter == NULL) {
1423 SCLogDebug(
"getting multiple blobs. Iter %p, %"PRIu64
"/%u", *iter, (*iter)->offset, (*iter)->len);
1428 if ((*iter)->offset <
offset) {
1429 uint64_t delta =
offset - (*iter)->offset;
1430 if (delta < mydata_len) {
1431 *data = mydata + delta;
1432 *data_len = mydata_len - delta;
1443 *data_len = mydata_len;
1444 *data_offset = (*iter)->offset;
1447 *iter = SBB_RB_NEXT(*iter);
1478 const uint64_t segs_re_abs =
1483 if (StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 1) {
1520 }
else if (progress == 0) {
1525 target = GetAbsLastAck(stream);
1534 SCLogDebug(
"p->pcap_cnt %"PRIu64
": progress %"PRIu64
" app %"PRIu64
" raw %"PRIu64
" tcp win %"PRIu32,
1543 SCLogDebug(
"ssn %p: STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED set, "
1544 "now that detect ran also set STREAMTCP_STREAM_FLAG_DISABLE_RAW", ssn);
1590 SCLogDebug(
"packet payload len %u, so chunk_size adjusted to %u",
1592 }
else if (((chunk_size / 3 ) * 2) < p->
payload_len) {
1594 SCLogDebug(
"packet payload len %u, so chunk_size adjusted to %u",
1598 const TCPHdr *tcph = PacketGetTCP(p);
1599 uint64_t packet_leftedge_abs =
1601 uint64_t packet_rightedge_abs = packet_leftedge_abs + p->
payload_len;
1602 SCLogDebug(
"packet_leftedge_abs %"PRIu64
", rightedge %"PRIu64,
1603 packet_leftedge_abs, packet_rightedge_abs);
1605 const uint8_t *mydata = NULL;
1606 uint32_t mydata_len = 0;
1607 uint64_t mydata_offset = 0;
1609 bool return_progress =
false;
1614 return_progress =
true;
1617 SCLogDebug(
"finding our SBB from offset %"PRIu64, packet_leftedge_abs);
1624 mydata_offset = sbb->
offset;
1629 uint64_t mydata_rightedge_abs = mydata_offset + mydata_len;
1630 if ((mydata == NULL || mydata_len == 0) ||
1631 (mydata_offset >= packet_rightedge_abs ||
1632 packet_leftedge_abs >= mydata_rightedge_abs) ||
1633 (packet_leftedge_abs < mydata_offset ||
1634 packet_rightedge_abs > mydata_rightedge_abs))
1639 mydata_offset = packet_leftedge_abs;
1643 SCLogDebug(
"chunk_size %u mydata_len %u", chunk_size, mydata_len);
1644 if (mydata_len > chunk_size) {
1645 uint32_t excess = mydata_len - chunk_size;
1646 SCLogDebug(
"chunk_size %u mydata_len %u excess %u", chunk_size, mydata_len, excess);
1648 if (mydata_rightedge_abs == packet_rightedge_abs) {
1650 mydata_len -= excess;
1651 mydata_offset += excess;
1652 SCLogDebug(
"cutting front of the buffer with %u", excess);
1653 }
else if (mydata_offset == packet_leftedge_abs) {
1654 mydata_len -= excess;
1655 SCLogDebug(
"cutting tail of the buffer with %u", excess);
1657 uint32_t before = (uint32_t)(packet_leftedge_abs - mydata_offset);
1658 uint32_t after = (uint32_t)(mydata_rightedge_abs - packet_rightedge_abs);
1659 SCLogDebug(
"before %u after %u", before, after);
1664 if (before >= (chunk_size - p->
payload_len) / 2) {
1666 before = after = (chunk_size - p->
payload_len) / 2;
1675 if (before >= (chunk_size - p->
payload_len) / 2) {
1683 uint32_t skip = (uint32_t)(packet_leftedge_abs - mydata_offset) - before;
1684 uint32_t cut = (uint32_t)(mydata_rightedge_abs - packet_rightedge_abs) - after;
1689 mydata_len -= (skip + cut);
1690 mydata_offset += skip;
1696 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1699 if (return_progress) {
1700 *progress_out = (mydata_offset + mydata_len);
1707 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1708 SCLogDebug(
"last_ack_abs %"PRIu64, last_ack_abs);
1711 if (mydata_offset > last_ack_abs) {
1713 *progress_out = last_ack_abs;
1715 *progress_out = (mydata_offset + mydata_len);
1758 const uint64_t re, uint64_t *progress_out,
bool eof,
bool respect_inspect_depth)
1764 uint64_t progress = progress_in;
1769 const uint8_t *mydata;
1770 uint32_t mydata_len;
1771 uint64_t mydata_offset = 0;
1773 GetRawBuffer(stream, &mydata, &mydata_len, &iter, progress, &mydata_offset);
1774 if (mydata_len == 0) {
1780 SCLogDebug(
"raw progress %"PRIu64, progress);
1781 SCLogDebug(
"stream %p data in buffer %p of len %u and offset %"PRIu64,
1782 stream, &stream->
sb, mydata_len, progress);
1787 if (re < progress) {
1792 SCLogDebug(
"re %" PRIu64
", raw_progress %" PRIu64, re, progress);
1793 SCLogDebug(
"raw_progress + mydata_len %" PRIu64
", re %" PRIu64, progress + mydata_len,
1797 if (progress + mydata_len > re) {
1798 uint32_t check = mydata_len;
1799 mydata_len = re - progress;
1800 BUG_ON(check < mydata_len);
1801 SCLogDebug(
"data len adjusted to %u to make sure only ACK'd "
1802 "data is considered", mydata_len);
1805 if (mydata_len == 0)
1808 SCLogDebug(
"data %p len %u", mydata, mydata_len);
1811 r = Callback(cb_data, mydata, mydata_len, mydata_offset);
1814 if (mydata_offset == progress) {
1815 SCLogDebug(
"progress %"PRIu64
" increasing with data len %u to %"PRIu64,
1816 progress, mydata_len, progress_in + mydata_len);
1818 progress += mydata_len;
1819 SCLogDebug(
"raw progress now %"PRIu64, progress);
1822 }
else if (mydata_offset > progress && mydata_offset < re) {
1823 SCLogDebug(
"GAP: data is missing from %"PRIu64
" (%u bytes), setting to first data we have: %"PRIu64, progress, (uint32_t)(mydata_offset - progress), mydata_offset);
1825 progress = mydata_offset;
1826 SCLogDebug(
"raw progress now %"PRIu64, progress);
1829 SCLogDebug(
"not increasing progress, data gap => mydata_offset "
1830 "%"PRIu64
" != progress %"PRIu64, mydata_offset, progress);
1833 if (iter == NULL || r == 1)
1837 *progress_out = progress;
1842 void *cb_data,
const uint64_t
offset,
const bool eof)
1846 SCLogDebug(
"app_progress %" PRIu64, app_progress);
1848 uint64_t unused = 0;
1849 return StreamReassembleRawDo(
1850 ssn, stream, Callback, cb_data,
offset, app_progress, &unused, eof,
false);
1855 uint64_t *progress_out,
bool respect_inspect_depth)
1859 return StreamReassembleRawInline(ssn, p, Callback, cb_data, progress_out);
1870 StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 0)
1882 SCLogDebug(
"respect_inspect_depth %s STREAMTCP_STREAM_FLAG_TRIGGER_RAW %s "
1883 "stream->min_inspect_depth %u",
1884 respect_inspect_depth ?
"true" :
"false",
1901 SCLogDebug(
"applied min inspect depth due to STREAMTCP_STREAM_FLAG_TRIGGER_RAW: progress "
1911 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1912 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1914 return StreamReassembleRawDo(ssn, stream, Callback, cb_data, progress, last_ack_abs,
1920 uint64_t *progress_out,
const bool eof)
1926 const uint64_t last_ack_abs = GetAbsLastAck(stream);
1927 SCLogDebug(
"last_ack_abs %" PRIu64, last_ack_abs);
1929 return StreamReassembleRawDo(
1930 ssn, stream, Callback, cb_data, progress_in, last_ack_abs, progress_out, eof,
false);
1938 static int StreamTcpReassembleHandleSegmentUpdateACK (
ThreadVars *
tv,
1949 static void StreamTcpReassembleExceptionPolicyStatsIncr(
1964 const TCPHdr *tcph = PacketGetTCP(p);
1966 SCLogDebug(
"ssn %p, stream %p, p %p, p->payload_len %"PRIu16
"",
1996 if (stream == &ssn->
client) {
1997 opposing_stream = &ssn->
server;
1999 opposing_stream = &ssn->
client;
2004 if (StreamTcpReassembleHandleSegmentUpdateACK(
tv, ra_ctx, ssn, opposing_stream, p) != 0) {
2005 SCLogDebug(
"StreamTcpReassembleHandleSegmentUpdateACK error");
2013 if (reversed_before_ack_handling != reversed_after_ack_handling) {
2015 stream = opposing_stream;
2021 SCLogDebug(
"calling StreamTcpReassembleHandleSegmentHandleData");
2024 SCLogDebug(
"StreamTcpReassembleHandleSegmentHandleData error");
2028 StreamTcpReassembleExceptionPolicyStatsIncr(
2036 SCLogDebug(
"ssn %p / stream %p: not calling StreamTcpReassembleHandleSegmentHandleData:"
2037 " p->payload_len %u, STREAMTCP_STREAM_FLAG_NOREASSEMBLY %s",
2047 if ((stream->
flags &
2051 SCLogDebug(
"STREAMTCP_STREAM_FLAG_DEPTH_REACHED, truncate applayer");
2053 SCLogDebug(
"override: direction now UPDATE_DIR_PACKET so we "
2054 "can trigger Truncate");
2062 SCLogDebug(
"inline (%s) or PKT_PSEUDO_STREAM_END (%s)",
2121 if (direction == STREAM_TOSERVER) {
2127 SCLogDebug(
"flagged ssn %p for immediate raw reassembly", ssn);
2138 if (direction == STREAM_TOSERVER) {
2140 SCLogDebug(
"ssn %p: set client.min_inspect_depth to %u", ssn, depth);
2143 SCLogDebug(
"ssn %p: set server.min_inspect_depth to %u", ssn, depth);
2151 #define SET_ISN(stream, setseq) \
2152 (stream)->isn = (setseq); \
2153 (stream)->base_seq = (setseq) + 1
2171 for (; i <
len; i++)
2185 data, data_len) == 0)
2194 #define MISSED_START(isn) \
2195 TcpReassemblyThreadCtx *ra_ctx = NULL; \
2198 memset(&tv, 0, sizeof(tv)); \
2200 StreamTcpUTInit(&ra_ctx); \
2202 StreamTcpUTSetupSession(&ssn); \
2203 StreamTcpUTSetupStream(&ssn.server, (isn)); \
2204 StreamTcpUTSetupStream(&ssn.client, (isn)); \
2206 TcpStream *stream = &ssn.client;
2208 #define MISSED_END \
2209 StreamTcpUTClearSession(&ssn); \
2210 StreamTcpUTDeinit(ra_ctx); \
2213 #define MISSED_STEP(seq, seg, seglen, buf, buflen) \
2214 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen)); \
2215 FAIL_IF(!(VALIDATE(stream, (uint8_t *)(buf), (buflen))));
2217 #define MISSED_ADD_PAYLOAD(seq, seg, seglen) \
2218 StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen));
2225 uint64_t last_re = 0;
2229 if (sbb->
offset != last_re) {
2249 uint64_t last_re = 0;
2253 if (sbb->
offset != last_re) {
2259 const uint8_t *buf = NULL;
2260 uint32_t buf_len = 0;
2263 if (
len == buf_len) {
2264 return (memcmp(data, buf,
len) == 0);
2281 static int StreamTcpReassembleTest25 (
void)
2302 static int StreamTcpReassembleTest26 (
void)
2321 static int StreamTcpReassembleTest27 (
void)
2338 static int StreamTcpReassembleTest28 (
void)
2362 static int StreamTcpReassembleTest29 (
void)
2374 static int StreamTcpReassembleTest33(
void)
2383 uint8_t packet[1460] =
"";
2388 memset(&f, 0,
sizeof (
Flow));
2389 memset(&tcph, 0,
sizeof (
TCPHdr));
2394 f.
proto = IPPROTO_TCP;
2397 p->
proto = IPPROTO_TCP;
2435 static int StreamTcpReassembleTest34(
void)
2444 uint8_t packet[1460] =
"";
2448 memset(&f, 0,
sizeof (
Flow));
2449 memset(&tcph, 0,
sizeof (
TCPHdr));
2454 f.
proto = IPPROTO_TCP;
2457 p->
proto = IPPROTO_TCP;
2466 tcph.
th_seq = htonl(857961230);
2472 tcph.
th_seq = htonl(857961534);
2478 tcph.
th_seq = htonl(857963582);
2484 tcph.
th_seq = htonl(857960946);
2504 static int StreamTcpReassembleTest39 (
void)
2514 memset (&f, 0,
sizeof(
Flow));
2516 memset(&stt, 0,
sizeof (stt));
2517 memset(&tcph, 0,
sizeof (
TCPHdr));
2521 f.
proto = IPPROTO_TCP;
2528 tcph.
th_win = htons(5480);
2596 uint8_t request1[] = { 0x47, 0x45, };
2643 uint8_t request2[] = {
2644 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
2645 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
2646 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
2647 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
2648 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
2649 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
2650 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
2651 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
2652 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
2653 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
2654 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
2679 uint8_t response[] = {
2680 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
2681 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
2682 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
2683 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
2684 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
2685 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
2686 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
2687 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
2688 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
2689 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
2690 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
2691 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
2692 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
2693 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
2694 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
2695 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
2696 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
2697 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
2698 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
2699 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
2700 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
2701 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
2702 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
2703 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
2704 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
2705 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
2706 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
2707 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
2708 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
2709 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
2710 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
2711 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
2712 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
2713 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
2714 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
2715 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
2716 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
2717 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
2718 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
2719 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
2720 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
2746 tcph.
th_ack = htonl(328);
2772 tcph.
th_seq = htonl(328);
2796 tcph.
th_ack = htonl(328);
2821 tcph.
th_seq = htonl(328);
2846 tcph.
th_ack = htonl(328);
2872 tcph.
th_seq = htonl(328);
2897 tcph.
th_ack = htonl(328);
2923 tcph.
th_ack = htonl(175);
2924 tcph.
th_seq = htonl(328);
2950 tcph.
th_ack = htonl(175);
2951 tcph.
th_seq = htonl(328);
2967 tcph.
th_ack = htonl(328);
2968 tcph.
th_seq = htonl(175);
2988 static int StreamTcpReassembleTest40 (
void)
2995 memset(&tcph, 0,
sizeof (
TCPHdr));
3005 uint8_t httpbuf1[] =
"P";
3006 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3007 uint8_t httpbuf3[] =
"O";
3008 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
3009 uint8_t httpbuf4[] =
"S";
3010 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
3011 uint8_t httpbuf5[] =
"T \r\n";
3012 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
3014 uint8_t httpbuf2[] =
"HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
3015 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3022 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3025 f->
proto = IPPROTO_TCP;
3028 tcph.
th_win = htons(5480);
3080 tcph.
th_ack = htonl(100);
3089 tcph.
th_seq = htonl(100);
3100 tcph.
th_ack = htonl(145);
3109 tcph.
th_seq = htonl(145);
3126 static int StreamTcpReassembleTest44(
void)
3147 static int StreamTcpReassembleTest45 (
void)
3152 memset(&
tv, 0,
sizeof(
tv));
3153 uint8_t payload[100] = {0};
3154 uint16_t payload_size = 100;
3185 static int StreamTcpReassembleTest46 (
void)
3191 memset(&
tv, 0,
sizeof(
tv));
3192 uint8_t payload[100] = {0};
3193 uint16_t payload_size = 100;
3206 printf(
"STREAMTCP_STREAM_FLAG_NOREASSEMBLY set: ");
3214 printf(
"STREAMTCP_STREAM_FLAG_NOREASSEMBLY set: ");
3234 static int StreamTcpReassembleTest47 (
void)
3242 memset(&tcph, 0,
sizeof (
TCPHdr));
3249 uint8_t httpbuf1[] =
"GET /EVILSUFF HTTP/1.1\r\n\r\n";
3250 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3258 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 200, 220);
3261 f->
proto = IPPROTO_TCP;
3264 tcph.
th_win = htons(5480);
3271 tcph.
th_ack = htonl(572799782UL);
3283 tcph.
th_seq = htonl(572799782UL);
3302 static int StreamTcpReassembleInlineTest01(
void)
3310 memset(&
tv, 0x00,
sizeof(
tv));
3318 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3321 printf(
"couldn't get a packet: ");
3328 printf(
"failed to add segment 1: ");
3332 printf(
"failed to add segment 2: ");
3336 printf(
"failed to add segment 3: ");
3352 static int StreamTcpReassembleInlineTest02(
void)
3360 memset(&
tv, 0x00,
sizeof(
tv));
3368 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3371 printf(
"couldn't get a packet: ");
3378 printf(
"failed to add segment 1: ");
3382 printf(
"failed to add segment 2: ");
3386 printf(
"failed to add segment 3: ");
3391 printf(
"failed to add segment 4: ");
3408 static int StreamTcpReassembleInlineTest03(
void)
3416 memset(&
tv, 0x00,
sizeof(
tv));
3426 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3429 printf(
"couldn't get a packet: ");
3437 printf(
"failed to add segment 1: ");
3441 printf(
"failed to add segment 2: ");
3445 printf(
"failed to add segment 3: ");
3450 printf(
"failed to add segment 4: ");
3469 static int StreamTcpReassembleInlineTest04(
void)
3477 memset(&
tv, 0x00,
sizeof(
tv));
3487 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3490 printf(
"couldn't get a packet: ");
3498 printf(
"failed to add segment 1: ");
3502 printf(
"failed to add segment 2: ");
3506 printf(
"failed to add segment 3: ");
3511 printf(
"failed to add segment 4: ");
3531 static int StreamTcpReassembleInlineTest08(
void)
3535 memset(&
tv, 0x00,
sizeof(
tv));
3547 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3579 static int StreamTcpReassembleInlineTest09(
void)
3587 memset(&
tv, 0x00,
sizeof(
tv));
3597 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3600 printf(
"couldn't get a packet: ");
3608 printf(
"failed to add segment 1: ");
3612 printf(
"failed to add segment 2: ");
3616 printf(
"failed to add segment 3: ");
3624 printf(
"failed to add segment 4: ");
3646 static int StreamTcpReassembleInlineTest10(
void)
3655 memset(&
tv, 0x00,
sizeof(
tv));
3666 f =
UTHBuildFlow(AF_INET,
"1.1.1.1",
"2.2.2.2", 1024, 80);
3670 f->
proto = IPPROTO_TCP;
3672 uint8_t stream_payload1[] =
"GE";
3673 uint8_t stream_payload2[] =
"T /";
3674 uint8_t stream_payload3[] =
"HTTP/1.0\r\n\r\n";
3676 p =
UTHBuildPacketReal(stream_payload3, 12, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
3678 printf(
"couldn't get a packet: ");
3686 printf(
"failed to add segment 1: ");
3693 printf(
"StreamTcpReassembleAppLayer failed: ");
3699 printf(
"expected ra_app_base_seq 1, got %u: ", ssn.
client.
base_seq);
3704 printf(
"failed to add segment 2: ");
3708 printf(
"failed to add segment 3: ");
3715 printf(
"StreamTcpReassembleAppLayer failed: ");
3732 static int StreamTcpReassembleInsertTest01(
void)
3739 memset(&
tv, 0x00,
sizeof(
tv));
3747 uint8_t payload[] = {
'C',
'C',
'C',
'C',
'C' };
3769 static int StreamTcpReassembleInsertTest02(
void)
3776 memset(&
tv, 0x00,
sizeof(
tv));
3783 for (i = 2; i < 10; i++) {
3794 printf(
"failed to add segment 1: ");
3799 printf(
"failed to add segment 2: ");
3812 static int StreamTcpReassembleInsertTest03(
void)
3819 memset(&
tv, 0x00,
sizeof(
tv));
3826 printf(
"failed to add segment 2: ");
3831 for (i = 2; i < 10; i++) {
3842 printf(
"failed to add segment 2: ");
3863 UtRegisterTest(
"StreamTcpReassembleTest25 -- Gap at Start Reassembly Test",
3864 StreamTcpReassembleTest25);
3865 UtRegisterTest(
"StreamTcpReassembleTest26 -- Gap at middle Reassembly Test",
3866 StreamTcpReassembleTest26);
3867 UtRegisterTest(
"StreamTcpReassembleTest27 -- Gap at after Reassembly Test",
3868 StreamTcpReassembleTest27);
3869 UtRegisterTest(
"StreamTcpReassembleTest28 -- Gap at Start IDS missed packet Reassembly Test",
3870 StreamTcpReassembleTest28);
3871 UtRegisterTest(
"StreamTcpReassembleTest29 -- Gap at Middle IDS missed packet Reassembly Test",
3872 StreamTcpReassembleTest29);
3874 StreamTcpReassembleTest33);
3876 StreamTcpReassembleTest34);
3878 StreamTcpReassembleTest39);
3880 StreamTcpReassembleTest40);
3882 StreamTcpReassembleTest44);
3884 StreamTcpReassembleTest45);
3886 StreamTcpReassembleTest46);
3887 UtRegisterTest(
"StreamTcpReassembleTest47 -- TCP Sequence Wraparound Test",
3888 StreamTcpReassembleTest47);
3890 UtRegisterTest(
"StreamTcpReassembleInlineTest01 -- inline RAW ra",
3891 StreamTcpReassembleInlineTest01);
3892 UtRegisterTest(
"StreamTcpReassembleInlineTest02 -- inline RAW ra 2",
3893 StreamTcpReassembleInlineTest02);
3894 UtRegisterTest(
"StreamTcpReassembleInlineTest03 -- inline RAW ra 3",
3895 StreamTcpReassembleInlineTest03);
3896 UtRegisterTest(
"StreamTcpReassembleInlineTest04 -- inline RAW ra 4",
3897 StreamTcpReassembleInlineTest04);
3898 UtRegisterTest(
"StreamTcpReassembleInlineTest08 -- inline RAW ra 8 cleanup",
3899 StreamTcpReassembleInlineTest08);
3900 UtRegisterTest(
"StreamTcpReassembleInlineTest09 -- inline RAW ra 9 GAP cleanup",
3901 StreamTcpReassembleInlineTest09);
3903 UtRegisterTest(
"StreamTcpReassembleInlineTest10 -- inline APP ra 10",
3904 StreamTcpReassembleInlineTest10);
3906 UtRegisterTest(
"StreamTcpReassembleInsertTest01 -- insert with overlap",
3907 StreamTcpReassembleInsertTest01);
3908 UtRegisterTest(
"StreamTcpReassembleInsertTest02 -- insert with overlap",
3909 StreamTcpReassembleInsertTest02);
3910 UtRegisterTest(
"StreamTcpReassembleInsertTest03 -- insert with overlap",
3911 StreamTcpReassembleInsertTest03);
3916 StreamTcpReassembleRawRegisterTests();