}
}
+#define IS_DISRUPTED(flags) \
+ ((flags) & (STREAM_DEPTH|STREAM_GAP))
+
+/**
+ * \brief get the progress value for a tx/protocol
+ *
+ * If the stream is disrupted, we return the 'completion' value.
+ */
int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto,
- void *alstate, uint8_t direction)
+ void *alstate, uint8_t flags)
{
SCEnter();
int r = 0;
- r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
- StateGetProgress(alstate, direction);
+ if (unlikely(IS_DISRUPTED(flags))) {
+ r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
+ StateGetProgressCompletionStatus(flags);
+ } else {
+ r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].
+ StateGetProgress(alstate, flags);
+ }
SCReturnInt(r);
}
if ((htp_state->cfg->request_body_limit == 0 ||
htud->request_body.content_len_so_far < htp_state->cfg->request_body_limit) &&
htud->request_body.content_len_so_far < htp_state->cfg->request_inspect_min_size &&
- !(AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER) > HTP_REQUEST_BODY) &&
+ !(AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_REQUEST_BODY) &&
!(flags & STREAM_EOF)) {
SCLogDebug("we still haven't seen the entire request body. "
"Let's defer body inspection till we see the "
end:
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER) > HTP_REQUEST_BODY)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_REQUEST_BODY)
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
else
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
end:
if (flags & STREAM_TOSERVER) {
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER) > HTP_REQUEST_HEADERS)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_REQUEST_HEADERS)
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
} else {
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOCLIENT) > HTP_RESPONSE_HEADERS)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_RESPONSE_HEADERS)
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
htp_table_t *headers;
if (flags & STREAM_TOSERVER) {
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER) <= HTP_REQUEST_HEADERS)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) <= HTP_REQUEST_HEADERS)
goto end;
headers = tx->request_headers;
} else {
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOCLIENT) <= HTP_RESPONSE_HEADERS)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) <= HTP_RESPONSE_HEADERS)
goto end;
headers = tx->response_headers;
}
end:
if (flags & STREAM_TOSERVER) {
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER) > HTP_REQUEST_HEADERS)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_REQUEST_HEADERS)
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
} else {
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOCLIENT) > HTP_RESPONSE_HEADERS)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_RESPONSE_HEADERS)
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
return DETECT_ENGINE_INSPECT_SIG_MATCH;
end:
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER) > HTP_REQUEST_HEADERS)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_REQUEST_HEADERS)
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
else
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
{
htp_tx_t *tx = (htp_tx_t *)txv;
if (tx->request_method == NULL) {
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER) > HTP_REQUEST_LINE)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_REQUEST_LINE)
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
else
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
SCReturnInt(cnt);
if (flags & STREAM_TOSERVER) {
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, STREAM_TOSERVER) <= HTP_REQUEST_HEADERS)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) <= HTP_REQUEST_HEADERS)
SCReturnInt(cnt);
if (tx_ud->request_headers_raw != NULL) {
flags);
}
} else {
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, STREAM_TOCLIENT) <= HTP_RESPONSE_HEADERS)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) <= HTP_RESPONSE_HEADERS)
SCReturnInt(cnt);
if (tx_ud->response_headers_raw != NULL) {
uint32_t headers_raw_len = 0;
if (flags & STREAM_TOSERVER) {
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, STREAM_TOSERVER) <= HTP_REQUEST_HEADERS)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) <= HTP_REQUEST_HEADERS)
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
} else {
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, STREAM_TOCLIENT) <= HTP_RESPONSE_HEADERS)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) <= HTP_RESPONSE_HEADERS)
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}
end:
if (flags & STREAM_TOSERVER) {
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, STREAM_TOSERVER) > HTP_REQUEST_HEADERS)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) > HTP_REQUEST_HEADERS)
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
} else {
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, STREAM_TOCLIENT) > HTP_RESPONSE_HEADERS)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) > HTP_RESPONSE_HEADERS)
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
}
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
return DETECT_ENGINE_INSPECT_SIG_MATCH;
end:
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER) > HTP_REQUEST_HEADERS)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_REQUEST_HEADERS)
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
else
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
htp_tx_t *tx = (htp_tx_t *)txv;
if (tx->request_line == NULL) {
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, STREAM_TOSERVER) > HTP_REQUEST_LINE)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) > HTP_REQUEST_LINE)
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
else
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
{
htp_tx_t *tx = (htp_tx_t *)txv;
if (tx->request_uri == NULL) {
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER) > HTP_REQUEST_LINE)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_REQUEST_LINE)
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
else
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
htud->response_body.content_len_so_far,
htp_state->cfg->response_inspect_min_size,
flags & STREAM_EOF ? "true" : "false",
- (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOCLIENT) > HTP_RESPONSE_BODY) ? "true" : "false");
+ (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_RESPONSE_BODY) ? "true" : "false");
if (!htp_state->cfg->http_body_inline) {
/* inspect the body if the transfer is complete or we have hit
if ((htp_state->cfg->response_body_limit == 0 ||
htud->response_body.content_len_so_far < htp_state->cfg->response_body_limit) &&
htud->response_body.content_len_so_far < htp_state->cfg->response_inspect_min_size &&
- !(AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOCLIENT) > HTP_RESPONSE_BODY) &&
+ !(AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_RESPONSE_BODY) &&
!(flags & STREAM_EOF)) {
SCLogDebug("we still haven't seen the entire response body. "
"Let's defer body inspection till we see the "
return DETECT_ENGINE_INSPECT_SIG_MATCH;
end:
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOCLIENT) > HTP_RESPONSE_BODY)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_RESPONSE_BODY)
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
else
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
{
htp_tx_t *tx = (htp_tx_t *)txv;
if (tx->response_status == NULL) {
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOCLIENT) > HTP_RESPONSE_LINE)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_RESPONSE_LINE)
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
else
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
{
htp_tx_t *tx = (htp_tx_t *)txv;
if (tx->response_message == NULL) {
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOCLIENT) > HTP_RESPONSE_LINE)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_RESPONSE_LINE)
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
else
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
return DETECT_ENGINE_INSPECT_SIG_MATCH;
end:
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER) > HTP_REQUEST_HEADERS)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_REQUEST_HEADERS)
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
else
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
HtpTxUserData *tx_ud = htp_tx_get_user_data(txv);
if (tx_ud == NULL || tx_ud->request_uri_normalized == NULL) {
- if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, STREAM_TOSERVER) > HTP_REQUEST_LINE)
+ if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) > HTP_REQUEST_LINE)
return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
else
return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
(p->proto == IPPROTO_UDP) ||
(p->proto == IPPROTO_SCTP && (p->flowflags & FLOW_PKT_ESTABLISHED)))
{
+ /* update flow flags with knowledge on disruptions */
+ flow_flags = FlowGetDisruptionFlags(pflow, flow_flags);
has_state = (FlowGetAppState(pflow) != NULL);
alproto = FlowGetAppProtocol(pflow);
alversion = AppLayerParserGetStateVersion(pflow->alparser);
return f->alstate;
}
+/**
+ * \brief get 'disruption' flags: GAP/DEPTH/PASS
+ * \param f locked flow
+ * \param flags existing flags to be ammended
+ * \retval flags original flags + disrupt flags (if any)
+ * \TODO handle UDP
+ */
+uint8_t FlowGetDisruptionFlags(const Flow *f, uint8_t flags)
+{
+ if (f->proto != IPPROTO_TCP) {
+ return flags;
+ }
+ if (f->protoctx == NULL) {
+ return flags;
+ }
+
+ uint8_t newflags = flags;
+ TcpSession *ssn = f->protoctx;
+ TcpStream *stream = flags & STREAM_TOSERVER ? &ssn->client : &ssn->server;
+
+ if (stream->flags & STREAMTCP_STREAM_FLAG_DEPTH_REACHED) {
+ newflags |= STREAM_DEPTH;
+ }
+ if (stream->flags & STREAMTCP_STREAM_FLAG_GAP) {
+ newflags |= STREAM_GAP;
+ }
+ /* todo: handle pass case (also for UDP!) */
+
+ return newflags;
+}
+
/************************************Unittests*******************************/
#ifdef UNITTESTS
AppProto FlowGetAppProtocol(const Flow *f);
void *FlowGetAppState(const Flow *f);
+uint8_t FlowGetDisruptionFlags(const Flow *f, uint8_t flags);
void FlowHandlePacketUpdateRemove(Flow *f, Packet *p);
void FlowHandlePacketUpdate(Flow *f, Packet *p);