Add API to bypass expensive TX list walks. This API call is optional.
Implement it for HTTP and DNS.
AppLayerDecoderEventsFreeEvents(&tx->decoder_events);
- if (tx->de_state != NULL)
+ if (tx->de_state != NULL) {
DetectEngineStateFree(tx->de_state);
+ BUG_ON(state->tx_with_detect_state_cnt == 0);
+ state->tx_with_detect_state_cnt--;
+ }
if (state->iter == tx)
state->iter = NULL;
return NULL;
}
+int DNSStateHasTxDetectState(void *alstate)
+{
+ DNSState *state = (DNSState *)alstate;
+ return (state->tx_with_detect_state_cnt > 0);
+}
+
DetectEngineState *DNSGetTxDetectState(void *vtx)
{
DNSTransaction *tx = (DNSTransaction *)vtx;
return tx->de_state;
}
-int DNSSetTxDetectState(void *vtx, DetectEngineState *s)
+int DNSSetTxDetectState(void *alstate, void *vtx, DetectEngineState *s)
{
+ DNSState *state = (DNSState *)alstate;
DNSTransaction *tx = (DNSTransaction *)vtx;
+ state->tx_with_detect_state_cnt++;
tx->de_state = s;
return 0;
}
SCFree(dns_state->buffer);
}
+ BUG_ON(dns_state->tx_with_detect_state_cnt > 0);
+
DNSDecrMemcap(sizeof(DNSState), dns_state);
BUG_ON(dns_state->memuse > 0);
SCFree(s);
uint32_t unreplied_cnt; /**< number of unreplied requests in a row */
uint32_t memuse; /**< state memuse, for comparing with
state-memcap settings */
+ uint64_t tx_with_detect_state_cnt;
+
uint16_t events;
uint16_t givenup;
void DNSStateTransactionFree(void *state, uint64_t tx_id);
DNSTransaction *DNSTransactionFindByTxId(const DNSState *dns_state, const uint16_t tx_id);
+int DNSStateHasTxDetectState(void *alstate);
DetectEngineState *DNSGetTxDetectState(void *vtx);
-int DNSSetTxDetectState(void *vtx, DetectEngineState *s);
+int DNSSetTxDetectState(void *alstate, void *vtx, DetectEngineState *s);
void DNSSetEvent(DNSState *s, uint8_t e);
void *DNSStateAlloc(void);
AppLayerParserRegisterGetEventsFunc(IPPROTO_TCP, ALPROTO_DNS, DNSGetEvents);
AppLayerParserRegisterHasEventsFunc(IPPROTO_TCP, ALPROTO_DNS, DNSHasEvents);
AppLayerParserRegisterDetectStateFuncs(IPPROTO_TCP, ALPROTO_DNS,
+ DNSStateHasTxDetectState,
DNSGetTxDetectState, DNSSetTxDetectState);
AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_DNS, DNSGetTx);
AppLayerParserRegisterGetEventsFunc(IPPROTO_UDP, ALPROTO_DNS, DNSGetEvents);
AppLayerParserRegisterHasEventsFunc(IPPROTO_UDP, ALPROTO_DNS, DNSHasEvents);
AppLayerParserRegisterDetectStateFuncs(IPPROTO_UDP, ALPROTO_DNS,
+ DNSStateHasTxDetectState,
DNSGetTxDetectState, DNSSetTxDetectState);
AppLayerParserRegisterGetTx(IPPROTO_UDP, ALPROTO_DNS,
SCReturnPtr(NULL, "void");
}
-static void HtpTxUserDataFree(HtpTxUserData *htud)
+static void HtpTxUserDataFree(HtpState *state, HtpTxUserData *htud)
{
- if (htud) {
+ if (likely(htud)) {
HtpBodyFree(&htud->request_body);
HtpBodyFree(&htud->response_body);
bstr_free(htud->request_uri_normalized);
if (htud->boundary)
HTPFree(htud->boundary, htud->boundary_len);
if (htud->de_state != NULL) {
+ if (likely(state != NULL)) { // should be impossible that it's null
+ BUG_ON(state->tx_with_detect_state_cnt == 0);
+ state->tx_with_detect_state_cnt--;
+ }
+
DetectEngineStateFree(htud->de_state);
}
HTPFree(htud, sizeof(HtpTxUserData));
htp_tx_t *tx = HTPStateGetTx(s, tx_id);
if (tx != NULL) {
HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
- if (htud != NULL) {
- HtpTxUserDataFree(htud);
- htp_tx_set_user_data(tx, NULL);
- }
+ HtpTxUserDataFree(s, htud);
+ htp_tx_set_user_data(tx, NULL);
}
}
}
htp_connp_destroy_all(s->connp);
}
+ BUG_ON(s->tx_with_detect_state_cnt > 0);
FileContainerFree(s->files_ts);
FileContainerFree(s->files_tc);
if (tx != NULL) {
/* This will remove obsolete body chunks */
HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
- if (htud != NULL) {
- HtpTxUserDataFree(htud);
- htp_tx_set_user_data(tx, NULL);
- }
+ HtpTxUserDataFree(s, htud);
+ htp_tx_set_user_data(tx, NULL);
htp_tx_destroy(tx);
}
tx_ud->request_headers_raw_len,
tx_ud->request_headers_raw_len + tx_data->len);
if (ptmp == NULL) {
- HTPFree(tx_ud->request_headers_raw, tx_ud->request_headers_raw_len);
- tx_ud->request_headers_raw = NULL;
- tx_ud->request_headers_raw_len = 0;
- HtpTxUserDataFree(tx_ud);
+ /* error: we're freeing the entire user data */
+ HtpState *hstate = htp_connp_get_user_data(tx_data->tx->connp);
+ HtpTxUserDataFree(hstate, tx_ud);
htp_tx_set_user_data(tx_data->tx, NULL);
return HTP_OK;
}
tx_ud->response_headers_raw_len,
tx_ud->response_headers_raw_len + tx_data->len);
if (ptmp == NULL) {
- HTPFree(tx_ud->response_headers_raw, tx_ud->response_headers_raw_len);
- tx_ud->response_headers_raw = NULL;
- tx_ud->response_headers_raw_len = 0;
- HtpTxUserDataFree(tx_ud);
+ /* error: we're freeing the entire user data */
+ HtpState *hstate = htp_connp_get_user_data(tx_data->tx->connp);
+ HtpTxUserDataFree(hstate, tx_ud);
htp_tx_set_user_data(tx_data->tx, NULL);
return HTP_OK;
}
}
}
+static int HTPStateHasTxDetectState(void *alstate)
+{
+ HtpState *htp_state = (HtpState *)alstate;
+ return (htp_state->tx_with_detect_state_cnt > 0);
+}
+
static DetectEngineState *HTPGetTxDetectState(void *vtx)
{
htp_tx_t *tx = (htp_tx_t *)vtx;
return tx_ud ? tx_ud->de_state : NULL;
}
-static int HTPSetTxDetectState(void *vtx, DetectEngineState *s)
+static int HTPSetTxDetectState(void *alstate, void *vtx, DetectEngineState *s)
{
+ HtpState *htp_state = (HtpState *)alstate;
htp_tx_t *tx = (htp_tx_t *)vtx;
HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
if (tx_ud == NULL) {
memset(tx_ud, 0, sizeof(*tx_ud));
htp_tx_set_user_data(tx, tx_ud);
}
+ htp_state->tx_with_detect_state_cnt++;
tx_ud->de_state = s;
return 0;
}
AppLayerParserRegisterTruncateFunc(IPPROTO_TCP, ALPROTO_HTTP, HTPStateTruncate);
AppLayerParserRegisterDetectStateFuncs(IPPROTO_TCP, ALPROTO_HTTP,
+ HTPStateHasTxDetectState,
HTPGetTxDetectState, HTPSetTxDetectState);
AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_HTTP, STREAM_TOSERVER,
uint16_t flags;
uint16_t events;
uint16_t htp_messages_offset; /**< offset into conn->messages list */
+ uint64_t tx_with_detect_state_cnt;
} HtpState;
/** part of the engine needs the request body (e.g. http_client_body keyword) */
return tx->de_state;
}
-int ModbusSetTxDetectState(void *vtx, DetectEngineState *s)
+int ModbusSetTxDetectState(void *state, void *vtx, DetectEngineState *s)
{
ModbusTransaction *tx = (ModbusTransaction *)vtx;
tx->de_state = s;
AppLayerParserRegisterGetEventsFunc(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetEvents);
AppLayerParserRegisterHasEventsFunc(IPPROTO_TCP, ALPROTO_MODBUS, ModbusHasEvents);
- AppLayerParserRegisterDetectStateFuncs(IPPROTO_TCP, ALPROTO_MODBUS,
+ AppLayerParserRegisterDetectStateFuncs(IPPROTO_TCP, ALPROTO_MODBUS, NULL,
ModbusGetTxDetectState, ModbusSetTxDetectState);
AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_MODBUS, ModbusGetTx);
int (*StateGetEventInfo)(const char *event_name,
int *event_id, AppLayerEventType *event_type);
+ int (*StateHasTxDetectState)(void *alstate);
DetectEngineState *(*GetTxDetectState)(void *tx);
- int (*SetTxDetectState)(void *tx, DetectEngineState *);
+ int (*SetTxDetectState)(void *alstate, void *tx, DetectEngineState *);
/* Indicates the direction the parser is ready to see the data
* the first time for a flow. Values accepted -
}
void AppLayerParserRegisterDetectStateFuncs(uint8_t ipproto, AppProto alproto,
+ int (*StateHasTxDetectState)(void *alstate),
DetectEngineState *(*GetTxDetectState)(void *tx),
- int (*SetTxDetectState)(void *tx, DetectEngineState *))
+ int (*SetTxDetectState)(void *alstate, void *tx, DetectEngineState *))
{
SCEnter();
+ alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateHasTxDetectState = StateHasTxDetectState;
alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxDetectState = GetTxDetectState;
alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].SetTxDetectState = SetTxDetectState;
return FALSE;
}
+int AppLayerParserHasTxDetectState(uint8_t ipproto, AppProto alproto, void *alstate)
+{
+ int r;
+ SCEnter();
+ if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateHasTxDetectState == NULL)
+ return -ENOSYS;
+ r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateHasTxDetectState(alstate);
+ SCReturnInt(r);
+}
+
DetectEngineState *AppLayerParserGetTxDetectState(uint8_t ipproto, AppProto alproto, void *tx)
{
SCEnter();
SCReturnPtr(s, "DetectEngineState");
}
-int AppLayerParserSetTxDetectState(uint8_t ipproto, AppProto alproto, void *tx, DetectEngineState *s)
+int AppLayerParserSetTxDetectState(uint8_t ipproto, AppProto alproto,
+ void *alstate, void *tx, DetectEngineState *s)
{
int r;
SCEnter();
if ((alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxDetectState(tx) != NULL))
SCReturnInt(-EBUSY);
- r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].SetTxDetectState(tx, s);
+ r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].SetTxDetectState(alstate, tx, s);
SCReturnInt(r);
}
int (*StateGetEventInfo)(const char *event_name, int *event_id,
AppLayerEventType *event_type));
void AppLayerParserRegisterDetectStateFuncs(uint8_t ipproto, AppProto alproto,
+ int (*StateHasTxDetectState)(void *alstate),
DetectEngineState *(*GetTxDetectState)(void *tx),
- int (*SetTxDetectState)(void *tx, DetectEngineState *));
+ int (*SetTxDetectState)(void *alstate, void *tx, DetectEngineState *));
/***** Get and transaction functions *****/
uint8_t AppLayerParserGetFirstDataDir(uint8_t ipproto, AppProto alproto);
int AppLayerParserSupportsTxDetectState(uint8_t ipproto, AppProto alproto);
+int AppLayerParserHasTxDetectState(uint8_t ipproto, AppProto alproto, void *alstate);
DetectEngineState *AppLayerParserGetTxDetectState(uint8_t ipproto, AppProto alproto, void *tx);
-int AppLayerParserSetTxDetectState(uint8_t ipproto, AppProto alproto, void *tx, DetectEngineState *s);
+int AppLayerParserSetTxDetectState(uint8_t ipproto, AppProto alproto, void *alstate, void *tx, DetectEngineState *s);
/***** General *****/
return tx->de_state;
}
-static int SMTPSetTxDetectState(void *vtx, DetectEngineState *s)
+static int SMTPSetTxDetectState(void *state, void *vtx, DetectEngineState *s)
{
SMTPTransaction *tx = (SMTPTransaction *)vtx;
tx->de_state = s;
AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateGetEventInfo);
AppLayerParserRegisterGetEventsFunc(IPPROTO_TCP, ALPROTO_SMTP, SMTPGetEvents);
- AppLayerParserRegisterDetectStateFuncs(IPPROTO_TCP, ALPROTO_SMTP,
+ AppLayerParserRegisterDetectStateFuncs(IPPROTO_TCP, ALPROTO_SMTP, NULL,
SMTPGetTxDetectState, SMTPSetTxDetectState);
AppLayerParserRegisterLocalStorageFunc(IPPROTO_TCP, ALPROTO_SMTP, SMTPLocalStorageAlloc,
return 0;
}
+ int state = AppLayerParserHasTxDetectState(f->proto, alproto, f->alstate);
+ if (state == -ENOSYS) { /* proto doesn't support this API call */
+ /* fall through */
+ } else if (state == 0) {
+ return 0;
+ }
+ /* if state == 1 we also fall through */
+
uint64_t inspect_tx_id = AppLayerParserGetTransactionInspectId(f->alparser, flags);
uint64_t total_txs = AppLayerParserGetTxCnt(f->proto, alproto, alstate);
destate = DetectEngineStateAlloc();
if (destate == NULL)
return;
- if (AppLayerParserSetTxDetectState(f->proto, f->alproto, tx, destate) < 0) {
+ if (AppLayerParserSetTxDetectState(f->proto, f->alproto, f->alstate, tx, destate) < 0) {
DetectEngineStateFree(destate);
BUG_ON(1);
return;
destate = DetectEngineStateAlloc();
if (destate == NULL)
return;
- if (AppLayerParserSetTxDetectState(f->proto, f->alproto, tx, destate) < 0) {
+ if (AppLayerParserSetTxDetectState(f->proto, f->alproto, f->alstate, tx, destate) < 0) {
DetectEngineStateFree(destate);
BUG_ON(1);
return;