app-layer: de_state optimization

Add API to bypass expensive TX list walks. This API call is optional.

Implement it for HTTP and DNS.
pull/1479/head
Victor Julien 10 years ago
parent 5f0678120d
commit f536099a67

@ -293,8 +293,11 @@ static void DNSTransactionFree(DNSTransaction *tx, DNSState *state)
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;
@ -366,15 +369,23 @@ DNSTransaction *DNSTransactionFindByTxId(const DNSState *dns_state, const uint16
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;
}
@ -413,6 +424,8 @@ void DNSStateFree(void *s)
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);

@ -181,6 +181,8 @@ typedef struct DNSState_ {
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;
@ -221,8 +223,9 @@ int DNSGetAlstateProgressCompletionStatus(uint8_t direction);
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);

@ -647,6 +647,7 @@ void RegisterDNSTCPParsers(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);

@ -403,6 +403,7 @@ void RegisterDNSUDPParsers(void)
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,

@ -310,9 +310,9 @@ error:
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);
@ -324,6 +324,11 @@ static void HtpTxUserDataFree(HtpTxUserData *htud)
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));
@ -357,15 +362,14 @@ void HTPStateFree(void *state)
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);
@ -400,10 +404,8 @@ static void HTPStateTransactionFree(void *state, uint64_t id)
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);
}
@ -2109,10 +2111,9 @@ static int HTPCallbackRequestHeaderData(htp_tx_data_t *tx_data)
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;
}
@ -2147,10 +2148,9 @@ static int HTPCallbackResponseHeaderData(htp_tx_data_t *tx_data)
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;
}
@ -2635,6 +2635,12 @@ static void HTPStateTruncate(void *state, uint8_t direction)
}
}
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;
@ -2642,8 +2648,9 @@ static DetectEngineState *HTPGetTxDetectState(void *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) {
@ -2653,6 +2660,7 @@ static int HTPSetTxDetectState(void *vtx, DetectEngineState *s)
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;
}
@ -2741,6 +2749,7 @@ void RegisterHTPParsers(void)
AppLayerParserRegisterTruncateFunc(IPPROTO_TCP, ALPROTO_HTTP, HTPStateTruncate);
AppLayerParserRegisterDetectStateFuncs(IPPROTO_TCP, ALPROTO_HTTP,
HTPStateHasTxDetectState,
HTPGetTxDetectState, HTPSetTxDetectState);
AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_HTTP, STREAM_TOSERVER,

@ -248,6 +248,7 @@ typedef struct HtpState_ {
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) */

@ -1343,7 +1343,7 @@ DetectEngineState *ModbusGetTxDetectState(void *vtx)
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;
@ -1410,7 +1410,7 @@ void RegisterModbusParsers(void)
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);

@ -106,8 +106,9 @@ typedef struct AppLayerParserProtoCtx_
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 -
@ -472,11 +473,13 @@ void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto,
}
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;
@ -804,6 +807,16 @@ int AppLayerParserSupportsTxDetectState(uint8_t ipproto, AppProto alproto)
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();
@ -812,13 +825,14 @@ DetectEngineState *AppLayerParserGetTxDetectState(uint8_t ipproto, AppProto alpr
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);
}

@ -143,8 +143,9 @@ void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto,
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 *****/
@ -180,8 +181,9 @@ uint64_t AppLayerParserGetTransactionActive(uint8_t ipproto, AppProto alproto, A
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 *****/

@ -1381,7 +1381,7 @@ static DetectEngineState *SMTPGetTxDetectState(void *vtx)
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;
@ -1415,7 +1415,7 @@ void RegisterSMTPParsers(void)
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,

@ -335,6 +335,14 @@ static int HasStoredSigs(Flow *f, uint8_t flags)
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);
@ -423,7 +431,7 @@ static void StoreStateTxFileOnly(DetectEngineThreadCtx *det_ctx,
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;
@ -449,7 +457,7 @@ static void StoreStateTx(DetectEngineThreadCtx *det_ctx,
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;

Loading…
Cancel
Save