StreamTcpSetupMsg(ssn, stream, p, smsg);
}
- smsg->data.seq = ra_base_seq;
+ smsg->data.seq = ra_base_seq+1;
/* copy the data into the smsg */
uint16_t copy_size = sizeof (smsg->data.data) - smsg_offset;
smsg_offset = 0;
StreamTcpSetupMsg(ssn, stream,p,smsg);
- smsg->data.seq = ra_base_seq;
+ smsg->data.seq = ra_base_seq+1;
copy_size = sizeof(smsg->data.data) - smsg_offset;
if (copy_size > (seg->payload_len - payload_offset)) {
SCReturnInt(0);
}
+/** \internal
+ * \brief check if we can remove a segment from our segment list
+ *
+ * If a segment is entirely before the oldest smsg, we can discard it. Otherwise
+ * we keep it around to be able to log it.
+ *
+ * \retval 1 yes
+ * \retval 0 no
+ */
+static inline int StreamTcpReturnSegmentCheck(TcpSession *ssn, TcpStream *stream, TcpSegment *seg) {
+ if (stream == &ssn->client && ssn->toserver_smsg_head != NULL) {
+ /* not (seg is entirely before first smsg, skip) */
+ if (!(SEQ_LEQ(seg->seq + seg->payload_len, ssn->toserver_smsg_head->data.seq))) {
+ SCReturnInt(0);
+ }
+ } else if (stream == &ssn->server && ssn->toclient_smsg_head != NULL) {
+ /* not (seg is entirely before first smsg, skip) */
+ if (!(SEQ_LEQ(seg->seq + seg->payload_len, ssn->toclient_smsg_head->data.seq))) {
+ SCReturnInt(0);
+ }
+ }
+ SCReturnInt(1);
+}
+
+/** \brief Remove idle TcpSegments from TcpSession
+ *
+ * \param f flow
+ * \param flags direction flags
+ */
+void StreamTcpPruneSession(Flow *f, uint8_t flags) {
+ if (f == NULL || f->protoctx == NULL ||
+ ((flags & (STREAM_TOSERVER|STREAM_TOCLIENT)) == 0))
+ return;
+
+ TcpSession *ssn = f->protoctx;
+ TcpStream *stream = NULL;
+
+ if (flags & STREAM_TOSERVER) {
+ stream = &ssn->client;
+ } else if (flags & STREAM_TOCLIENT) {
+ stream = &ssn->server;
+ }
+
+ /* loop through the segments and fill one or more msgs */
+ TcpSegment *seg = stream->seg_list;
+ uint32_t ra_base_seq = stream->ra_app_base_seq;
+
+ for (; seg != NULL && SEQ_LT(seg->seq, stream->last_ack);)
+ {
+ SCLogDebug("seg %p, SEQ %"PRIu32", LEN %"PRIu16", SUM %"PRIu32,
+ seg, seg->seq, seg->payload_len,
+ (uint32_t)(seg->seq + seg->payload_len));
+
+ if (SEQ_LEQ((seg->seq + seg->payload_len), (ra_base_seq+1)) &&
+ seg->flags & SEGMENTTCP_FLAG_RAW_PROCESSED &&
+ seg->flags & SEGMENTTCP_FLAG_APPLAYER_PROCESSED) {
+ if (StreamTcpReturnSegmentCheck(ssn, stream, seg) == 0) {
+ seg = seg->next;
+ break;
+ }
+
+ SCLogDebug("removing pre ra_base_seq %"PRIu32" seg %p seq %"PRIu32
+ " len %"PRIu16"", ra_base_seq, seg, seg->seq, seg->payload_len);
+
+ TcpSegment *next_seg = seg->next;
+ StreamTcpRemoveSegmentFromStream(stream, seg);
+ StreamTcpSegmentReturntoPool(seg);
+ seg = next_seg;
+ continue;
+
+ } else if ((ssn->flags & STREAMTCP_FLAG_APPPROTO_DETECTION_COMPLETED) &&
+ (seg->flags & SEGMENTTCP_FLAG_RAW_PROCESSED) &&
+ (seg->flags & SEGMENTTCP_FLAG_APPLAYER_PROCESSED))
+ {
+ if (StreamTcpReturnSegmentCheck(ssn, stream, seg) == 0) {
+ seg = seg->next;
+ break;
+ }
+
+ SCLogDebug("segment(%p) of length %"PRIu16" has been processed,"
+ " so return it to pool", seg, seg->payload_len);
+ TcpSegment *next_seg = seg->next;
+ seg = next_seg;
+ continue;
+ } else {
+ /* give up */
+ break;
+ }
+ }
+}
+
/**
* \brief Update the stream reassembly upon receiving an ACK packet.
*
} else if (SEQ_LEQ((seg->seq + seg->payload_len), (ra_base_seq+1)) &&
seg->flags & SEGMENTTCP_FLAG_RAW_PROCESSED &&
seg->flags & SEGMENTTCP_FLAG_APPLAYER_PROCESSED) {
+ if (StreamTcpReturnSegmentCheck(ssn, stream, seg) == 0) {
+ seg = seg->next;
+ continue;
+ }
+
SCLogDebug("removing pre ra_base_seq %"PRIu32" seg %p seq %"PRIu32
" len %"PRIu16"", ra_base_seq, seg, seg->seq, seg->payload_len);
(seg->flags & SEGMENTTCP_FLAG_RAW_PROCESSED) &&
(seg->flags & SEGMENTTCP_FLAG_APPLAYER_PROCESSED))
{
+ if (StreamTcpReturnSegmentCheck(ssn, stream, seg) == 0) {
+ next_seq = seg->seq + seg->payload_len;
+ seg = seg->next;
+ continue;
+ }
+
SCLogDebug("segment(%p) of length %"PRIu16" has been processed,"
" so return it to pool", seg, seg->payload_len);
next_seq = seg->seq + seg->payload_len;
As we are copying until the stream->last_ack only */
if (SEQ_LEQ((seg->seq + seg->payload_len), ra_base_seq+1))
{
+ if (StreamTcpReturnSegmentCheck(ssn, stream, seg) == 0) {
+ seg = seg->next;
+ continue;
+ }
+
SCLogDebug("removing pre ra_base_seq %"PRIu32" seg %p seq %"PRIu32""
" len %"PRIu16"", ra_base_seq, seg, seg->seq,
seg->payload_len);
(seg->flags & SEGMENTTCP_FLAG_APPLAYER_PROCESSED ||
stream->flags & STREAMTCP_STREAM_FLAG_GAP))
{
+ if (StreamTcpReturnSegmentCheck(ssn, stream, seg) == 0) {
+ seg = seg->next;
+ continue;
+ }
+
SCLogDebug("segment(%p) of length %"PRIu16" has been processed,"
" so return it to pool", seg, seg->payload_len);
TcpSegment *next_seg = seg->next;
StreamTcpSetupMsg(ssn, stream, p, smsg);
}
- smsg->data.seq = ra_base_seq;
+ smsg->data.seq = ra_base_seq+1;
/* copy the data into the smsg */
smsg_offset = 0;
StreamTcpSetupMsg(ssn, stream,p,smsg);
- smsg->data.seq = ra_base_seq;
+ smsg->data.seq = ra_base_seq+1;
copy_size = sizeof(smsg->data.data) - smsg_offset;
if (copy_size > (seg->payload_len - payload_offset)) {
goto end;
}
+ SCLogDebug("ssn.client.seg_list->flags %02x, seg %p", ssn.client.seg_list->flags, ssn.client.seg_list);
+
if (!(ssn.client.seg_list->flags & SEGMENTTCP_FLAG_APPLAYER_PROCESSED)) {
printf("segment should have flags SEGMENTTCP_FLAG_APPLAYER_PROCESSED set (15): ");
goto end;