diff --git a/src/app-layer-detect-proto.c b/src/app-layer-detect-proto.c index 338d6e8149..db7b911088 100644 --- a/src/app-layer-detect-proto.c +++ b/src/app-layer-detect-proto.c @@ -3679,110 +3679,6 @@ static int AppLayerProtoDetectTest19(void) return result; } -/** \test test if the engine detect the proto and match with it - * and also against a content option */ -static int AppLayerProtoDetectTest20(void) -{ - int result = 0; - Flow *f = NULL; - uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n" - "User-Agent: Mozilla/1.0\r\n" - "Cookie: hellocatch\r\n\r\n"; - uint32_t http_buf1_len = sizeof(http_buf1) - 1; - TcpSession ssn; - Packet *p = NULL; - Signature *s = NULL; - ThreadVars tv; - DetectEngineThreadCtx *det_ctx = NULL; - DetectEngineCtx *de_ctx = NULL; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&tv, 0, sizeof(ThreadVars)); - memset(&ssn, 0, sizeof(TcpSession)); - - p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP); - - f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80); - if (f == NULL) - goto end; - f->protoctx = &ssn; - p->flow = f; - p->flowflags |= FLOW_PKT_TOSERVER; - p->flowflags |= FLOW_PKT_ESTABLISHED; - p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; - f->alproto = ALPROTO_HTTP; - f->proto = IPPROTO_TCP; - p->flags |= PKT_STREAM_ADD; - p->flags |= PKT_STREAM_EOF; - - de_ctx = DetectEngineCtxInit(); - if (de_ctx == NULL) { - goto end; - } - - StreamTcpInitConfig(TRUE); - - StreamMsg *stream_msg = StreamMsgGetFromPool(); - if (stream_msg == NULL) { - printf("no stream_msg: "); - goto end; - } - - memcpy(stream_msg->data, http_buf1, http_buf1_len); - stream_msg->data_len = http_buf1_len; - - ssn.toserver_smsg_head = stream_msg; - ssn.toserver_smsg_tail = stream_msg; - - de_ctx->flags |= DE_QUIET; - - s = de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any " - "(msg:\"Test content option\"; " - "content:\"one\"; sid:1;)"); - if (s == NULL) { - goto end; - } - - SigGroupBuild(de_ctx); - DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); - - FLOWLOCK_WRLOCK(f); - int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP, - STREAM_TOSERVER, http_buf1, http_buf1_len); - if (r != 0) { - printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); - FLOWLOCK_UNLOCK(f); - goto end; - } - FLOWLOCK_UNLOCK(f); - - /* do detect */ - SigMatchSignatures(&tv, de_ctx, det_ctx, p); - - if (!PacketAlertCheck(p, 1)) { - printf("sig 1 didn't alert, but it should: "); - goto end; - } - - result = 1; - - end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - if (det_ctx != NULL) - DetectEngineThreadCtxDeinit(&tv, det_ctx); - if (de_ctx != NULL) - SigGroupCleanup(de_ctx); - if (de_ctx != NULL) - DetectEngineCtxFree(de_ctx); - - StreamTcpFreeConfig(TRUE); - UTHFreePackets(&p, 1); - UTHFreeFlow(f); - return result; -} - - void AppLayerProtoDetectUnittestsRegister(void) { SCEnter(); @@ -3806,7 +3702,6 @@ void AppLayerProtoDetectUnittestsRegister(void) UtRegisterTest("AppLayerProtoDetectTest17", AppLayerProtoDetectTest17); UtRegisterTest("AppLayerProtoDetectTest18", AppLayerProtoDetectTest18); UtRegisterTest("AppLayerProtoDetectTest19", AppLayerProtoDetectTest19); - UtRegisterTest("AppLayerProtoDetectTest20", AppLayerProtoDetectTest20); SCReturn; } diff --git a/src/app-layer.c b/src/app-layer.c index 8cbb86838d..2bb7dc7d8b 100644 --- a/src/app-layer.c +++ b/src/app-layer.c @@ -607,8 +607,6 @@ int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, r = AppLayerParserParse(tv, app_tctx->alp_tctx, f, f->alproto, flags, data, data_len); PACKET_PROFILING_APP_END(app_tctx, f->alproto); - } else { - SCLogDebug(" smsg not start, but no l7 data? Weird"); } } diff --git a/src/decode.h b/src/decode.h index d732ce9038..16ab1a43e8 100644 --- a/src/decode.h +++ b/src/decode.h @@ -1108,6 +1108,8 @@ int DecoderParseDataFromFileSerie(char *fileprefix, DecoderFunc Decoder); #define PKT_REBUILT_FRAGMENT (1<<25) /**< Packet is rebuilt from * fragments. */ +#define PKT_DETECT_HAS_STREAMDATA (1<<26) /**< Set by Detect() if raw stream data is available. */ + /** \brief return 1 if the packet is a pseudo packet */ #define PKT_IS_PSEUDOPKT(p) ((p)->flags & PKT_PSEUDO_STREAM_END) diff --git a/src/detect-engine-alert.c b/src/detect-engine-alert.c index 5187bf9f3c..794331d117 100644 --- a/src/detect-engine-alert.c +++ b/src/detect-engine-alert.c @@ -184,7 +184,6 @@ int PacketAlertRemove(Packet *p, uint16_t pos) * \param s the signature that matched * \param p packet * \param flags alert flags - * \param alert_msg ptr to StreamMsg object that the signature matched on */ int PacketAlertAppend(DetectEngineThreadCtx *det_ctx, const Signature *s, Packet *p, uint64_t tx_id, uint8_t flags) diff --git a/src/detect-engine-payload.c b/src/detect-engine-payload.c index ce65a08ba4..8e94dc2196 100644 --- a/src/detect-engine-payload.c +++ b/src/detect-engine-payload.c @@ -35,6 +35,7 @@ #include "detect-engine-prefilter.h" #include "stream.h" +#include "stream-tcp.h" #include "util-debug.h" #include "util-print.h" @@ -45,27 +46,39 @@ #include "util-mpm-ac.h" +struct StreamMpmData { + DetectEngineThreadCtx *det_ctx; + const MpmCtx *mpm_ctx; +}; + +static int StreamMpmFunc(void *cb_data, const uint8_t *data, const uint32_t data_len) +{ + struct StreamMpmData *smd = cb_data; + if (data_len >= smd->mpm_ctx->minlen) { + (void)mpm_table[smd->mpm_ctx->mpm_type].Search(smd->mpm_ctx, + &smd->det_ctx->mtcs, &smd->det_ctx->pmq, + data, data_len); + } + return 0; +} + static void PrefilterPktStream(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx) { SCEnter(); const MpmCtx *mpm_ctx = (MpmCtx *)pectx; - const StreamMsg *smsg = det_ctx->smsg; - - /* for established packets inspect any smsg we may have queued up */ - if (p->flowflags & FLOW_PKT_ESTABLISHED) { - SCLogDebug("p->flowflags & FLOW_PKT_ESTABLISHED"); - - for ( ; smsg != NULL; smsg = smsg->next) { - if (smsg->data_len >= mpm_ctx->minlen) { - (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx, - &det_ctx->mtcs, &det_ctx->pmq, - smsg->data, smsg->data_len); - } - } + + /* for established packets inspect any stream we may have queued up */ + if (p->flags & PKT_DETECT_HAS_STREAMDATA) { + struct StreamMpmData stream_mpm_data = { det_ctx, mpm_ctx }; + StreamReassembleRaw(p->flow->protoctx, p, + StreamMpmFunc, &stream_mpm_data, + &det_ctx->raw_stream_progress); + SCLogDebug("det_ctx->raw_stream_progress %"PRIu64, + det_ctx->raw_stream_progress); } else { - SCLogDebug("NOT p->flowflags & FLOW_PKT_ESTABLISHED"); + SCLogDebug("NOT p->flags & PKT_DETECT_HAS_STREAMDATA"); } /* packets that have not been added to the stream will be inspected @@ -152,48 +165,61 @@ int DetectEngineInspectPacketPayload(DetectEngineCtx *de_ctx, SCReturnInt(0); } +struct StreamContentInspectData { + DetectEngineCtx *de_ctx; + DetectEngineThreadCtx *det_ctx; + const Signature *s; + Flow *f; +}; + +static int StreamContentInspectFunc(void *cb_data, const uint8_t *data, const uint32_t data_len) +{ + SCEnter(); + int r = 0; + struct StreamContentInspectData *smd = cb_data; + + smd->det_ctx->buffer_offset = 0; + smd->det_ctx->discontinue_matching = 0; + smd->det_ctx->inspection_recursion_counter = 0; + + r = DetectEngineContentInspection(smd->de_ctx, smd->det_ctx, + smd->s, smd->s->sm_arrays[DETECT_SM_LIST_PMATCH], + smd->f, (uint8_t *)data, data_len, 0, + DETECT_ENGINE_CONTENT_INSPECTION_MODE_STREAM, NULL); + if (r == 1) { + SCReturnInt(1); + } + + SCReturnInt(0); +} + /** - * \brief Do the content inspection & validation for a signature for a stream chunk + * \brief Do the content inspection & validation for a signature + * on the raw stream * * \param de_ctx Detection engine context * \param det_ctx Detection engine thread context * \param s Signature to inspect * \param f flow (for pcre flowvar storage) - * \param payload ptr to the payload to inspect - * \param payload_len length of the payload * * \retval 0 no match * \retval 1 match - * - * \todo we might also pass the packet to this function for the pktvar - * storage. Only, would that be right? We're not inspecting data - * from the current packet here. */ int DetectEngineInspectStreamPayload(DetectEngineCtx *de_ctx, - DetectEngineThreadCtx *det_ctx, const Signature *s, Flow *f, - uint8_t *payload, uint32_t payload_len) + DetectEngineThreadCtx *det_ctx, const Signature *s, + Flow *f, Packet *p) { SCEnter(); - int r = 0; - - if (s->sm_arrays[DETECT_SM_LIST_PMATCH] == NULL) { - SCReturnInt(0); - } - det_ctx->buffer_offset = 0; - det_ctx->discontinue_matching = 0; - det_ctx->inspection_recursion_counter = 0; - - r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_arrays[DETECT_SM_LIST_PMATCH], - f, payload, payload_len, 0, - DETECT_ENGINE_CONTENT_INSPECTION_MODE_STREAM, NULL); - if (r == 1) { - SCReturnInt(1); - } - - SCReturnInt(0); + uint64_t unused; + struct StreamContentInspectData inspect_data = { de_ctx, det_ctx, s, f }; + int r = StreamReassembleRaw(f->protoctx, p, + StreamContentInspectFunc, &inspect_data, + &unused); + return r; } + #ifdef UNITTESTS /** \test Not the first but the second occurence of "abc" should be used diff --git a/src/detect-engine-payload.h b/src/detect-engine-payload.h index 205f8523f4..2e243ecf63 100644 --- a/src/detect-engine-payload.h +++ b/src/detect-engine-payload.h @@ -31,7 +31,7 @@ int DetectEngineInspectPacketPayload(DetectEngineCtx *, DetectEngineThreadCtx *, const Signature *, Flow *, Packet *); int DetectEngineInspectStreamPayload(DetectEngineCtx *, DetectEngineThreadCtx *, const Signature *, Flow *, - uint8_t *, uint32_t); + Packet *); void PayloadRegisterTests(void); diff --git a/src/detect-engine-prefilter.c b/src/detect-engine-prefilter.c index 1bb2dc6495..5a1580fc05 100644 --- a/src/detect-engine-prefilter.c +++ b/src/detect-engine-prefilter.c @@ -141,7 +141,7 @@ static inline void PrefilterTx(DetectEngineThreadCtx *det_ctx, } void Prefilter(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, - Packet *p, const uint8_t flags, int has_state) + Packet *p, const uint8_t flags, const bool has_state) { SCEnter(); @@ -165,8 +165,9 @@ void Prefilter(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, /* run payload inspecting engines */ if (sgh->payload_engines && - (p->payload_len > 0 || det_ctx->smsg != NULL) && - !(p->flags & PKT_NOPAYLOAD_INSPECTION)) { + (p->payload_len || (p->flags & PKT_DETECT_HAS_STREAMDATA)) && + !(p->flags & PKT_NOPAYLOAD_INSPECTION)) + { PACKET_PROFILING_DETECT_START(p, PROF_DETECT_PF_PAYLOAD); PrefilterEngine *engine = sgh->payload_engines; while (1) { diff --git a/src/detect-engine-prefilter.h b/src/detect-engine-prefilter.h index b058cf738e..2c49136d9a 100644 --- a/src/detect-engine-prefilter.h +++ b/src/detect-engine-prefilter.h @@ -25,7 +25,7 @@ #define __DETECT_ENGINE_PREFILTER_H__ void Prefilter(DetectEngineThreadCtx *, const SigGroupHead *, Packet *p, - const uint8_t flags, int has_state); + const uint8_t flags, const bool has_state); int PrefilterAppendEngine(SigGroupHead *sgh, void (*Prefilter)(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx), diff --git a/src/detect-ssl-version.c b/src/detect-ssl-version.c index 82ac3632eb..b6d9c39701 100644 --- a/src/detect-ssl-version.c +++ b/src/detect-ssl-version.c @@ -549,104 +549,6 @@ static int DetectSslVersionTestDetect02(void) PASS; } -static int DetectSslVersionTestDetect03(void) -{ - DetectEngineCtx *de_ctx = NULL; - Flow f; - uint8_t sslbuf1[] = { 0x16 }; - uint32_t ssllen1 = sizeof(sslbuf1); - uint8_t sslbuf2[] = { 0x03 }; - uint32_t ssllen2 = sizeof(sslbuf2); - uint8_t sslbuf3[] = { 0x01 }; - uint32_t ssllen3 = sizeof(sslbuf3); - uint8_t sslbuf4[] = { 0x01, 0x00, 0x00, 0xad, 0x03, 0x02 }; - uint32_t ssllen4 = sizeof(sslbuf4); - TcpSession ssn; - Packet *p = NULL; - Signature *s = NULL; - ThreadVars th_v; - DetectEngineThreadCtx *det_ctx = NULL; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&th_v, 0, sizeof(th_v)); - memset(&f, 0, sizeof(f)); - memset(&ssn, 0, sizeof(ssn)); - - p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); - p->tcph->th_seq = htonl(1000); - - FLOW_INITIALIZE(&f); - f.protoctx = (void *)&ssn; - p->flow = &f; - p->flowflags |= FLOW_PKT_TOSERVER; - p->flowflags |= FLOW_PKT_ESTABLISHED; - p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST; - f.alproto = ALPROTO_TLS; - f.proto = p->proto; - - StreamTcpInitConfig(TRUE); - - StreamMsg *stream_msg = StreamMsgGetFromPool(); - FAIL_IF_NULL(stream_msg); - - memcpy(stream_msg->data, sslbuf4, ssllen4); - stream_msg->data_len = ssllen4; - - ssn.toserver_smsg_head = stream_msg; - ssn.toserver_smsg_tail = stream_msg; - - de_ctx = DetectEngineCtxInit(); - FAIL_IF_NULL(de_ctx); - - de_ctx->flags |= DE_QUIET; - - s = de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"TLS\"; ssl_version:tls1.0; content:\"|01 00 00 AD|\"; sid:1;)"); - FAIL_IF_NULL(s); - - SigGroupBuild(de_ctx); - DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); - - FLOWLOCK_WRLOCK(&f); - int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, - STREAM_TOSERVER, sslbuf1, ssllen1); - FAIL_IF(r != 0); - - r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOSERVER, - sslbuf2, ssllen2); - FAIL_IF(r != 0); - - r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOSERVER, - sslbuf3, ssllen3); - FAIL_IF(r != 0); - - r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOSERVER, - sslbuf4, ssllen4); - FAIL_IF(r != 0); - FLOWLOCK_UNLOCK(&f); - - SSLState *app_state = f.alstate; - FAIL_IF_NULL(app_state); - - FAIL_IF(app_state->client_connp.content_type != 0x16); - - FAIL_IF(app_state->client_connp.version != TLS_VERSION_10); - - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - - FAIL_IF_NOT(PacketAlertCheck(p, 1)); - - AppLayerParserThreadCtxFree(alp_tctx); - DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); - DetectEngineCtxFree(de_ctx); - - StreamTcpFreeConfig(TRUE); - FLOW_DESTROY(&f); - UTHFreePackets(&p, 1); - - PASS; -} - #endif /* UNITTESTS */ /** @@ -662,8 +564,6 @@ static void DetectSslVersionRegisterTests(void) DetectSslVersionTestDetect01); UtRegisterTest("DetectSslVersionTestDetect02", DetectSslVersionTestDetect02); - UtRegisterTest("DetectSslVersionTestDetect03", - DetectSslVersionTestDetect03); #endif /* UNITTESTS */ return; diff --git a/src/detect-tls-version.c b/src/detect-tls-version.c index 1f027b8247..8895e4483e 100644 --- a/src/detect-tls-version.c +++ b/src/detect-tls-version.c @@ -480,105 +480,6 @@ static int DetectTlsVersionTestDetect02(void) PASS; } - -static int DetectTlsVersionTestDetect03(void) -{ - DetectEngineCtx *de_ctx = NULL; - Flow f; - uint8_t tlsbuf1[] = { 0x16 }; - uint32_t tlslen1 = sizeof(tlsbuf1); - uint8_t tlsbuf2[] = { 0x03 }; - uint32_t tlslen2 = sizeof(tlsbuf2); - uint8_t tlsbuf3[] = { 0x01 }; - uint32_t tlslen3 = sizeof(tlsbuf3); - uint8_t tlsbuf4[] = { 0x01, 0x00, 0x00, 0xad, 0x03, 0x02 }; - uint32_t tlslen4 = sizeof(tlsbuf4); - TcpSession ssn; - Packet *p = NULL; - Signature *s = NULL; - ThreadVars th_v; - DetectEngineThreadCtx *det_ctx = NULL; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&th_v, 0, sizeof(th_v)); - memset(&f, 0, sizeof(f)); - memset(&ssn, 0, sizeof(ssn)); - - p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); - p->tcph->th_seq = htonl(1000); - - FLOW_INITIALIZE(&f); - f.protoctx = (void *)&ssn; - p->flow = &f; - p->flowflags |= FLOW_PKT_TOSERVER; - p->flowflags |= FLOW_PKT_ESTABLISHED; - p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; - f.alproto = ALPROTO_TLS; - f.proto = p->proto; - - StreamTcpInitConfig(TRUE); - - StreamMsg *stream_msg = StreamMsgGetFromPool(); - FAIL_IF_NULL(stream_msg); - - memcpy(stream_msg->data, tlsbuf4, tlslen4); - stream_msg->data_len = tlslen4; - - ssn.toserver_smsg_head = stream_msg; - ssn.toserver_smsg_tail = stream_msg; - - de_ctx = DetectEngineCtxInit(); - FAIL_IF_NULL(de_ctx); - - de_ctx->flags |= DE_QUIET; - - s = de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"TLS\"; tls.version:1.0; content:\"|01 00 00 AD|\"; sid:1;)"); - FAIL_IF_NULL(s); - - SigGroupBuild(de_ctx); - DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); - - FLOWLOCK_WRLOCK(&f); - int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, - STREAM_TOSERVER, tlsbuf1, tlslen1); - FAIL_IF(r != 0); - - r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOSERVER, - tlsbuf2, tlslen2); - FAIL_IF(r != 0); - - r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOSERVER, - tlsbuf3, tlslen3); - FAIL_IF(r != 0); - - r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOSERVER, - tlsbuf4, tlslen4); - FAIL_IF(r != 0); - FLOWLOCK_UNLOCK(&f); - - SSLState *ssl_state = f.alstate; - FAIL_IF_NULL(ssl_state); - - FAIL_IF(ssl_state->client_connp.content_type != 0x16); - - FAIL_IF(ssl_state->client_connp.version != TLS_VERSION_10); - - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - - FAIL_IF_NOT(PacketAlertCheck(p, 1)); - - AppLayerParserThreadCtxFree(alp_tctx); - DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); - DetectEngineCtxFree(de_ctx); - - StreamTcpFreeConfig(TRUE); - FLOW_DESTROY(&f); - UTHFreePackets(&p, 1); - - PASS; -} - #endif /* UNITTESTS */ /** @@ -593,8 +494,6 @@ static void DetectTlsVersionRegisterTests(void) DetectTlsVersionTestDetect01); UtRegisterTest("DetectTlsVersionTestDetect02", DetectTlsVersionTestDetect02); - UtRegisterTest("DetectTlsVersionTestDetect03", - DetectTlsVersionTestDetect03); #endif /* UNITTESTS */ } diff --git a/src/detect-uricontent.c b/src/detect-uricontent.c index b541e08735..61227b2a04 100644 --- a/src/detect-uricontent.c +++ b/src/detect-uricontent.c @@ -998,19 +998,6 @@ static int DetectUriSigTest05(void) f.proto = p->proto; StreamTcpInitConfig(TRUE); - - StreamMsg *stream_msg = StreamMsgGetFromPool(); - if (stream_msg == NULL) { - printf("no stream_msg: "); - goto end; - } - - memcpy(stream_msg->data, httpbuf1, httplen1); - stream_msg->data_len = httplen1; - - ssn.toserver_smsg_head = stream_msg; - ssn.toserver_smsg_tail = stream_msg; - de_ctx = DetectEngineCtxInit(); if (de_ctx == NULL) { goto end; @@ -1127,19 +1114,6 @@ static int DetectUriSigTest06(void) f.proto = p->proto; StreamTcpInitConfig(TRUE); - - StreamMsg *stream_msg = StreamMsgGetFromPool(); - if (stream_msg == NULL) { - printf("no stream_msg: "); - goto end; - } - - memcpy(stream_msg->data, httpbuf1, httplen1); - stream_msg->data_len = httplen1; - - ssn.toserver_smsg_head = stream_msg; - ssn.toserver_smsg_tail = stream_msg; - de_ctx = DetectEngineCtxInit(); if (de_ctx == NULL) { goto end; diff --git a/src/detect.c b/src/detect.c index 6edede5442..ca6cdb385d 100644 --- a/src/detect.c +++ b/src/detect.c @@ -237,7 +237,7 @@ void DetectExitPrintStats(ThreadVars *tv, void *data); void DbgPrintSigs(DetectEngineCtx *, SigGroupHead *); void DbgPrintSigs2(DetectEngineCtx *, SigGroupHead *); -static void PacketCreateMask(Packet *, SignatureMask *, uint16_t, int, StreamMsg *, int); +static void PacketCreateMask(Packet *, SignatureMask *, AppProto, bool, int); /** * \brief Create the path if default-rule-path was specified @@ -639,103 +639,6 @@ SigGroupHead *SigMatchSignaturesGetSgh(DetectEngineCtx *de_ctx, DetectEngineThre SCReturnPtr(sgh, "SigGroupHead"); } -/** \brief Get the smsgs relevant to this packet - * - * \param f LOCKED flow - * \param p packet - * \param flags stream flags - */ -static StreamMsg *SigMatchSignaturesGetSmsg(Flow *f, Packet *p, uint8_t flags) -{ - SCEnter(); - - DEBUG_ASSERT_FLOW_LOCKED(f); - - StreamMsg *smsg = NULL; - - if (p->proto == IPPROTO_TCP && f->protoctx != NULL && (p->flags & PKT_STREAM_EST)) { - TcpSession *ssn = (TcpSession *)f->protoctx; - - /* at stream eof, or in inline mode, inspect all smsg's */ - if ((flags & STREAM_EOF) || StreamTcpInlineMode()) { - if (p->flowflags & FLOW_PKT_TOSERVER) { - smsg = ssn->toserver_smsg_head; - /* deref from the ssn */ - ssn->toserver_smsg_head = NULL; - ssn->toserver_smsg_tail = NULL; - - SCLogDebug("to_server smsg %p at stream eof", smsg); - if (smsg) - SCLogDebug("to_server smsg %p, size %u, SEQ %u", smsg, smsg->data_len, smsg->seq); - } else { - smsg = ssn->toclient_smsg_head; - /* deref from the ssn */ - ssn->toclient_smsg_head = NULL; - ssn->toclient_smsg_tail = NULL; - - SCLogDebug("to_client smsg %p at stream eof", smsg); - if (smsg) - SCLogDebug("to_client smsg %p, size %u, SEQ %u", smsg, smsg->data_len, smsg->seq); - } - } else { - if (p->flowflags & FLOW_PKT_TOSERVER) { - StreamMsg *head = ssn->toserver_smsg_head; - if (unlikely(head == NULL)) { - SCLogDebug("no smsgs in to_server direction"); - goto end; - } - - /* if the smsg is bigger than the current packet, we will - * process the smsg in a later run */ - if (SEQ_GT((head->seq + head->data_len), (TCP_GET_SEQ(p) + p->payload_len))) { - SCLogDebug("smsg ends beyond current packet, skipping for now %"PRIu32">%"PRIu32, - (head->seq + head->data_len), (TCP_GET_SEQ(p) + p->payload_len)); - goto end; - } - - smsg = head; - /* deref from the ssn */ - ssn->toserver_smsg_head = NULL; - ssn->toserver_smsg_tail = NULL; - - SCLogDebug("to_server smsg %p, size %u, SEQ %u", smsg, smsg->data_len, smsg->seq); - } else { - StreamMsg *head = ssn->toclient_smsg_head; - if (unlikely(head == NULL)) - goto end; - - /* if the smsg is bigger than the current packet, we will - * process the smsg in a later run */ - if (SEQ_GT((head->seq + head->data_len), (TCP_GET_SEQ(p) + p->payload_len))) { - SCLogDebug("smsg ends beyond current packet, skipping for now %"PRIu32">%"PRIu32, - (head->seq + head->data_len), (TCP_GET_SEQ(p) + p->payload_len)); - goto end; - } - - smsg = head; - /* deref from the ssn */ - ssn->toclient_smsg_head = NULL; - ssn->toclient_smsg_tail = NULL; - - SCLogDebug("to_client smsg %p, size %u, SEQ %u", smsg, smsg->data_len, smsg->seq); - } - } - } - -end: -#ifdef DEBUG - if (SCLogDebugEnabled()) { - StreamMsg *m = smsg; - while(m) { - SCLogDebug("m %p size %u, SEQ %u", m, m->data_len, m->seq); - PrintRawDataFp(stdout, m->data, m->data_len); - m = m->next; - } - } -#endif - SCReturnPtr(smsg, "StreamMsg"); -} - static inline void DetectPrefilterMergeSort(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx) { @@ -863,17 +766,6 @@ static inline void DetectPrefilterMergeSort(DetectEngineCtx *de_ctx, #define SMS_USE_FLOW_SGH 0x01 #define SMS_USED_PM 0x02 -#ifdef DEBUG -static void DebugInspectIds(Packet *p, Flow *f, StreamMsg *smsg) -{ - SCLogDebug("pcap_cnt %02"PRIu64", %s, %12s, smsg %s", - p->pcap_cnt, p->flowflags & FLOW_PKT_TOSERVER ? "toserver" : "toclient", - p->flags & PKT_STREAM_EST ? "established" : "stateless", - smsg ? "yes" : "no"); - AppLayerParserStatePrintDetails(f->alparser); -} -#endif - static inline void DetectPrefilterBuildNonPrefilterList(DetectEngineThreadCtx *det_ctx, SignatureMask mask) { @@ -1000,7 +892,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh int state_alert = 0; int alerts = 0; int app_decoder_events = 0; - int has_state = 0; /* do we have an alstate to work with? */ + bool has_state = false; /* do we have an alstate to work with? */ SCEnter(); @@ -1009,8 +901,8 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh det_ctx->ticker++; p->alerts.cnt = 0; det_ctx->filestore_cnt = 0; - det_ctx->smsg = NULL; det_ctx->base64_decoded_len = 0; + det_ctx->raw_stream_progress = 0; /* No need to perform any detection on this packet, if the the given flag is set.*/ if (p->flags & PKT_NOPACKET_INSPECTION) { @@ -1083,17 +975,6 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh sms_runflags |= SMS_USE_FLOW_SGH; } PACKET_PROFILING_DETECT_END(p, PROF_DETECT_GETSGH); - - det_ctx->smsg = SigMatchSignaturesGetSmsg(pflow, p, flow_flags); -#if 0 - StreamMsg *tmpsmsg = smsg; - while (tmpsmsg) { - printf("detect ---start---:\n"); - PrintRawDataFp(stdout,tmpsmsg->data.data,tmpsmsg->data.data_len); - printf("detect ---end---:\n"); - tmpsmsg = tmpsmsg->next; - } -#endif } /* Retrieve the app layer state and protocol and the tcp reassembled @@ -1106,6 +987,10 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh flow_flags = FlowGetDisruptionFlags(pflow, flow_flags); has_state = (FlowGetAppState(pflow) != NULL); alproto = FlowGetAppProtocol(pflow); + if (p->proto == IPPROTO_TCP && pflow->protoctx && + StreamReassembleRawHasDataReady(pflow->protoctx, p)) { + p->flags |= PKT_DETECT_HAS_STREAMDATA; + } SCLogDebug("alstate %s, alproto %u", has_state ? "true" : "false", alproto); } else { SCLogDebug("packet doesn't have established flag set (proto %d)", p->proto); @@ -1151,11 +1036,6 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh PACKET_PROFILING_DETECT_END(p, PROF_DETECT_GETSGH); } -#ifdef DEBUG - if (pflow) { - DebugInspectIds(p, pflow, det_ctx->smsg); - } -#endif } else { /* p->flags & PKT_HAS_FLOW */ /* no flow */ @@ -1194,8 +1074,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh /* create our prefilter mask */ SignatureMask mask = 0; - PacketCreateMask(p, &mask, alproto, has_state, det_ctx->smsg, - app_decoder_events); + PacketCreateMask(p, &mask, alproto, has_state, app_decoder_events); /* build and prefilter non_pf list against the mask of the packet */ PACKET_PROFILING_DETECT_START(p, PROF_DETECT_NONMPMLIST); @@ -1382,33 +1261,25 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh /* if we have stream msgs, inspect against those first, * but not for a "dsize" signature */ if (sflags & SIG_FLAG_REQUIRE_STREAM) { - char pmatch = 0; - if (det_ctx->smsg != NULL) { - StreamMsg *smsg_inspect = det_ctx->smsg; - for ( ; smsg_inspect != NULL; smsg_inspect = smsg_inspect->next) { - if (DetectEngineInspectStreamPayload(de_ctx, det_ctx, s, pflow, smsg_inspect->data, smsg_inspect->data_len) == 1) { - SCLogDebug("match in smsg %p", smsg_inspect); - pmatch = 1; - det_ctx->flags |= DETECT_ENGINE_THREAD_CTX_STREAM_CONTENT_MATCH; - /* Tell the engine that this reassembled stream can drop the - * rest of the pkts with no further inspection */ - if (s->action & ACTION_DROP) - alert_flags |= PACKET_ALERT_FLAG_DROP_FLOW; - - alert_flags |= PACKET_ALERT_FLAG_STREAM_MATCH; - break; - } + int pmatch = 0; + if (p->flags & PKT_DETECT_HAS_STREAMDATA) { + pmatch = DetectEngineInspectStreamPayload(de_ctx, det_ctx, s, pflow, p); + if (pmatch) { + det_ctx->flags |= DETECT_ENGINE_THREAD_CTX_STREAM_CONTENT_MATCH; + /* Tell the engine that this reassembled stream can drop the + * rest of the pkts with no further inspection */ + if (s->action & ACTION_DROP) + alert_flags |= PACKET_ALERT_FLAG_DROP_FLOW; + + alert_flags |= PACKET_ALERT_FLAG_STREAM_MATCH; } - - } /* if (smsg != NULL) */ - + } /* no match? then inspect packet payload */ if (pmatch == 0) { SCLogDebug("no match in smsg, fall back to packet payload"); - if (!(sflags & SIG_FLAG_REQUIRE_PACKET)) { - if (p->flags & PKT_STREAM_ADD) - goto next; + if (!(sflags & SIG_FLAG_REQUIRE_PACKET) && (p->flags & PKT_STREAM_ADD)) { + goto next; } if (DetectEngineInspectPacketPayload(de_ctx, det_ctx, s, pflow, p) != 1) { @@ -1448,7 +1319,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh /* consider stateful sig matches */ if (sflags & SIG_FLAG_STATE_MATCH) { - if (has_state == 0) { + if (has_state == false) { SCLogDebug("state matches but no state, we can't match"); goto next; } @@ -1542,10 +1413,13 @@ end: DetectPostInspectFirstSGH(p, pflow, det_ctx->sgh); } - /* if we had no alerts that involved the smsgs, - * we can get rid of them now. */ - StreamMsgReturnListToPool(det_ctx->smsg); - det_ctx->smsg = NULL; + /* update inspected tracker for raw reassembly */ + if (p->proto == IPPROTO_TCP && pflow->protoctx != NULL && + det_ctx->raw_stream_progress > 0) + { + StreamReassembleRawUpdateProgress(pflow->protoctx, p, + det_ctx->raw_stream_progress); + } } PACKET_PROFILING_DETECT_END(p, PROF_DETECT_CLEANUP); @@ -2062,13 +1936,15 @@ deonly: * SIG_MASK_REQUIRE_HTTP_STATE, SIG_MASK_REQUIRE_DCE_STATE */ static void -PacketCreateMask(Packet *p, SignatureMask *mask, AppProto alproto, int has_state, StreamMsg *smsg, - int app_decoder_events) +PacketCreateMask(Packet *p, SignatureMask *mask, AppProto alproto, + bool has_state, int app_decoder_events) { - /* no payload inspect flag doesn't apply to smsg */ - if (smsg != NULL || (!(p->flags & PKT_NOPAYLOAD_INSPECTION) && p->payload_len > 0)) { + if (!(p->flags & PKT_NOPAYLOAD_INSPECTION) && p->payload_len > 0) { SCLogDebug("packet has payload"); (*mask) |= SIG_MASK_REQUIRE_PAYLOAD; + } else if (p->flags & PKT_DETECT_HAS_STREAMDATA) { + SCLogDebug("stream data available"); + (*mask) |= SIG_MASK_REQUIRE_PAYLOAD; } else { SCLogDebug("packet has no payload"); (*mask) |= SIG_MASK_REQUIRE_NO_PAYLOAD; diff --git a/src/detect.h b/src/detect.h index bda17fb4e8..1a3286d66e 100644 --- a/src/detect.h +++ b/src/detect.h @@ -791,6 +791,8 @@ typedef struct DetectEngineThreadCtx_ { /* detection engine variables */ + uint64_t raw_stream_progress; + /** offset into the payload of the last match by: * content, pcre, etc */ uint32_t buffer_offset; @@ -864,8 +866,6 @@ typedef struct DetectEngineThreadCtx_ { MpmThreadCtx mtcs; /**< thread ctx for stream mpm */ PrefilterRuleStore pmq; - StreamMsg *smsg; - /** SPM thread context used for scanning. This has been cloned from the * prototype held by DetectEngineCtx. */ SpmThreadCtx *spm_thread_ctx; diff --git a/src/stream-tcp-list.c b/src/stream-tcp-list.c index 524a0a4e16..89e3ffb1ae 100644 --- a/src/stream-tcp-list.c +++ b/src/stream-tcp-list.c @@ -584,18 +584,6 @@ int StreamTcpReassembleInsertSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ static inline int SegmentInUse(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 + TCP_SEG_LEN(seg), ssn->toserver_smsg_head->seq))) { - SCReturnInt(1); - } - } else if (stream == &ssn->server && ssn->toclient_smsg_head != NULL) { - /* not (seg is entirely before first smsg, skip) */ - if (!(SEQ_LEQ(seg->seq + TCP_SEG_LEN(seg), ssn->toclient_smsg_head->seq))) { - SCReturnInt(1); - } - } - /* if proto detect isn't done, we're not returning */ if (!(stream->flags & STREAMTCP_STREAM_FLAG_GAP)) { if (!(StreamTcpIsSetStreamFlagAppProtoDetectionCompleted(stream))) { @@ -610,9 +598,6 @@ static inline int SegmentInUse(TcpSession *ssn, TcpStream *stream, TcpSegment *s /** \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 */ diff --git a/src/stream-tcp-private.h b/src/stream-tcp-private.h index 7e78c7fbad..f51e8ac8ff 100644 --- a/src/stream-tcp-private.h +++ b/src/stream-tcp-private.h @@ -232,11 +232,6 @@ typedef struct TcpSession_ { uint32_t reassembly_depth; /**< reassembly depth for the stream */ TcpStream server; TcpStream client; - struct StreamMsg_ *toserver_smsg_head; /**< list of stream msgs (for detection inspection) */ - struct StreamMsg_ *toserver_smsg_tail; /**< list of stream msgs (for detection inspection) */ - struct StreamMsg_ *toclient_smsg_head; /**< list of stream msgs (for detection inspection) */ - struct StreamMsg_ *toclient_smsg_tail; /**< list of stream msgs (for detection inspection) */ - TcpStateQueue *queue; /**< list of SYN/ACK candidates */ } TcpSession; diff --git a/src/stream-tcp-reassemble.c b/src/stream-tcp-reassemble.c index 8f471a5a00..48587b7efc 100644 --- a/src/stream-tcp-reassemble.c +++ b/src/stream-tcp-reassemble.c @@ -363,21 +363,14 @@ int StreamTcpReassemblyConfig(char quiet) SCLogInfo("stream.reassembly \"segment-prealloc\": %u", segment_prealloc); stream_config.prealloc_segments = segment_prealloc; - uint32_t stream_chunk_prealloc = 250; - ConfNode *chunk = ConfGetNode("stream.reassembly.chunk-prealloc"); - if (chunk) { - uint32_t prealloc = 0; - if (ByteExtractStringUint32(&prealloc, 10, strlen(chunk->val), chunk->val) == -1) - { - SCLogError(SC_ERR_INVALID_ARGUMENT, "chunk-prealloc of " - "%s is invalid", chunk->val); - return -1; - } - stream_chunk_prealloc = prealloc; + int overlap_diff_data = 0; + ConfGetBool("stream.reassembly.check-overlap-different-data", &overlap_diff_data); + if (overlap_diff_data) { + StreamTcpReassembleConfigEnableOverlapCheck(); + } + if (StreamTcpInlineMode() == TRUE) { + StreamTcpReassembleConfigEnableOverlapCheck(); } - if (!quiet) - SCLogConfig("stream.reassembly \"chunk-prealloc\": %u", stream_chunk_prealloc); - StreamMsgQueuesInit(stream_chunk_prealloc); stream_config.sbcnf.flags = STREAMING_BUFFER_NOFLAGS; stream_config.sbcnf.buf_size = 2048; @@ -407,8 +400,6 @@ int StreamTcpReassembleInit(char quiet) void StreamTcpReassembleFree(char quiet) { - StreamMsgQueuesDeinit(quiet); - SCMutexLock(&segment_thread_pool_mutex); if (segment_thread_pool != NULL) { PoolThreadFree(segment_thread_pool); @@ -584,56 +575,6 @@ static uint32_t StreamTcpReassembleCheckDepth(TcpSession *ssn, TcpStream *stream SCReturnUInt(0); } -static void StreamTcpStoreStreamChunk(TcpSession *ssn, StreamMsg *smsg, const Packet *p, int streaminline) -{ - uint8_t direction = 0; - - if ((!streaminline && (p->flowflags & FLOW_PKT_TOSERVER)) || - ( streaminline && (p->flowflags & FLOW_PKT_TOCLIENT))) - { - direction = STREAM_TOCLIENT; - SCLogDebug("stream chunk is to_client"); - } else { - direction = STREAM_TOSERVER; - SCLogDebug("stream chunk is to_server"); - } - - /* store the smsg in the tcp stream */ - if (direction == STREAM_TOSERVER) { - SCLogDebug("storing smsg in the to_server"); - - /* put the smsg in the stream list */ - if (ssn->toserver_smsg_head == NULL) { - ssn->toserver_smsg_head = smsg; - ssn->toserver_smsg_tail = smsg; - smsg->next = NULL; - smsg->prev = NULL; - } else { - StreamMsg *cur = ssn->toserver_smsg_tail; - cur->next = smsg; - smsg->prev = cur; - smsg->next = NULL; - ssn->toserver_smsg_tail = smsg; - } - } else { - SCLogDebug("storing smsg in the to_client"); - - /* put the smsg in the stream list */ - if (ssn->toclient_smsg_head == NULL) { - ssn->toclient_smsg_head = smsg; - ssn->toclient_smsg_tail = smsg; - smsg->next = NULL; - smsg->prev = NULL; - } else { - StreamMsg *cur = ssn->toclient_smsg_tail; - cur->next = smsg; - smsg->prev = cur; - smsg->next = NULL; - ssn->toclient_smsg_tail = smsg; - } - } -} - /** * \brief Insert a packets TCP data into the stream reassembly engine. * @@ -790,47 +731,46 @@ static int StreamTcpReassembleRawCheckLimit(TcpSession *ssn, SCReturnInt(1); /* check if we have enough data to do raw reassembly */ - if (p->flowflags & FLOW_PKT_TOCLIENT) { - SCLogDebug("StreamMsgQueueGetMinChunkLen(STREAM_TOSERVER) %"PRIu32, - StreamMsgQueueGetMinChunkLen(FLOW_PKT_TOSERVER)); - - uint32_t delta = stream->last_ack - stream->base_seq; - /* get max absolute offset */ - uint64_t max_offset = STREAM_BASE_OFFSET(stream) + delta; - - int64_t diff = max_offset - STREAM_RAW_PROGRESS(stream); - - if ((int64_t)StreamMsgQueueGetMinChunkLen(FLOW_PKT_TOSERVER) > - diff) { - SCLogDebug("toserver min chunk len not yet reached: " - "last_ack %"PRIu32", ra_raw_base_seq %"PRIu32", %"PRIu32" < " - "%"PRIu32"", stream->last_ack, stream->base_seq, - (stream->last_ack - stream->base_seq), - StreamMsgQueueGetMinChunkLen(FLOW_PKT_TOSERVER)); - SCReturnInt(0); + if (PKT_IS_TOSERVER(p)) { + if (STREAM_LASTACK_GT_BASESEQ(stream)) { + uint32_t delta = stream->last_ack - stream->base_seq; + /* get max absolute offset */ + uint64_t max_offset = STREAM_BASE_OFFSET(stream) + delta; + + int64_t diff = max_offset - STREAM_RAW_PROGRESS(stream); + if ((int64_t)stream_config.reassembly_toserver_chunk_size <= diff) { + SCReturnInt(1); + } else { + SCLogDebug("toserver min chunk len not yet reached: " + "last_ack %"PRIu32", ra_raw_base_seq %"PRIu32", %"PRIu32" < " + "%"PRIu32"", stream->last_ack, stream->base_seq, + (stream->last_ack - stream->base_seq), + stream_config.reassembly_toserver_chunk_size); + SCReturnInt(0); + } } } else { - SCLogDebug("StreamMsgQueueGetMinChunkLen(STREAM_TOCLIENT) %"PRIu32, - StreamMsgQueueGetMinChunkLen(FLOW_PKT_TOCLIENT)); - - uint32_t delta = stream->last_ack - stream->base_seq; - /* get max absolute offset */ - uint64_t max_offset = STREAM_BASE_OFFSET(stream) + delta; + if (STREAM_LASTACK_GT_BASESEQ(stream)) { + uint32_t delta = stream->last_ack - stream->base_seq; + /* get max absolute offset */ + uint64_t max_offset = STREAM_BASE_OFFSET(stream) + delta; - int64_t diff = max_offset - STREAM_RAW_PROGRESS(stream); + int64_t diff = max_offset - STREAM_RAW_PROGRESS(stream); - if ((int64_t)StreamMsgQueueGetMinChunkLen(FLOW_PKT_TOCLIENT) > - diff) { - SCLogDebug("toclient min chunk len not yet reached: " - "last_ack %"PRIu32", base_seq %"PRIu32", %"PRIu32" < " - "%"PRIu32"", stream->last_ack, stream->base_seq, - (stream->last_ack - stream->base_seq), - StreamMsgQueueGetMinChunkLen(FLOW_PKT_TOCLIENT)); - SCReturnInt(0); + if ((int64_t)stream_config.reassembly_toclient_chunk_size <= diff) { + SCReturnInt(1); + } else { + SCLogDebug("toclient min chunk len not yet reached: " + "last_ack %"PRIu32", base_seq %"PRIu32", %"PRIu32" < " + "%"PRIu32"", stream->last_ack, stream->base_seq, + (stream->last_ack - stream->base_seq), + stream_config.reassembly_toclient_chunk_size); + SCReturnInt(0); + } } } - SCReturnInt(1); + SCReturnInt(0); } /** @@ -839,20 +779,17 @@ static int StreamTcpReassembleRawCheckLimit(TcpSession *ssn, int StreamNeedsReassembly(TcpSession *ssn, int direction) { TcpStream *stream = NULL; - StreamMsg *head = NULL; #ifdef DEBUG char *dirstr = NULL; #endif /* TODO use STREAM_TOCLIENT/STREAM_TOSERVER */ if (direction == 0) { stream = &ssn->client; - head = ssn->toserver_smsg_head; #ifdef DEBUG dirstr = "client"; #endif } else { stream = &ssn->server; - head = ssn->toclient_smsg_head; #ifdef DEBUG dirstr = "server"; #endif @@ -900,11 +837,6 @@ int StreamNeedsReassembly(TcpSession *ssn, int direction) SCLogDebug("%s: no list", dirstr); } - if (head != NULL) { - SCLogDebug("%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION", dirstr); - return STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION; - } - SCLogDebug("%s: STREAM_HAS_UNPROCESSED_SEGMENTS_NONE", dirstr); return STREAM_HAS_UNPROCESSED_SEGMENTS_NONE; } @@ -1225,12 +1157,97 @@ static int GetRawBuffer(TcpStream *stream, const uint8_t **data, uint32_t *data_ return 0; } -/** \internal - * \brief based on the data in the streaming buffer setup StreamMsgs +/** \brief does the stream engine have data to inspect? + * + * Returns true if there is data to inspect. In IDS case this is + * about ACK'd data in the packet's direction. + * + * In the IPS case this is about the packet itself. + */ +bool StreamReassembleRawHasDataReady(TcpSession *ssn, Packet *p) +{ + TcpStream *stream; + if (PKT_IS_TOSERVER(p)) { + stream = &ssn->client; + } else { + stream = &ssn->server; + } + + uint64_t progress = STREAM_RAW_PROGRESS(stream); + if (StreamTcpInlineMode() == FALSE) { + if (StreamTcpReassembleRawCheckLimit(ssn, stream, p) == 1) { + uint32_t delta = stream->last_ack - stream->base_seq; + /* get max absolute offset */ + uint64_t last_ack_abs = STREAM_BASE_OFFSET(stream) + delta; + if (last_ack_abs > progress) { + return true; + } + } + } else { + if (p->payload_len > 0 && (p->flags & PKT_STREAM_ADD)) { + return true; + } + } + return false; +} + +/** \brief Update stream after inspection has run + */ +void StreamReassembleRawUpdateProgress(TcpSession *ssn, Packet *p, uint64_t progress) +{ + TcpStream *stream; + if (PKT_IS_TOSERVER(p)) { + stream = &ssn->client; + } else { + stream = &ssn->server; + } + + if (progress > STREAM_RAW_PROGRESS(stream)) { + uint32_t slide = progress - STREAM_RAW_PROGRESS(stream); + stream->raw_progress_rel += slide; + } + + SCLogDebug("stream raw progress now %"PRIu64, STREAM_RAW_PROGRESS(stream)); +} + +/** \brief access 'raw' reassembly data. + * + * Access data as tracked by 'raw' tracker. Data is made available to + * callback that is passed to this function. + * + * In the case of IDS the callback may be run multiple times if data + * contains gaps. It will then be run for each block of data that is + * continuous. + * + * The callback should give on of 2 return values: + * - 0 ok + * - 1 done + * The value 1 will break the loop if there is a block list that is + * inspected. + * + * This function will return the 'progress' value that has been + * consumed until now. + * + * \param ssn tcp session + * \param p packet + * \param Callback the function pointer to the callback function + * \param cb_data callback data + * \param[out] progress_out absolute progress value of the data this + * call handled. */ -static int ReassembleRaw(TcpSession *ssn, TcpStream *stream, Packet *p) +int StreamReassembleRaw(TcpSession *ssn, const Packet *p, + StreamReassembleRawFunc Callback, void *cb_data, + uint64_t *progress_out) { SCEnter(); + int r = 0; + + TcpStream *stream; + if (PKT_IS_TOSERVER(p)) { + stream = &ssn->client; + } else { + stream = &ssn->server; + } StreamingBufferBlock *iter = NULL; uint64_t progress = STREAM_RAW_PROGRESS(stream); @@ -1309,9 +1326,9 @@ static int ReassembleRaw(TcpSession *ssn, TcpStream *stream, Packet *p) /* StreamTcpInlineMode() == TRUE */ } else { if (progress + mydata_len > right_edge_abs) { - uint32_t delta = (progress + mydata_len) - right_edge_abs; - SCLogDebug("adjusting mydata_len %u to subtract %u", mydata_len, delta); - mydata_len -= delta; + uint32_t delta2 = (progress + mydata_len) - right_edge_abs; + SCLogDebug("adjusting mydata_len %u to subtract %u", mydata_len, delta2); + mydata_len -= delta2; } } if (mydata_len == 0) @@ -1331,43 +1348,15 @@ static int ReassembleRaw(TcpSession *ssn, TcpStream *stream, Packet *p) #define GET_SEQ_FOR_PROGRESS(stream, progress) \ (((progress) - STREAM_BASE_OFFSET((stream))) + (stream->base_seq)) - /* we have data. Use it to setup StreamMsg(s) */ - StreamMsg *smsg = NULL; - uint32_t data_offset = 0; - uint32_t data_left = mydata_len; - while (data_left) { - smsg = StreamMsgGetFromPool(); - if (smsg == NULL) - break; - - uint32_t copy_len = (data_left > smsg->data_size) ? smsg->data_size : data_left; - SCLogDebug("copy_len %u, data_left %u", copy_len, data_left); - - memcpy(smsg->data, mydata + data_offset, copy_len); - smsg->data_len = copy_len; - smsg->seq = GET_SEQ_FOR_PROGRESS(stream, (mydata_offset + data_offset)); - SCLogDebug("smsg %p seq %u", smsg, smsg->seq); - - BUG_ON(copy_len > data_left); - data_left -= copy_len; - BUG_ON(data_left > mydata_len); - data_offset += copy_len; - - SCLogDebug("smsg %p %u/%u", smsg, smsg->data_len, smsg->data_size); - //PrintRawDataFp(stdout, smsg->data, smsg->data_len); - - StreamTcpStoreStreamChunk(ssn, smsg, p, StreamTcpInlineMode()); - } + /* we have data. */ + r = Callback(cb_data, mydata, mydata_len); + BUG_ON(r < 0); if (mydata_offset == progress) { SCLogDebug("raw progress %"PRIu64" increasing with data len %u to %"PRIu64, progress, mydata_len, STREAM_RAW_PROGRESS(stream) + mydata_len); - //if (StreamTcpInlineMode() == TRUE) { - //progress = right_edge_abs; - //} else { progress += mydata_len; - //} SCLogDebug("raw progress now %"PRIu64, progress); /* data is beyond the progress we'd like, and before last ack. Gap. */ @@ -1382,56 +1371,12 @@ static int ReassembleRaw(TcpSession *ssn, TcpStream *stream, Packet *p) "%"PRIu64" != progress %"PRIu64, mydata_offset, progress); } - if (iter == NULL) + if (iter == NULL || r == 1) break; } end: - if (progress > STREAM_RAW_PROGRESS(stream)) { - uint32_t slide = progress - STREAM_RAW_PROGRESS(stream); - stream->raw_progress_rel += slide; - } - - SCLogDebug("stream raw progress now %"PRIu64, STREAM_RAW_PROGRESS(stream)); - return 0; -} - -/** - * \brief Update the stream reassembly upon receiving an ACK packet. - * \todo this function is too long, we need to break it up. It needs it BAD - */ -int StreamTcpReassembleRaw (ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, - TcpSession *ssn, TcpStream *stream, Packet *p) -{ - SCEnter(); - SCLogDebug("start p %p", p); - - if (ssn->flags & STREAMTCP_FLAG_DISABLE_RAW) - SCReturnInt(0); - - if (stream->seg_list == NULL) { - SCLogDebug("no segments in the list to reassemble"); - SCReturnInt(0); - } - -#if 0 - if (ssn->state <= TCP_ESTABLISHED && - !StreamTcpIsSetStreamFlagAppProtoDetectionCompleted(stream)) { - SCLogDebug("only starting raw reassembly after app layer protocol " - "detection has completed."); - SCReturnInt(0); - } -#endif - /* check if we have enough data */ - if (StreamTcpInlineMode() == FALSE && - StreamTcpReassembleRawCheckLimit(ssn,stream,p) == 0) - { - SCLogDebug("not yet reassembling"); - SCReturnInt(0); - } - - /* take the data we have, and turn it into StreamMsgs */ - ReassembleRaw(ssn, stream, p); - SCReturnInt(0); + *progress_out = progress; + return r; } /** \brief update app layer and raw reassembly @@ -1449,8 +1394,6 @@ int StreamTcpReassembleHandleSegmentUpdateACK (ThreadVars *tv, if (!(StreamTcpInlineMode())) { if (StreamTcpReassembleAppLayer(tv, ra_ctx, ssn, stream, p) < 0) r = -1; - if (StreamTcpReassembleRaw(tv, ra_ctx, ssn, stream, p) < 0) - r = -1; } SCLogDebug("stream->seg_list %p", stream->seg_list); @@ -1500,8 +1443,6 @@ int StreamTcpReassembleHandleSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ int r = 0; if (StreamTcpReassembleAppLayer(tv, ra_ctx, ssn, stream, p) < 0) r = -1; - if (StreamTcpReassembleRaw(tv, ra_ctx, ssn, stream, p) < 0) - r = -1; if (r < 0) { SCReturnInt(-1); @@ -1525,7 +1466,6 @@ TcpSegment *StreamTcpGetSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx) segment request due to memcap limit */ StatsIncr(tv, ra_ctx->counter_tcp_segment_memcap); } else { - seg->flags = stream_config.segment_init_flags; seg->next = NULL; seg->prev = NULL; @@ -1567,272 +1507,6 @@ void StreamTcpReassembleTriggerRawReassembly(TcpSession *ssn) (stream)->isn = (setseq); \ (stream)->base_seq = (setseq) + 1 -static int UtTestSmsg(StreamMsg *smsg, const uint8_t *buf, uint32_t buf_len) -{ - if (smsg == NULL) - return 0; - - if (smsg->data_len != buf_len) { - printf("Got: data_len %u, expected %u\n", smsg->data_len, buf_len); - PrintRawDataFp(stdout, smsg->data, smsg->data_len); - return 0; - } - - if (!(memcmp(buf, smsg->data, buf_len) == 0)) { - printf("data is not what we expected:\nExpected:\n"); - PrintRawDataFp(stdout, (uint8_t *)buf, buf_len); - printf("Got:\n"); - PrintRawDataFp(stdout, smsg->data, smsg->data_len); - return 0; - } - return 1; -} - -static uint32_t UtSsnSmsgCnt(TcpSession *ssn, uint8_t direction) -{ - uint32_t cnt = 0; - StreamMsg *smsg = (direction == STREAM_TOSERVER) ? - ssn->toserver_smsg_head : - ssn->toclient_smsg_head; - while (smsg) { - cnt++; - smsg = smsg->next; - } - return cnt; -} - -#if 0 -/** \brief The Function tests the reassembly engine working for different - * OSes supported. It includes all the OS cases and send - * crafted packets to test the reassembly. - * - * \param stream The stream which will contain the reassembled segments - */ - -static int StreamTcpReassembleStreamTest(TcpStream *stream) -{ - - TcpSession ssn; - Packet *p = PacketGetFromAlloc(); - if (unlikely(p == NULL)) - return 0; - Flow f; - uint8_t payload[4]; - TCPHdr tcph; - TcpReassemblyThreadCtx *ra_ctx = StreamTcpReassembleInitThreadCtx(NULL); - - /* prevent L7 from kicking in */ - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 4096); - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 4096); - PacketQueue pq; - memset(&pq,0,sizeof(PacketQueue)); - - memset(&ssn, 0, sizeof (TcpSession)); - memset(&f, 0, sizeof (Flow)); - memset(&tcph, 0, sizeof (TCPHdr)); - ThreadVars tv; - memset(&tv, 0, sizeof (ThreadVars)); - FLOW_INITIALIZE(&f); - f.protoctx = &ssn; - f.proto = IPPROTO_TCP; - p->src.family = AF_INET; - p->dst.family = AF_INET; - p->proto = IPPROTO_TCP; - p->flow = &f; - tcph.th_win = 5480; - tcph.th_flags = TH_PUSH | TH_ACK; - p->tcph = &tcph; - p->flowflags = FLOW_PKT_TOSERVER; - SET_ISN(&ssn.client, 10); - SET_ISN(&ssn.server, 10); - - StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/ - p->tcph->th_seq = htonl(12); - p->tcph->th_ack = htonl(31); - p->payload = payload; - p->payload_len = 3; - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, stream, p, &pq) == -1) { - SCFree(p); - return 0; - } - - StreamTcpCreateTestPacket(payload, 0x42, 2, 4); /*BB*/ - p->tcph->th_seq = htonl(16); - p->tcph->th_ack = htonl(31); - p->payload = payload; - p->payload_len = 2; - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, stream, p, &pq) == -1) { - SCFree(p); - return 0; - } - - StreamTcpCreateTestPacket(payload, 0x43, 3, 4); /*CCC*/ - p->tcph->th_seq = htonl(18); - p->tcph->th_ack = htonl(31); - p->payload = payload; - p->payload_len = 3; - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, stream, p, &pq) == -1) { - SCFree(p); - return 0; - } - - StreamTcpCreateTestPacket(payload, 0x44, 1, 4); /*D*/ - p->tcph->th_seq = htonl(22); - p->tcph->th_ack = htonl(31); - p->payload = payload; - p->payload_len = 1; - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, stream, p, &pq) == -1) { - SCFree(p); - return 0; - } - - StreamTcpCreateTestPacket(payload, 0x45, 2, 4); /*EE*/ - p->tcph->th_seq = htonl(25); - p->tcph->th_ack = htonl(31); - p->payload = payload; - p->payload_len = 2; - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, stream, p, &pq) == -1) { - SCFree(p); - return 0; - } - - StreamTcpCreateTestPacket(payload, 0x46, 3, 4); /*FFF*/ - p->tcph->th_seq = htonl(27); - p->tcph->th_ack = htonl(31); - p->payload = payload; - p->payload_len = 3; - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, stream, p, &pq) == -1) { - SCFree(p); - return 0; - } - - StreamTcpCreateTestPacket(payload, 0x47, 2, 4); /*GG*/ - p->tcph->th_seq = htonl(30); - p->tcph->th_ack = htonl(31); - p->payload = payload; - p->payload_len = 2; - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, stream, p, &pq) == -1) { - SCFree(p); - return 0; - } - - StreamTcpCreateTestPacket(payload, 0x48, 2, 4); /*HH*/ - p->tcph->th_seq = htonl(32); - p->tcph->th_ack = htonl(31); - p->payload = payload; - p->payload_len = 2; - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, stream, p, &pq) == -1) { - SCFree(p); - return 0; - } - - StreamTcpCreateTestPacket(payload, 0x49, 1, 4); /*I*/ - p->tcph->th_seq = htonl(34); - p->tcph->th_ack = htonl(31); - p->payload = payload; - p->payload_len = 1; - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, stream, p, &pq) == -1) { - SCFree(p); - return 0; - } - - StreamTcpCreateTestPacket(payload, 0x4a, 4, 4); /*JJJJ*/ - p->tcph->th_seq = htonl(13); - p->tcph->th_ack = htonl(31); - p->payload = payload; - p->payload_len = 4; - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, stream, p, &pq) == -1) { - SCFree(p); - return 0; - } - - StreamTcpCreateTestPacket(payload, 0x4b, 3, 4); /*KKK*/ - p->tcph->th_seq = htonl(18); - p->tcph->th_ack = htonl(31); - p->payload = payload; - p->payload_len = 3; - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, stream, p, &pq) == -1) { - SCFree(p); - return 0; - } - - StreamTcpCreateTestPacket(payload, 0x4c, 3, 4); /*LLL*/ - p->tcph->th_seq = htonl(21); - p->tcph->th_ack = htonl(31); - p->payload = payload; - p->payload_len = 3; - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, stream, p, &pq) == -1) { - SCFree(p); - return 0; - } - - StreamTcpCreateTestPacket(payload, 0x4d, 3, 4); /*MMM*/ - p->tcph->th_seq = htonl(24); - p->tcph->th_ack = htonl(31); - p->payload = payload; - p->payload_len = 3; - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, stream, p, &pq) == -1) { - SCFree(p); - return 0; - } - - StreamTcpCreateTestPacket(payload, 0x4e, 1, 4); /*N*/ - p->tcph->th_seq = htonl(28); - p->tcph->th_ack = htonl(31); - p->payload = payload; - p->payload_len = 1; - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, stream, p, &pq) == -1) { - SCFree(p); - return 0; - } - - StreamTcpCreateTestPacket(payload, 0x4f, 1, 4); /*O*/ - p->tcph->th_seq = htonl(31); - p->tcph->th_ack = htonl(31); - p->payload = payload; - p->payload_len = 1; - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, stream, p, &pq) == -1) { - SCFree(p); - return 0; - } - - StreamTcpCreateTestPacket(payload, 0x50, 1, 4); /*P*/ - p->tcph->th_seq = htonl(32); - p->tcph->th_ack = htonl(31); - p->payload = payload; - p->payload_len = 1; - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, stream, p, &pq) == -1) { - SCFree(p); - return 0; - } - - StreamTcpCreateTestPacket(payload, 0x51, 2, 4); /*QQ*/ - p->tcph->th_seq = htonl(34); - p->tcph->th_ack = htonl(31); - p->payload = payload; - p->payload_len = 2; - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, stream, p, &pq) == -1) { - SCFree(p); - return 0; - } - - StreamTcpCreateTestPacket(payload, 0x30, 1, 4); /*0*/ - p->tcph->th_seq = htonl(11); - p->tcph->th_ack = htonl(31); - p->payload = payload; - p->payload_len = 1; - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, stream, p, &pq) == -1) { - SCFree(p); - return 0; - } - - StreamTcpReassembleFreeThreadCtx(ra_ctx); - - SCFree(p); - return 1; -} -#endif - /** \brief The Function to create the packet with given payload, which is used * to test the reassembly of the engine. * @@ -2064,11 +1738,6 @@ static int StreamTcpReassembleTest34(void) StreamTcpUTInit(&ra_ctx); StreamTcpUTSetupSession(&ssn); - - /* prevent L7 from kicking in */ - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 4096); - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 4096); - PacketQueue pq; memset(&pq,0,sizeof(PacketQueue)); memset(&f, 0, sizeof (Flow)); @@ -2135,11 +1804,6 @@ static int StreamTcpReassembleTest37(void) StreamTcpUTInit(&ra_ctx); StreamTcpUTSetupSession(&ssn); - - /* prevent L7 from kicking in */ - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 10); - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 10); - memset(&pq,0,sizeof(PacketQueue)); memset(&f, 0, sizeof (Flow)); memset(&tcph, 0, sizeof (TCPHdr)); @@ -2188,98 +1852,6 @@ static int StreamTcpReassembleTest37(void) PASS; } -/** - * \test Test to make sure we don't send the smsg from toclient to app layer - * until the app layer protocol has been detected and one smsg from - * toserver side has been sent to app layer. - * - * \retval On success it returns 1 and on failure 0. - */ -static int StreamTcpReassembleTest38 (void) -{ - Packet *p = PacketGetFromAlloc(); - FAIL_IF(unlikely(p == NULL)); - Flow f; - TCPHdr tcph; - Port sp; - Port dp; - struct in_addr in; - TcpSession ssn; - PacketQueue pq; - memset(&pq,0,sizeof(PacketQueue)); - memset(&f, 0, sizeof (Flow)); - memset(&tcph, 0, sizeof (TCPHdr)); - ThreadVars tv; - memset(&tv, 0, sizeof (ThreadVars)); - TcpReassemblyThreadCtx *ra_ctx = NULL; - - StreamTcpUTInit(&ra_ctx); - StreamTcpUTSetupSession(&ssn); - - uint8_t httpbuf2[] = "POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\n"; - uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */ - - uint8_t httpbuf1[] = "HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n"; - uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ - - FLOW_INITIALIZE(&f); - FAIL_IF(inet_pton(AF_INET, "1.2.3.4", &in) != 1); - f.src.addr_data32[0] = in.s_addr; - FAIL_IF(inet_pton(AF_INET, "1.2.3.5", &in) != 1); - f.dst.addr_data32[0] = in.s_addr; - sp = 200; - dp = 220; - - SET_ISN(&ssn.server, 9); - ssn.server.last_ack = 60; - SET_ISN(&ssn.client, 9); - ssn.client.last_ack = 9; - f.alproto = ALPROTO_UNKNOWN; - - f.flags |= FLOW_IPV4; - f.sp = sp; - f.dp = dp; - f.protoctx = &ssn; - f.proto = IPPROTO_TCP; - p->flow = &f; - - tcph.th_win = htons(5480); - tcph.th_seq = htonl(10); - tcph.th_ack = htonl(20); - tcph.th_flags = TH_ACK|TH_PUSH; - p->tcph = &tcph; - p->flowflags = FLOW_PKT_TOSERVER; - - p->payload = httpbuf2; - p->payload_len = httplen2; - ssn.state = TCP_ESTABLISHED; - - TcpStream *s = NULL; - s = &ssn.server; - - FAIL_IF(StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1); - - /* Check if we have stream smsgs in queue */ - FAIL_IF(UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) > 0); - - p->flowflags = FLOW_PKT_TOCLIENT; - p->payload = httpbuf1; - p->payload_len = httplen1; - tcph.th_seq = htonl(10); - tcph.th_ack = htonl(55); - s = &ssn.client; - - FAIL_IF(StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1); - - /* Check if we have stream smsgs in queue */ - FAIL_IF(UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) != 1); - - StreamTcpUTClearSession(&ssn); - StreamTcpUTDeinit(ra_ctx); - SCFree(p); - PASS; -} - /** * \test Test to make sure that we don't return the segments until the app * layer proto has been detected and after that remove the processed @@ -2336,8 +1908,6 @@ static int StreamTcpReassembleTest39 (void) FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || ssn->client.seg_list != NULL || ssn->server.seg_list != NULL || - ssn->toserver_smsg_head != NULL || - ssn->toclient_smsg_head != NULL || ssn->data_first_seen_dir != 0) { printf("failure 1\n"); goto end; @@ -2361,8 +1931,6 @@ static int StreamTcpReassembleTest39 (void) FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || ssn->client.seg_list != NULL || ssn->server.seg_list != NULL || - ssn->toserver_smsg_head != NULL || - ssn->toclient_smsg_head != NULL || ssn->data_first_seen_dir != 0) { printf("failure 2\n"); goto end; @@ -2387,8 +1955,6 @@ static int StreamTcpReassembleTest39 (void) FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || ssn->client.seg_list != NULL || ssn->server.seg_list != NULL || - ssn->toserver_smsg_head != NULL || - ssn->toclient_smsg_head != NULL || ssn->data_first_seen_dir != 0) { printf("failure 3\n"); goto end; @@ -2415,8 +1981,6 @@ static int StreamTcpReassembleTest39 (void) ssn->client.seg_list == NULL || ssn->client.seg_list->next != NULL || ssn->server.seg_list != NULL || - ssn->toserver_smsg_head != NULL || - ssn->toclient_smsg_head != NULL || ssn->data_first_seen_dir != STREAM_TOSERVER) { printf("failure 4\n"); goto end; @@ -2443,8 +2007,6 @@ static int StreamTcpReassembleTest39 (void) ssn->client.seg_list == NULL || ssn->client.seg_list->next != NULL || ssn->server.seg_list != NULL || - ssn->toserver_smsg_head != NULL || - ssn->toclient_smsg_head != NULL || ssn->data_first_seen_dir != STREAM_TOSERVER) { printf("failure 5\n"); goto end; @@ -2483,8 +2045,6 @@ static int StreamTcpReassembleTest39 (void) ssn->client.seg_list->next == NULL || ssn->client.seg_list->next->next != NULL || ssn->server.seg_list != NULL || - ssn->toserver_smsg_head != NULL || - ssn->toclient_smsg_head != NULL || ssn->data_first_seen_dir != STREAM_TOSERVER) { printf("failure 6\n"); goto end; @@ -2776,21 +2336,6 @@ static int StreamTcpReassembleTest39 (void) printf("failure 15\n"); goto end; } - - if (ssn->toserver_smsg_head == NULL || - ssn->toserver_smsg_head->next == NULL || - ssn->toserver_smsg_head->next->next != NULL || - ssn->toclient_smsg_head == NULL || - ssn->toclient_smsg_head->next != NULL) { - printf("failure 16\n"); - goto end; - } - - StreamMsgReturnListToPool(ssn->toserver_smsg_head); - ssn->toserver_smsg_head = ssn->toserver_smsg_tail = NULL; - StreamMsgReturnListToPool(ssn->toclient_smsg_head); - ssn->toclient_smsg_head = ssn->toclient_smsg_tail = NULL; - /* response acking a request */ p->tcph->th_ack = htonl(175); p->tcph->th_seq = htonl(328); @@ -2837,6 +2382,7 @@ static int StreamTcpReassembleTest39 (void) p->payload = NULL; if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) goto end; +#if 0 if (//!StreamTcpIsSetStreamFlagAppProtoDetectionCompleted(&ssn->server) || //!StreamTcpIsSetStreamFlagAppProtoDetectionCompleted(&ssn->client) || //f.alproto != ALPROTO_HTTP || @@ -2853,7 +2399,7 @@ static int StreamTcpReassembleTest39 (void) abort(); goto end; } - +#endif ret = 1; end: @@ -2888,7 +2434,6 @@ static int StreamTcpReassembleTest40 (void) StreamTcpInitConfig(TRUE); StreamTcpUTSetupSession(&ssn); - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 130); TcpReassemblyThreadCtx *ra_ctx = StreamTcpReassembleInitThreadCtx(NULL); @@ -2935,14 +2480,6 @@ static int StreamTcpReassembleTest40 (void) printf("failed in segments reassembly, while processing toserver packet (1): "); goto end; } - - /* Check if we have stream smsgs in queue */ - if (UtSsnSmsgCnt(&ssn, STREAM_TOCLIENT) > 0) { - printf("there shouldn't be any stream smsgs in the queue, as we didn't" - " processed any smsg from toserver side till yet (2): "); - goto end; - } - p->flowflags = FLOW_PKT_TOCLIENT; p->payload = httpbuf2; p->payload_len = httplen2; @@ -2985,7 +2522,6 @@ static int StreamTcpReassembleTest40 (void) /* check is have the segment in the list and flagged or not */ if (ssn.client.seg_list == NULL || SEGMENT_BEFORE_OFFSET(&ssn.client, ssn.client.seg_list, STREAM_APP_PROGRESS(&ssn.client))) -// (ssn.client.seg_list->flags & SEGMENTTCP_FLAG_APPLAYER_PROCESSED)) { printf("the list is NULL or the processed segment has not been flaged (7): "); goto end; @@ -3042,15 +2578,6 @@ static int StreamTcpReassembleTest40 (void) printf("failed in segments reassembly, while processing toserver packet (15): "); goto end; } - - /* Check if we have stream smsgs in queue */ - if (UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) == 0) { - printf("there should be a stream smsgs in the queue, as we have detected" - " the app layer protocol and one smsg from toserver side has " - "been sent (16): "); - goto end; - } - if (f->alproto != ALPROTO_HTTP) { printf("app layer proto has not been detected (18): "); goto end; @@ -3067,219 +2594,20 @@ end: return ret; } -/** - * \retval On success it returns 1 and on failure 0. - */ - -static int StreamTcpReassembleTest43 (void) -{ - int ret = 0; - Packet *p = PacketGetFromAlloc(); - if (unlikely(p == NULL)) - return 0; - Flow *f = NULL; - TCPHdr tcph; - TcpSession ssn; - PacketQueue pq; - memset(&pq,0,sizeof(PacketQueue)); - memset(&tcph, 0, sizeof (TCPHdr)); - ThreadVars tv; - memset(&tv, 0, sizeof (ThreadVars)); - - StreamTcpInitConfig(TRUE); - StreamTcpUTSetupSession(&ssn); - TcpReassemblyThreadCtx *ra_ctx = StreamTcpReassembleInitThreadCtx(NULL); - - uint8_t httpbuf1[] = "/ HTTP/1.0\r\nUser-Agent: Victor/1.0"; - - uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ - - uint8_t httpbuf2[] = "HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n"; - uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */ - - uint8_t httpbuf3[] = "W2dyb3VwMV0NCnBob25lMT1wMDB3ODgyMTMxMzAyMTINCmxvZ2lu" - "MT0NCnBhc3N3b3JkMT0NCnBob25lMj1wMDB3ODgyMTMxMzAyMTIN" - "CmxvZ2luMj0NCnBhc3N3b3JkMj0NCnBob25lMz0NCmxvZ2luMz0N" - "CnBhc3N3b3JkMz0NCnBob25lND0NCmxvZ2luND0NCnBhc3N3b3Jk" - "ND0NCnBob25lNT0NCmxvZ2luNT0NCnBhc3N3b3JkNT0NCnBob25l" - "Nj0NCmxvZ2luNj0NCnBhc3N3b3JkNj0NCmNhbGxfdGltZTE9MzIN" - "CmNhbGxfdGltZTI9MjMyDQpkYXlfbGltaXQ9NQ0KbW9udGhfbGlt" - "aXQ9MTUNCltncm91cDJdDQpwaG9uZTE9DQpsb2dpbjE9DQpwYXNz" - "d29yZDE9DQpwaG9uZTI9DQpsb2dpbjI9DQpwYXNzd29yZDI9DQpw" - "aG9uZT\r\n\r\n"; - uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */ - - ssn.server.base_seq= 10; - ssn.server.isn = 9; - ssn.server.last_ack = 600; - ssn.client.base_seq = 10; - ssn.client.isn = 9; - ssn.client.last_ack = 600; - - f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 200, 220); - if (f == NULL) - goto end; - f->protoctx = &ssn; - f->proto = IPPROTO_TCP; - p->flow = f; - - tcph.th_win = htons(5480); - tcph.th_seq = htonl(10); - tcph.th_ack = htonl(10); - tcph.th_flags = TH_ACK|TH_PUSH; - p->tcph = &tcph; - p->flowflags = FLOW_PKT_TOCLIENT; - - p->payload = httpbuf2; - p->payload_len = httplen2; - ssn.state = TCP_ESTABLISHED; - - TcpStream *s = NULL; - s = &ssn.server; - - FLOWLOCK_WRLOCK(f); - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) { - printf("failed in segments reassembly, while processing toserver packet (1): "); - goto end; - } - - /* Check if we have stream smsgs in queue */ - if (UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) > 0) { - printf("there shouldn't be any stream smsgs in the queue (2): "); - goto end; - } - - p->flowflags = FLOW_PKT_TOSERVER; - p->payload = httpbuf1; - p->payload_len = httplen1; - tcph.th_seq = htonl(10); - tcph.th_ack = htonl(55); - s = &ssn.client; - - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) { - printf("failed in segments reassembly, while processing toserver packet (3): "); - goto end; - } - - /* Check if we have stream smsgs in queue */ - if (UtSsnSmsgCnt(&ssn, STREAM_TOCLIENT) > 0) { - printf("there shouldn't be any stream smsgs in the queue, as we didn't" - " processed any smsg from toserver side till yet (4): "); - goto end; - } - - p->flowflags = FLOW_PKT_TOCLIENT; - p->payload = httpbuf2; - p->payload_len = httplen2; - tcph.th_seq = htonl(55); - tcph.th_ack = htonl(44); - s = &ssn.server; - - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) { - printf("failed in segments reassembly, while processing toserver packet (5): "); - goto end; - } - if (!StreamTcpIsSetStreamFlagAppProtoDetectionCompleted(&ssn.client)) { - printf("app layer detected flag isn't set, it should be (8): "); - goto end; - } - - /* This packets induces a packet gap and also shows why we need to - process the current segment completely, even if it results in sending more - than one smsg to the app layer. If we don't send more than one smsg in - this case, then the first segment of lentgh 34 bytes will be sent to - app layer and protocol can not be detected in that message and moreover - the segment lentgh is less than the max. signature size for protocol - detection, so this will keep looping !! */ - p->flowflags = FLOW_PKT_TOSERVER; - p->payload = httpbuf3; - p->payload_len = httplen3; - tcph.th_seq = htonl(54); - tcph.th_ack = htonl(100); - s = &ssn.client; - - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) { - printf("failed in segments reassembly, while processing toserver packet (9): "); - goto end; - } - - /* Check if we have stream smsgs in queue */ - if (UtSsnSmsgCnt(&ssn, STREAM_TOCLIENT) > 0) { - printf("there shouldn't be any stream smsgs in the queue, as we didn't" - " detected the app layer protocol till yet (10): "); - goto end; - } - - p->flowflags = FLOW_PKT_TOCLIENT; - p->payload = httpbuf2; - p->payload_len = httplen2; - tcph.th_seq = htonl(100); - tcph.th_ack = htonl(53); - s = &ssn.server; - - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) { - printf("failed in segments reassembly, while processing toserver packet (11): "); - goto end; - } - /* the flag should be set, as the smsg scanned size has crossed the max. - signature size for app proto detection */ - if (!StreamTcpIsSetStreamFlagAppProtoDetectionCompleted(&ssn.client)) { - printf("app layer detected flag is not set, it should be (14): "); - goto end; - } - - ret = 1; -end: - StreamTcpUTClearSession(&ssn); - StreamTcpReassembleFreeThreadCtx(ra_ctx); - StreamTcpFreeConfig(TRUE); - SCFree(p); - SCMutexUnlock(&f->m); - UTHFreeFlow(f); - return ret; -} - /** \test Test the memcap incrementing/decrementing and memcap check */ static int StreamTcpReassembleTest44(void) { - uint8_t ret = 0; StreamTcpInitConfig(TRUE); uint32_t memuse = SC_ATOMIC_GET(ra_memuse); - StreamTcpReassembleIncrMemuse(500); - if (SC_ATOMIC_GET(ra_memuse) != (memuse+500)) { - printf("failed in incrementing the memory"); - goto end; - } - + FAIL_IF(SC_ATOMIC_GET(ra_memuse) != (memuse+500)); StreamTcpReassembleDecrMemuse(500); - if (SC_ATOMIC_GET(ra_memuse) != memuse) { - printf("failed in decrementing the memory"); - goto end; - } - - if (StreamTcpReassembleCheckMemcap(500) != 1) { - printf("failed in validating the memcap"); - goto end; - } - - if (StreamTcpReassembleCheckMemcap((memuse + stream_config.reassembly_memcap)) != 0) { - printf("failed in validating the memcap"); - goto end; - } - - StreamTcpFreeConfig(TRUE); - - if (SC_ATOMIC_GET(ra_memuse) != 0) { - printf("failed in clearing the memory"); - goto end; - } - - ret = 1; - return ret; -end: + FAIL_IF(SC_ATOMIC_GET(ra_memuse) != memuse); + FAIL_IF(StreamTcpReassembleCheckMemcap(500) != 1); + FAIL_IF(StreamTcpReassembleCheckMemcap((1 + memuse + stream_config.reassembly_memcap)) != 0); StreamTcpFreeConfig(TRUE); - return ret; + FAIL_IF(SC_ATOMIC_GET(ra_memuse) != 0); + PASS; } /** @@ -3387,11 +2715,6 @@ static int StreamTcpReassembleTest47 (void) memset(&pq,0,sizeof(PacketQueue)); memset(&tcph, 0, sizeof (TCPHdr)); memset(&tv, 0, sizeof (ThreadVars)); - - /* prevent L7 from kicking in */ - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 0); - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 0); - StreamTcpInitConfig(TRUE); StreamTcpUTSetupSession(&ssn); TcpReassemblyThreadCtx *ra_ctx = StreamTcpReassembleInitThreadCtx(NULL); @@ -3467,7 +2790,6 @@ static int StreamTcpReassembleInlineTest01(void) StreamTcpUTSetupStream(&ssn.client, 1); FLOW_INITIALIZE(&f); - uint8_t stream_payload[] = "AAAAABBBBBCCCCC"; uint8_t payload[] = { 'C', 'C', 'C', 'C', 'C' }; Packet *p = UTHBuildPacketReal(payload, 5, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80); if (p == NULL) { @@ -3491,19 +2813,6 @@ static int StreamTcpReassembleInlineTest01(void) goto end; } ssn.client.next_seq = 17; - - int r = StreamTcpReassembleRaw(&tv, ra_ctx, &ssn, &ssn.client, p); - if (r < 0) { - printf("StreamTcpReassembleInlineRaw failed: "); - goto end; - } - - FAIL_IF(UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) != 1); - - StreamMsg *smsg = ssn.toserver_smsg_head; - if (UtTestSmsg(smsg, stream_payload, 15) == 0) - goto end; - ret = 1; end: FLOWLOCK_UNLOCK(&f); @@ -3533,8 +2842,6 @@ static int StreamTcpReassembleInlineTest02(void) StreamTcpUTSetupStream(&ssn.client, 1); FLOW_INITIALIZE(&f); - uint8_t stream_payload1[] = "AAAAABBBBBCCCCC"; - uint8_t stream_payload2[] = "AAAAABBBBBCCCCCDDDDD"; uint8_t payload[] = { 'C', 'C', 'C', 'C', 'C' }; Packet *p = UTHBuildPacketReal(payload, 5, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80); if (p == NULL) { @@ -3558,43 +2865,11 @@ static int StreamTcpReassembleInlineTest02(void) goto end; } ssn.client.next_seq = 17; - - int r = StreamTcpReassembleRaw(&tv, ra_ctx, &ssn, &ssn.client, p); - if (r < 0) { - printf("StreamTcpReassembleInlineRaw failed: "); - goto end; - } - - if (UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) != 1) { - printf("expected a single stream message: "); - goto end; - } - - StreamMsg *smsg = ssn.toserver_smsg_head; - if (UtTestSmsg(smsg, stream_payload1, 15) == 0) - goto end; - if (StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &ssn.client, 17, 'D', 5) == -1) { printf("failed to add segment 4: "); goto end; } ssn.client.next_seq = 22; - - r = StreamTcpReassembleRaw(&tv, ra_ctx, &ssn, &ssn.client, p); - if (r < 0) { - printf("StreamTcpReassembleInlineRaw failed 2: "); - goto end; - } - - if (UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) != 2) { - printf("expected a single stream message: "); - goto end; - } - - smsg = ssn.toserver_smsg_head->next; - if (UtTestSmsg(smsg, stream_payload2, 20) == 0) - goto end; - ret = 1; end: FLOWLOCK_UNLOCK(&f); @@ -3627,8 +2902,6 @@ static int StreamTcpReassembleInlineTest03(void) stream_config.reassembly_toserver_chunk_size = 15; - uint8_t stream_payload1[] = "AAAAABBBBBCCCCC"; - uint8_t stream_payload2[] = "BBBBBCCCCCDDDDD"; uint8_t payload[] = { 'C', 'C', 'C', 'C', 'C' }; Packet *p = UTHBuildPacketReal(payload, 5, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80); if (p == NULL) { @@ -3653,22 +2926,6 @@ static int StreamTcpReassembleInlineTest03(void) goto end; } ssn.client.next_seq = 17; - - int r = StreamTcpReassembleRaw(&tv, ra_ctx, &ssn, &ssn.client, p); - if (r < 0) { - printf("StreamTcpReassembleInlineRaw failed: "); - goto end; - } - - if (UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) != 1) { - printf("expected a single stream message 1, got %u: ", UtSsnSmsgCnt(&ssn, STREAM_TOSERVER)); - goto end; - } - - StreamMsg *smsg = ssn.toserver_smsg_head; - if (UtTestSmsg(smsg, stream_payload1, 15) == 0) - goto end; - if (StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &ssn.client, 17, 'D', 5) == -1) { printf("failed to add segment 4: "); goto end; @@ -3676,22 +2933,6 @@ static int StreamTcpReassembleInlineTest03(void) ssn.client.next_seq = 22; p->tcph->th_seq = htonl(17); - - r = StreamTcpReassembleRaw(&tv, ra_ctx, &ssn, &ssn.client, p); - if (r < 0) { - printf("StreamTcpReassembleInlineRaw failed 2: "); - goto end; - } - - if (UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) != 2) { - printf("expected two stream messages: "); - goto end; - } - - smsg = ssn.toserver_smsg_head->next; - if (UtTestSmsg(smsg, stream_payload2, 15) == 0) - goto end; - ret = 1; end: FLOWLOCK_UNLOCK(&f); @@ -3724,8 +2965,6 @@ static int StreamTcpReassembleInlineTest04(void) stream_config.reassembly_toserver_chunk_size = 16; - uint8_t stream_payload1[] = "AAAAABBBBBCCCCC"; - uint8_t stream_payload2[] = "ABBBBBCCCCCDDDDD"; uint8_t payload[] = { 'C', 'C', 'C', 'C', 'C' }; Packet *p = UTHBuildPacketReal(payload, 5, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80); if (p == NULL) { @@ -3750,22 +2989,6 @@ static int StreamTcpReassembleInlineTest04(void) goto end; } ssn.client.next_seq = 17; - - int r = StreamTcpReassembleRaw(&tv, ra_ctx, &ssn, &ssn.client, p); - if (r < 0) { - printf("StreamTcpReassembleInlineRaw failed: "); - goto end; - } - - if (UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) != 1) { - printf("expected a single stream message: "); - goto end; - } - - StreamMsg *smsg = ssn.toserver_smsg_head; - if (UtTestSmsg(smsg, stream_payload1, 15) == 0) - goto end; - if (StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &ssn.client, 17, 'D', 5) == -1) { printf("failed to add segment 4: "); goto end; @@ -3773,305 +2996,6 @@ static int StreamTcpReassembleInlineTest04(void) ssn.client.next_seq = 22; p->tcph->th_seq = htonl(17); - - r = StreamTcpReassembleRaw(&tv, ra_ctx, &ssn, &ssn.client, p); - if (r < 0) { - printf("StreamTcpReassembleInlineRaw failed 2: "); - goto end; - } - - if (UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) != 2) { - printf("expected a single stream message: "); - goto end; - } - - smsg = ssn.toserver_smsg_head->next; - if (UtTestSmsg(smsg, stream_payload2, 16) == 0) - goto end; - - ret = 1; -end: - FLOWLOCK_UNLOCK(&f); - FLOW_DESTROY(&f); - UTHFreePacket(p); - StreamTcpUTClearSession(&ssn); - StreamTcpUTDeinit(ra_ctx); - return ret; -} - -/** \test with a GAP we should have 2 smsgs */ -static int StreamTcpReassembleInlineTest05(void) -{ - int ret = 0; - TcpReassemblyThreadCtx *ra_ctx = NULL; - ThreadVars tv; - TcpSession ssn; - Flow f; - - memset(&tv, 0x00, sizeof(tv)); - - StreamTcpUTInit(&ra_ctx); - StreamTcpUTInitInline(); - StreamTcpUTSetupSession(&ssn); - StreamTcpUTSetupStream(&ssn.client, 1); - FLOW_INITIALIZE(&f); - - uint8_t stream_payload1[] = "AAAAABBBBB"; - uint8_t stream_payload2[] = "DDDDD"; - uint8_t payload[] = { 'C', 'C', 'C', 'C', 'C' }; - Packet *p = UTHBuildPacketReal(payload, 5, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80); - if (p == NULL) { - printf("couldn't get a packet: "); - goto end; - } - p->tcph->th_seq = htonl(12); - p->flow = &f; - - FLOWLOCK_WRLOCK(&f); - if (StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &ssn.client, 2, 'A', 5) == -1) { - printf("failed to add segment 1: "); - goto end; - } - if (StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &ssn.client, 7, 'B', 5) == -1) { - printf("failed to add segment 2: "); - goto end; - } - ssn.client.next_seq = 12; - - if (StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &ssn.client, 17, 'D', 5) == -1) { - printf("failed to add segment 4: "); - goto end; - } - - p->tcph->th_seq = htonl(17); - - int r = StreamTcpReassembleRaw(&tv, ra_ctx, &ssn, &ssn.client, p); - if (r < 0) { - printf("StreamTcpReassembleInlineRaw failed: "); - goto end; - } - - if (UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) != 2) { - printf("expected a single stream message: "); - goto end; - } - - StreamMsg *smsg = ssn.toserver_smsg_head; - if (UtTestSmsg(smsg, stream_payload1, 10) == 0) - goto end; - - smsg = ssn.toserver_smsg_head->next; - if (UtTestSmsg(smsg, stream_payload2, 5) == 0) - goto end; - - ret = 1; -end: - FLOWLOCK_UNLOCK(&f); - FLOW_DESTROY(&f); - UTHFreePacket(p); - StreamTcpUTClearSession(&ssn); - StreamTcpUTDeinit(ra_ctx); - return ret; -} - -/** \test with a GAP we should have 2 smsgs, with filling the GAP later */ -static int StreamTcpReassembleInlineTest06(void) -{ - int ret = 0; - TcpReassemblyThreadCtx *ra_ctx = NULL; - ThreadVars tv; - TcpSession ssn; - Flow f; - - memset(&tv, 0x00, sizeof(tv)); - - StreamTcpUTInit(&ra_ctx); - StreamTcpUTInitInline(); - StreamTcpUTSetupSession(&ssn); - StreamTcpUTSetupStream(&ssn.client, 1); - FLOW_INITIALIZE(&f); - - uint8_t stream_payload1[] = "AAAAABBBBB"; - uint8_t stream_payload2[] = "DDDDD"; - uint8_t stream_payload3[] = "AAAAABBBBBCCCCCDDDDD"; - uint8_t payload[] = { 'C', 'C', 'C', 'C', 'C' }; - Packet *p = UTHBuildPacketReal(payload, 5, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80); - if (p == NULL) { - printf("couldn't get a packet: "); - goto end; - } - p->tcph->th_seq = htonl(12); - p->flow = &f; - - FLOWLOCK_WRLOCK(&f); - if (StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &ssn.client, 2, 'A', 5) == -1) { - printf("failed to add segment 1: "); - goto end; - } - if (StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &ssn.client, 7, 'B', 5) == -1) { - printf("failed to add segment 2: "); - goto end; - } - ssn.client.next_seq = 12; - - if (StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &ssn.client, 17, 'D', 5) == -1) { - printf("failed to add segment 4: "); - goto end; - } - - p->tcph->th_seq = htonl(17); - - int r = StreamTcpReassembleRaw(&tv, ra_ctx, &ssn, &ssn.client, p); - if (r < 0) { - printf("StreamTcpReassembleInlineRaw failed: "); - goto end; - } - - if (UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) != 2) { - printf("expected two stream messages: "); - goto end; - } - - StreamMsg *smsg = ssn.toserver_smsg_head; - if (UtTestSmsg(smsg, stream_payload1, 10) == 0) - goto end; - - smsg = ssn.toserver_smsg_head->next; - if (UtTestSmsg(smsg, stream_payload2, 5) == 0) - goto end; - - if (StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &ssn.client, 12, 'C', 5) == -1) { - printf("failed to add segment 3: "); - goto end; - } - ssn.client.next_seq = 22; - - p->tcph->th_seq = htonl(12); - - r = StreamTcpReassembleRaw(&tv, ra_ctx, &ssn, &ssn.client, p); - if (r < 0) { - printf("StreamTcpReassembleInlineRaw failed: "); - goto end; - } - - if (UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) != 3) { - printf("expected a single stream message, got %u: ", UtSsnSmsgCnt(&ssn, STREAM_TOSERVER)); - goto end; - } - - smsg = ssn.toserver_smsg_head->next->next; - if (UtTestSmsg(smsg, stream_payload3, 20) == 0) - goto end; - - ret = 1; -end: - FLOWLOCK_UNLOCK(&f); - FLOW_DESTROY(&f); - UTHFreePacket(p); - StreamTcpUTClearSession(&ssn); - StreamTcpUTDeinit(ra_ctx); - return ret; -} - -/** \test with a GAP we should have 2 smsgs, with filling the GAP later, small - * window */ -static int StreamTcpReassembleInlineTest07(void) -{ - int ret = 0; - TcpReassemblyThreadCtx *ra_ctx = NULL; - ThreadVars tv; - TcpSession ssn; - Flow f; - - memset(&tv, 0x00, sizeof(tv)); - - StreamTcpUTInit(&ra_ctx); - StreamTcpUTInitInline(); - StreamTcpUTSetupSession(&ssn); - StreamTcpUTSetupStream(&ssn.client, 1); - FLOW_INITIALIZE(&f); - - stream_config.reassembly_toserver_chunk_size = 16; - - uint8_t stream_payload1[] = "ABBBBB"; - uint8_t stream_payload2[] = "DDDDD"; - uint8_t stream_payload3[] = "AAAAABBBBBCCCCCD"; - uint8_t payload[] = { 'C', 'C', 'C', 'C', 'C' }; - Packet *p = UTHBuildPacketReal(payload, 5, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80); - if (p == NULL) { - printf("couldn't get a packet: "); - goto end; - } - p->tcph->th_seq = htonl(12); - p->flow = &f; - p->flowflags |= FLOW_PKT_TOSERVER; - - FLOWLOCK_WRLOCK(&f); - if (StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &ssn.client, 2, 'A', 5) == -1) { - printf("failed to add segment 1: "); - goto end; - } - if (StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &ssn.client, 7, 'B', 5) == -1) { - printf("failed to add segment 2: "); - goto end; - } - ssn.client.next_seq = 12; - - if (StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &ssn.client, 17, 'D', 5) == -1) { - printf("failed to add segment 4: "); - goto end; - } - - p->tcph->th_seq = htonl(17); - - int r = StreamTcpReassembleRaw(&tv, ra_ctx, &ssn, &ssn.client, p); - if (r < 0) { - printf("StreamTcpReassembleInlineRaw failed: "); - goto end; - } - - if (UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) != 2) { - printf("expected a single stream message, got %u: ", UtSsnSmsgCnt(&ssn, STREAM_TOSERVER)); - goto end; - } - - StreamMsg *smsg = ssn.toserver_smsg_head; - if (UtTestSmsg(smsg, stream_payload1, 6) == 0) { - printf("stream_payload1 failed: "); - goto end; - } - - smsg = ssn.toserver_smsg_head->next; - if (UtTestSmsg(smsg, stream_payload2, 5) == 0) { - printf("stream_payload2 failed: "); - goto end; - } - - if (StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &ssn.client, 12, 'C', 5) == -1) { - printf("failed to add segment 3: "); - goto end; - } - ssn.client.next_seq = 22; - - p->tcph->th_seq = htonl(12); - - r = StreamTcpReassembleRaw(&tv, ra_ctx, &ssn, &ssn.client, p); - if (r < 0) { - printf("StreamTcpReassembleInlineRaw failed: "); - goto end; - } - - if (UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) != 3) { - printf("expected a single stream message, got %u: ", UtSsnSmsgCnt(&ssn, STREAM_TOSERVER)); - goto end; - } - - smsg = ssn.toserver_smsg_head->next->next; - if (UtTestSmsg(smsg, stream_payload3, 16) == 0) { - printf("stream_payload3 failed: "); - goto end; - } - ret = 1; end: FLOWLOCK_UNLOCK(&f); @@ -4104,8 +3028,6 @@ static int StreamTcpReassembleInlineTest08(void) ssn.client.flags |= STREAMTCP_STREAM_FLAG_GAP; f.protoctx = &ssn; - uint8_t stream_payload1[] = "AAAAABBBBBCCCCC"; - uint8_t stream_payload2[] = "BBBBBCCCCCDDDDD"; uint8_t payload[] = { 'C', 'C', 'C', 'C', 'C' }; Packet *p = UTHBuildPacketReal(payload, 5, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80); FAIL_IF(p == NULL); @@ -4117,33 +3039,9 @@ static int StreamTcpReassembleInlineTest08(void) FAIL_IF(StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &ssn.client, 7, 'B', 5) == -1); FAIL_IF(StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &ssn.client, 12, 'C', 5) == -1); ssn.client.next_seq = 17; - - int r = StreamTcpReassembleRaw(&tv, ra_ctx, &ssn, &ssn.client, p); - FAIL_IF(r < 0); - - FAIL_IF(UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) != 1); - StreamMsg *smsg = ssn.toserver_smsg_head; - FAIL_IF(UtTestSmsg(smsg, stream_payload1, 15) == 0); - - FAIL_IF(STREAM_RAW_PROGRESS(&ssn.client) != 15); FAIL_IF(StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &ssn.client, 17, 'D', 5) == -1); ssn.client.next_seq = 22; p->tcph->th_seq = htonl(17); - - r = StreamTcpReassembleRaw(&tv, ra_ctx, &ssn, &ssn.client, p); - FAIL_IF (r < 0); - - FAIL_IF(UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) != 2); - - smsg = ssn.toserver_smsg_head->next; - FAIL_IF(UtTestSmsg(smsg, stream_payload2, 15) == 0); - - FAIL_IF(STREAM_RAW_PROGRESS(&ssn.client) != 20); - - smsg = ssn.toserver_smsg_head; - StreamMsgReturnToPool(smsg); - ssn.toserver_smsg_head = ssn.toserver_smsg_head->next; - StreamTcpPruneSession(&f, STREAM_TOSERVER); FAIL_IF (ssn.client.seg_list->seq != 2); @@ -4179,9 +3077,6 @@ static int StreamTcpReassembleInlineTest09(void) stream_config.reassembly_toserver_chunk_size = 20; ssn.client.flags |= STREAMTCP_STREAM_FLAG_GAP; - uint8_t stream_payload1[] = "AAAAABBBBBCCCCC"; - uint8_t stream_payload2[] = "DDDDD"; - uint8_t stream_payload3[] = "AAAAABBBBBCCCCCDDDDD"; uint8_t payload[] = { 'C', 'C', 'C', 'C', 'C' }; Packet *p = UTHBuildPacketReal(payload, 5, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80); if (p == NULL) { @@ -4208,27 +3103,6 @@ static int StreamTcpReassembleInlineTest09(void) ssn.client.next_seq = 12; ssn.client.last_ack = 10; - int r = StreamTcpReassembleRaw(&tv, ra_ctx, &ssn, &ssn.client, p); - if (r < 0) { - printf("StreamTcpReassembleInlineRaw failed: "); - goto end; - } - - if (UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) != 2) { - printf("expected 2 stream message2, got %u: ", UtSsnSmsgCnt(&ssn, STREAM_TOSERVER)); - goto end; - } - - StreamMsg *smsg = ssn.toserver_smsg_head; - if (UtTestSmsg(smsg, stream_payload1, 10) == 0) - goto end; - - smsg = ssn.toserver_smsg_head->next; - if (UtTestSmsg(smsg, stream_payload2, 5) == 0) - goto end; - - FAIL_IF(STREAM_RAW_PROGRESS(&ssn.client) != 10); - /* close the GAP and see if we properly reassemble and update base_seq */ if (StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &ssn.client, 12, 'C', 5) == -1) { printf("failed to add segment 4: "); @@ -4238,23 +3112,6 @@ static int StreamTcpReassembleInlineTest09(void) p->tcph->th_seq = htonl(12); - r = StreamTcpReassembleRaw(&tv, ra_ctx, &ssn, &ssn.client, p); - if (r < 0) { - printf("StreamTcpReassembleInlineRaw failed 2: "); - goto end; - } - - if (UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) != 3) { - printf("expected 3 stream messages: "); - goto end; - } - - smsg = ssn.toserver_smsg_head->next->next; - if (UtTestSmsg(smsg, stream_payload3, 20) == 0) - goto end; - - FAIL_IF(STREAM_RAW_PROGRESS(&ssn.client) != 20); - if (ssn.client.seg_list->seq != 2) { printf("expected segment 1 (seq 2) to be first in the list, got seq %"PRIu32": ", ssn.client.seg_list->seq); goto end; @@ -4378,7 +3235,6 @@ static int StreamTcpReassembleInsertTest01(void) ssn.client.os_policy = OS_POLICY_LAST; FLOW_INITIALIZE(&f); - uint8_t stream_payload1[] = "AAAAABBBBBCCCCCDDDDD"; uint8_t payload[] = { 'C', 'C', 'C', 'C', 'C' }; Packet *p = UTHBuildPacketReal(payload, 5, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80); FAIL_IF(p == NULL); @@ -4392,13 +3248,6 @@ static int StreamTcpReassembleInsertTest01(void) FAIL_IF(StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &ssn.client, 12, 'C', 5) == -1); ssn.client.next_seq = 21; - int r = StreamTcpReassembleRaw(&tv, ra_ctx, &ssn, &ssn.client, p); - FAIL_IF (r < 0); - FAIL_IF (UtSsnSmsgCnt(&ssn, STREAM_TOSERVER) != 1); - StreamMsg *smsg = ssn.toserver_smsg_head; - FAIL_IF(UtTestSmsg(smsg, stream_payload1, 20) == 0); - FAIL_IF(STREAM_RAW_PROGRESS(&ssn.client) != 20); - FLOW_DESTROY(&f); UTHFreePacket(p); StreamTcpUTClearSession(&ssn); @@ -4517,14 +3366,10 @@ void StreamTcpReassembleRegisterTests(void) StreamTcpReassembleTest34); UtRegisterTest("StreamTcpReassembleTest37 -- Bug76 test", StreamTcpReassembleTest37); - UtRegisterTest("StreamTcpReassembleTest38 -- app proto test", - StreamTcpReassembleTest38); UtRegisterTest("StreamTcpReassembleTest39 -- app proto test", StreamTcpReassembleTest39); UtRegisterTest("StreamTcpReassembleTest40 -- app proto test", StreamTcpReassembleTest40); - UtRegisterTest("StreamTcpReassembleTest43 -- min smsg size test", - StreamTcpReassembleTest43); UtRegisterTest("StreamTcpReassembleTest44 -- Memcap Test", StreamTcpReassembleTest44); UtRegisterTest("StreamTcpReassembleTest45 -- Depth Test", @@ -4542,12 +3387,6 @@ void StreamTcpReassembleRegisterTests(void) StreamTcpReassembleInlineTest03); UtRegisterTest("StreamTcpReassembleInlineTest04 -- inline RAW ra 4", StreamTcpReassembleInlineTest04); - UtRegisterTest("StreamTcpReassembleInlineTest05 -- inline RAW ra 5 GAP", - StreamTcpReassembleInlineTest05); - UtRegisterTest("StreamTcpReassembleInlineTest06 -- inline RAW ra 6 GAP", - StreamTcpReassembleInlineTest06); - UtRegisterTest("StreamTcpReassembleInlineTest07 -- inline RAW ra 7 GAP", - StreamTcpReassembleInlineTest07); UtRegisterTest("StreamTcpReassembleInlineTest08 -- inline RAW ra 8 cleanup", StreamTcpReassembleInlineTest08); UtRegisterTest("StreamTcpReassembleInlineTest09 -- inline RAW ra 9 GAP cleanup", diff --git a/src/stream-tcp-reassemble.h b/src/stream-tcp-reassemble.h index 8f3a3a6803..f2bbf277e5 100644 --- a/src/stream-tcp-reassemble.h +++ b/src/stream-tcp-reassemble.h @@ -118,5 +118,7 @@ int StreamTcpAppLayerIsDisabled(Flow *f); int StreamTcpCheckStreamContents(uint8_t *, uint16_t , TcpStream *); #endif +bool StreamReassembleRawHasDataReady(TcpSession *ssn, Packet *p); + #endif /* __STREAM_TCP_REASSEMBLE_H__ */ diff --git a/src/stream-tcp.c b/src/stream-tcp.c index 126c7fde72..82cfcfd10d 100644 --- a/src/stream-tcp.c +++ b/src/stream-tcp.c @@ -187,8 +187,6 @@ void StreamTcpStreamCleanup(TcpStream *stream) void StreamTcpSessionCleanup(TcpSession *ssn) { SCEnter(); - - StreamMsg *smsg = NULL; TcpStateQueue *q, *q_next; if (ssn == NULL) @@ -197,29 +195,6 @@ void StreamTcpSessionCleanup(TcpSession *ssn) StreamTcpStreamCleanup(&ssn->client); StreamTcpStreamCleanup(&ssn->server); - /* if we have (a) smsg(s), return to the pool */ - smsg = ssn->toserver_smsg_head; - while(smsg != NULL) { - StreamMsg *smsg_next = smsg->next; - SCLogDebug("returning smsg %p to pool", smsg); - smsg->next = NULL; - smsg->prev = NULL; - StreamMsgReturnToPool(smsg); - smsg = smsg_next; - } - ssn->toserver_smsg_head = NULL; - - smsg = ssn->toclient_smsg_head; - while(smsg != NULL) { - StreamMsg *smsg_next = smsg->next; - SCLogDebug("returning smsg %p to pool", smsg); - smsg->next = NULL; - smsg->prev = NULL; - StreamMsgReturnToPool(smsg); - smsg = smsg_next; - } - ssn->toclient_smsg_head = NULL; - q = ssn->queue; while (q != NULL) { q_next = q->next; @@ -553,9 +528,6 @@ void StreamTcpInitConfig(char quiet) (int) (stream_config.reassembly_toserver_chunk_size * (r * 1.0 / RAND_MAX - 0.5) * rdrange / 100); } - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, - stream_config.reassembly_toserver_chunk_size); - char *temp_stream_reassembly_toclient_chunk_size_str; if (ConfGet("stream.reassembly.toclient-chunk-size", &temp_stream_reassembly_toclient_chunk_size_str) == 1) { @@ -578,10 +550,6 @@ void StreamTcpInitConfig(char quiet) (int) (stream_config.reassembly_toclient_chunk_size * (r * 1.0 / RAND_MAX - 0.5) * rdrange / 100); } - - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, - stream_config.reassembly_toclient_chunk_size); - if (!quiet) { SCLogConfig("stream.reassembly \"toserver-chunk-size\": %"PRIu16, stream_config.reassembly_toserver_chunk_size); @@ -593,8 +561,6 @@ void StreamTcpInitConfig(char quiet) if (ConfGetBool("stream.reassembly.raw", &enable_raw) == 1) { if (!enable_raw) { stream_config.ssn_init_flags = STREAMTCP_FLAG_DISABLE_RAW; -// TODO how to handle this now? -// stream_config.segment_init_flags = SEGMENTTCP_FLAG_RAW_PROCESSED; } } else { enable_raw = 1; @@ -6170,11 +6136,6 @@ static int StreamTcpTest05 (void) int ret = 0; StreamTcpUTInit(&stt.ra_ctx); - - /* prevent L7 from kicking in */ - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 4096); - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 4096); - tcph.th_win = htons(5480); tcph.th_seq = htonl(10); tcph.th_ack = htonl(20); @@ -7004,11 +6965,6 @@ static int StreamTcpTest14 (void) strlcpy(os_policy_name, "linux\0", sizeof(os_policy_name)); ip_addr = StreamTcpParseOSPolicy(os_policy_name); SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1); - - /* prevent L7 from kicking in */ - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 4096); - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 4096); - addr.s_addr = inet_addr("192.168.0.1"); tcph.th_win = htons(5480); tcph.th_seq = htonl(10); @@ -7411,11 +7367,6 @@ static int StreamTcpTest15 (void) strlcpy(os_policy_name, "linux\0", sizeof(os_policy_name)); ip_addr = StreamTcpParseOSPolicy(os_policy_name); SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1); - - /* prevent L7 from kicking in */ - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 4096); - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 4096); - addr.s_addr = inet_addr("192.168.0.20"); tcph.th_win = htons(5480); tcph.th_seq = htonl(10); @@ -7583,11 +7534,6 @@ static int StreamTcpTest16 (void) strlcpy(os_policy_name, "linux\0", sizeof(os_policy_name)); ip_addr = StreamTcpParseOSPolicy(os_policy_name); SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1); - - /* prevent L7 from kicking in */ - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 4096); - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 4096); - addr.s_addr = inet_addr("192.168.0.1"); tcph.th_win = htons(5480); tcph.th_seq = htonl(10); @@ -7758,11 +7704,6 @@ static int StreamTcpTest17 (void) strlcpy(os_policy_name, "linux\0", sizeof(os_policy_name)); ip_addr = StreamTcpParseOSPolicy(os_policy_name); SCHInfoAddHostOSInfo(os_policy_name, ip_addr, -1); - - /* prevent L7 from kicking in */ - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 4096); - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 4096); - addr.s_addr = inet_addr("192.168.0.1"); tcph.th_win = htons(5480); tcph.th_seq = htonl(10); @@ -8164,11 +8105,6 @@ static int StreamTcpTest23(void) StreamTcpUTInit(&stt.ra_ctx); StreamTcpUTSetupSession(&ssn); - - /* prevent L7 from kicking in */ - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 4096); - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 4096); - FLOW_INITIALIZE(&f); ssn.client.os_policy = OS_POLICY_BSD; f.protoctx = &ssn; @@ -8308,11 +8244,6 @@ static int StreamTcpTest25(void) tcph.th_flags = TH_SYN | TH_CWR; p->tcph = &tcph; p->flowflags = FLOW_PKT_TOSERVER; - - /* prevent L7 from kicking in */ - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 4096); - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 4096); - StreamTcpUTInit(&stt.ra_ctx); if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) @@ -9132,10 +9063,8 @@ static int StreamTcpTest33 (void) StreamTcpThread stt; TCPHdr tcph; TcpReassemblyThreadCtx ra_ctx; - StreamMsgQueue stream_q; PacketQueue pq; memset(&pq,0,sizeof(PacketQueue)); - memset(&stream_q, 0, sizeof(StreamMsgQueue)); memset(&ra_ctx, 0, sizeof(TcpReassemblyThreadCtx)); memset (&p, 0, SIZE_OF_PACKET); memset (&f, 0, sizeof(Flow)); @@ -9150,7 +9079,6 @@ static int StreamTcpTest33 (void) p.tcph = &tcph; p.flowflags = FLOW_PKT_TOSERVER; int ret = 0; - ra_ctx.stream_q = &stream_q; stt.ra_ctx = &ra_ctx; StreamTcpInitConfig(TRUE); @@ -9236,10 +9164,8 @@ static int StreamTcpTest34 (void) StreamTcpThread stt; TCPHdr tcph; TcpReassemblyThreadCtx ra_ctx; - StreamMsgQueue stream_q; PacketQueue pq; memset(&pq,0,sizeof(PacketQueue)); - memset(&stream_q, 0, sizeof(StreamMsgQueue)); memset(&ra_ctx, 0, sizeof(TcpReassemblyThreadCtx)); memset (&p, 0, SIZE_OF_PACKET); memset (&f, 0, sizeof(Flow)); @@ -9254,7 +9180,6 @@ static int StreamTcpTest34 (void) p.tcph = &tcph; p.flowflags = FLOW_PKT_TOSERVER; int ret = 0; - ra_ctx.stream_q = &stream_q; stt.ra_ctx = &ra_ctx; StreamTcpInitConfig(TRUE); @@ -9304,10 +9229,8 @@ static int StreamTcpTest35 (void) StreamTcpThread stt; TCPHdr tcph; TcpReassemblyThreadCtx ra_ctx; - StreamMsgQueue stream_q; PacketQueue pq; memset(&pq,0,sizeof(PacketQueue)); - memset(&stream_q, 0, sizeof(StreamMsgQueue)); memset(&ra_ctx, 0, sizeof(TcpReassemblyThreadCtx)); memset (&p, 0, SIZE_OF_PACKET); memset (&f, 0, sizeof(Flow)); @@ -9322,7 +9245,6 @@ static int StreamTcpTest35 (void) p.tcph = &tcph; p.flowflags = FLOW_PKT_TOSERVER; int ret = 0; - ra_ctx.stream_q = &stream_q; stt.ra_ctx = &ra_ctx; StreamTcpInitConfig(TRUE); @@ -9554,7 +9476,7 @@ static int StreamTcpTest37(void) } TcpStream *stream = &(((TcpSession *)p->flow->protoctx)->client); - FAIL_IF(STREAM_RAW_PROGRESS(stream) != 3); + FAIL_IF(STREAM_RAW_PROGRESS(stream) != 0); // no detect no progress update StreamTcpSessionClear(p->flow->protoctx); diff --git a/src/stream-tcp.h b/src/stream-tcp.h index 98afac2737..a04857515e 100644 --- a/src/stream-tcp.h +++ b/src/stream-tcp.h @@ -45,7 +45,6 @@ typedef struct TcpStreamCnf_ { uint64_t reassembly_memcap; /**< max memory usage for stream reassembly */ uint32_t ssn_init_flags; /**< new ssn flags will be initialized to this */ - uint8_t segment_init_flags; /**< new seg flags will be initialized to this */ uint32_t prealloc_sessions; /**< ssns to prealloc per stream thread */ uint32_t prealloc_segments; /**< segments to prealloc per stream thread */ @@ -118,6 +117,12 @@ int StreamTcpSegmentForEach(const Packet *p, uint8_t flag, void StreamTcpReassembleConfigEnableOverlapCheck(void); void TcpSessionSetReassemblyDepth(TcpSession *ssn, uint32_t size); +typedef int (*StreamReassembleRawFunc)(void *data, const uint8_t *input, const uint32_t input_len); + +int StreamReassembleRaw(TcpSession *ssn, const Packet *p, + StreamReassembleRawFunc Callback, void *cb_data, uint64_t *progress_out); +void StreamReassembleRawUpdateProgress(TcpSession *ssn, Packet *p, uint64_t progress); + /** ------- Inline functions: ------ */ /** diff --git a/src/stream.c b/src/stream.c index 6415420981..a09f125e35 100644 --- a/src/stream.c +++ b/src/stream.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2013 Open Information Security Foundation +/* Copyright (C) 2007-2017 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -19,8 +19,6 @@ * \file * * \author Victor Julien - * - * Stream Chunk Handling API */ #include "suricata-common.h" @@ -32,241 +30,6 @@ #include "stream-tcp.h" #include "flow-util.h" -#ifdef DEBUG -static SCMutex stream_pool_memuse_mutex; -static uint64_t stream_pool_memuse = 0; -static uint64_t stream_pool_memcnt = 0; -#endif - -/* per queue setting */ -static uint16_t toserver_min_chunk_len = 2560; -static uint16_t toclient_min_chunk_len = 2560; - -static Pool *stream_msg_pool = NULL; -static SCMutex stream_msg_pool_mutex = SCMUTEX_INITIALIZER; - -static void StreamMsgEnqueue (StreamMsgQueue *q, StreamMsg *s) -{ - SCEnter(); - SCLogDebug("s %p", s); - /* more packets in queue */ - if (q->top != NULL) { - s->next = q->top; - q->top->prev = s; - q->top = s; - /* only packet */ - } else { - q->top = s; - q->bot = s; - } - q->len++; -#ifdef DBG_PERF - if (q->len > q->dbg_maxlen) - q->dbg_maxlen = q->len; -#endif /* DBG_PERF */ - SCReturn; -} - -static StreamMsg *StreamMsgDequeue (StreamMsgQueue *q) -{ - SCEnter(); - - /* if the queue is empty there are no packets left. - * In that case we sleep and try again. */ - if (q->len == 0) { - SCReturnPtr(NULL, "StreamMsg"); - } - - /* pull the bottom packet from the queue */ - StreamMsg *s = q->bot; - - /* more packets in queue */ - if (q->bot->prev != NULL) { - q->bot = q->bot->prev; - q->bot->next = NULL; - /* just the one we remove, so now empty */ - } else { - q->top = NULL; - q->bot = NULL; - } - q->len--; - - s->next = NULL; - s->prev = NULL; - SCReturnPtr(s, "StreamMsg"); -} - -/* Used by stream reassembler to get msgs */ -StreamMsg *StreamMsgGetFromPool(void) -{ - SCMutexLock(&stream_msg_pool_mutex); - StreamMsg *s = (StreamMsg *)PoolGet(stream_msg_pool); - SCMutexUnlock(&stream_msg_pool_mutex); - return s; -} - -/* Used by l7inspection to return msgs to pool */ -void StreamMsgReturnToPool(StreamMsg *s) -{ - SCLogDebug("s %p", s); - SCMutexLock(&stream_msg_pool_mutex); - PoolReturn(stream_msg_pool, (void *)s); - SCMutexUnlock(&stream_msg_pool_mutex); -} - -/* Used by l7inspection to get msgs with data */ -StreamMsg *StreamMsgGetFromQueue(StreamMsgQueue *q) -{ - if (q->len > 0) { - StreamMsg *s = StreamMsgDequeue(q); - return s; - } else { - /* return NULL if we have no stream msg. Should only happen on signals. */ - return NULL; - } -} - -/* Used by stream reassembler to fill the queue for l7inspect reading */ -void StreamMsgPutInQueue(StreamMsgQueue *q, StreamMsg *s) -{ - StreamMsgEnqueue(q, s); - SCLogDebug("q->len %" PRIu32 "", q->len); -} - -#define SIZE 4072 -void *StreamMsgPoolAlloc(void) -{ - if (StreamTcpReassembleCheckMemcap((uint32_t)(sizeof(StreamMsg)+SIZE)) == 0) - return NULL; - - StreamMsg *m = SCCalloc(1, (sizeof(StreamMsg) + SIZE)); - if (m != NULL) { - m->data = (uint8_t *)m + sizeof(StreamMsg); - m->data_size = SIZE; - - StreamTcpReassembleIncrMemuse((uint32_t)(sizeof(StreamMsg)+SIZE)); - } - - return m; -} - -int StreamMsgInit(void *data, void *initdata) -{ - StreamMsg *s = data; - memset(s->data, 0, s->data_size); - -#ifdef DEBUG - SCMutexLock(&stream_pool_memuse_mutex); - stream_pool_memuse += (sizeof(StreamMsg) + SIZE); - stream_pool_memcnt ++; - SCMutexUnlock(&stream_pool_memuse_mutex); -#endif - return 1; -} - -void StreamMsgPoolFree(void *ptr) -{ - if (ptr) { - SCFree(ptr); - StreamTcpReassembleDecrMemuse((uint32_t)(sizeof(StreamMsg)+SIZE)); - } -} - -void StreamMsgQueuesInit(uint32_t prealloc) -{ -#ifdef DEBUG - SCMutexInit(&stream_pool_memuse_mutex, NULL); -#endif - SCMutexLock(&stream_msg_pool_mutex); - stream_msg_pool = PoolInit(0, prealloc, 0, - StreamMsgPoolAlloc,StreamMsgInit, - NULL,NULL,StreamMsgPoolFree); - if (stream_msg_pool == NULL) - exit(EXIT_FAILURE); /* XXX */ - SCMutexUnlock(&stream_msg_pool_mutex); -} - -void StreamMsgQueuesDeinit(char quiet) -{ - if (quiet == FALSE) { - if (stream_msg_pool->max_outstanding > stream_msg_pool->allocated) - SCLogInfo("TCP segment chunk pool had a peak use of %u chunks, " - "more than the prealloc setting of %u", - stream_msg_pool->max_outstanding, stream_msg_pool->allocated); - } - - SCMutexLock(&stream_msg_pool_mutex); - PoolFree(stream_msg_pool); - SCMutexUnlock(&stream_msg_pool_mutex); - -#ifdef DEBUG - SCMutexDestroy(&stream_pool_memuse_mutex); - - if (quiet == FALSE) - SCLogDebug("stream_pool_memuse %"PRIu64", stream_pool_memcnt %"PRIu64"", stream_pool_memuse, stream_pool_memcnt); -#endif -} - -/** \brief alloc a stream msg queue - * \retval smq ptr to the queue or NULL */ -StreamMsgQueue *StreamMsgQueueGetNew(void) -{ - if (StreamTcpReassembleCheckMemcap((uint32_t)sizeof(StreamMsgQueue)) == 0) - return NULL; - - StreamMsgQueue *smq = SCMalloc(sizeof(StreamMsgQueue)); - if (unlikely(smq == NULL)) - return NULL; - - StreamTcpReassembleIncrMemuse((uint32_t)sizeof(StreamMsgQueue)); - - memset(smq, 0x00, sizeof(StreamMsgQueue)); - return smq; -} - -/** \brief Free a StreamMsgQueue - * \param q the queue to free - * \todo we may want to consider non empty queue's - */ -void StreamMsgQueueFree(StreamMsgQueue *q) -{ - SCFree(q); - StreamTcpReassembleDecrMemuse((uint32_t)sizeof(StreamMsgQueue)); -} - -void StreamMsgQueueSetMinChunkLen(uint8_t dir, uint16_t len) -{ - if (dir == FLOW_PKT_TOSERVER) { - toserver_min_chunk_len = len; - } else { - toclient_min_chunk_len = len; - } -} - -uint16_t StreamMsgQueueGetMinChunkLen(uint8_t dir) -{ - if (dir == FLOW_PKT_TOSERVER) { - return toserver_min_chunk_len; - } else { - return toclient_min_chunk_len; - } -} - -/** \brief Return a list of smsgs to the pool */ -void StreamMsgReturnListToPool(void *list) -{ - /* if we have (a) smsg(s), return to the pool */ - StreamMsg *smsg = (StreamMsg *)list; - while (smsg != NULL) { - StreamMsg *smsg_next = smsg->next; - SCLogDebug("returning smsg %p to pool", smsg); - smsg->next = NULL; - smsg->prev = NULL; - StreamMsgReturnToPool(smsg); - smsg = smsg_next; - } -} - /** \brief Run callback for all segments * * Must be called under flow lock. diff --git a/src/stream.h b/src/stream.h index 72674f803d..d421c99a70 100644 --- a/src/stream.h +++ b/src/stream.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2010 Open Information Security Foundation +/* Copyright (C) 2007-2017 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -33,43 +33,6 @@ #define STREAM_GAP 0x10 /**< data gap encountered */ #define STREAM_DEPTH 0x20 /**< depth reached */ -typedef struct StreamMsg_ { - struct StreamMsg_ *next; - struct StreamMsg_ *prev; - - uint32_t seq; /**< sequence number */ - uint32_t data_len; /**< length of the data */ - uint32_t data_size; - uint8_t *data; /**< reassembled data: ptr to after this - * struct */ -} StreamMsg; - -typedef struct StreamMsgQueue_ { - StreamMsg *top; - StreamMsg *bot; - uint16_t len; -#ifdef DBG_PERF - uint16_t dbg_maxlen; -#endif /* DBG_PERF */ -} StreamMsgQueue; - -/* prototypes */ -void StreamMsgQueuesInit(uint32_t prealloc); -void StreamMsgQueuesDeinit(char); - -StreamMsg *StreamMsgGetFromPool(void); -void StreamMsgReturnToPool(StreamMsg *); -StreamMsg *StreamMsgGetFromQueue(StreamMsgQueue *); -void StreamMsgPutInQueue(StreamMsgQueue *, StreamMsg *); - -StreamMsgQueue *StreamMsgQueueGetNew(void); -void StreamMsgQueueFree(StreamMsgQueue *); - -void StreamMsgQueueSetMinChunkLen(uint8_t dir, uint16_t len); -uint16_t StreamMsgQueueGetMinChunkLen(uint8_t); - -void StreamMsgReturnListToPool(void *); - typedef int (*StreamSegmentCallback)(const Packet *, void *, const uint8_t *, uint32_t); int StreamSegmentForEach(const Packet *p, uint8_t flag, StreamSegmentCallback CallbackFunc, diff --git a/src/suricata.h b/src/suricata.h index c49b7f43a0..c93036a234 100644 --- a/src/suricata.h +++ b/src/suricata.h @@ -47,7 +47,6 @@ * - ::Packet: Data relative to an individual packet with information about * linked structure such as the ::Flow the ::Packet belongs to. * - ::Flow: Information about a flow for example a TCP session - * - ::StreamMsg: structure containing the reassembled data * * \subsection runmode Running mode * diff --git a/src/util-mpm-ac.c b/src/util-mpm-ac.c index 6ab2e883fb..ff2728911b 100644 --- a/src/util-mpm-ac.c +++ b/src/util-mpm-ac.c @@ -1336,7 +1336,6 @@ void CudaReleasePacket(Packet *p) * tables on priority. * - Introduce profiling. * - Retrieve sgh before buffer packet. - * - Buffer smsgs too. */ void SCACConstructBoth16and32StateTables(void)