You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
suricata/src/detect-engine.c

3054 lines
99 KiB
C

/* Copyright (C) 2007-2010 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
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* \file
*
* \author Victor Julien <victor@inliniac.net>
*/
#include "suricata-common.h"
#include "suricata.h"
#include "debug.h"
#include "detect.h"
#include "flow.h"
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
#include "flow-private.h"
#include "flow-util.h"
#include "conf.h"
#include "conf-yaml-loader.h"
#include "app-layer-htp.h"
#include "detect-parse.h"
#include "detect-engine-sigorder.h"
#include "detect-engine-siggroup.h"
#include "detect-engine-address.h"
#include "detect-engine-port.h"
16 years ago
#include "detect-engine-mpm.h"
#include "detect-engine-hcbd.h"
16 years ago
#include "detect-engine-iponly.h"
#include "detect-engine-tag.h"
#include "detect-engine-uri.h"
#include "detect-engine-hcbd.h"
#include "detect-engine-hsbd.h"
#include "detect-engine-hhd.h"
#include "detect-engine-hrhd.h"
#include "detect-engine-hmd.h"
#include "detect-engine-hcd.h"
#include "detect-engine-hrud.h"
#include "detect-engine-hrl.h"
#include "detect-engine-hsmd.h"
#include "detect-engine-hscd.h"
#include "detect-engine-hua.h"
#include "detect-engine-hhhd.h"
#include "detect-engine-hrhhd.h"
#include "detect-engine-file.h"
#include "detect-engine-dns.h"
#include "detect-engine-modbus.h"
#include "detect-engine-filedata-smtp.h"
#include "detect-engine.h"
#include "detect-engine-state.h"
#include "detect-byte-extract.h"
16 years ago
#include "detect-content.h"
#include "detect-uricontent.h"
16 years ago
#include "detect-engine-threshold.h"
16 years ago
#include "util-classification-config.h"
#include "util-reference-config.h"
#include "util-threshold-config.h"
#include "util-error.h"
#include "util-hash.h"
#include "util-byte.h"
#include "util-debug.h"
#include "util-unittest.h"
#include "util-action.h"
#include "util-magic.h"
#include "util-signal.h"
#include "util-var-name.h"
Add per packet profiling. Per packet profiling uses tick based accounting. It has 2 outputs, a summary and a csv file that contains per packet stats. Stats per packet include: 1) total ticks spent 2) ticks spent per individual thread module 3) "threading overhead" which is simply calculated by subtracting (2) of (1). A number of changes were made to integrate the new code in a clean way: a number of generic enums are now placed in tm-threads-common.h so we can include them from any part of the engine. Code depends on --enable-profiling just like the rule profiling code. New yaml parameters: profiling: # packet profiling packets: # Profiling can be disabled here, but it will still have a # performance impact if compiled in. enabled: yes filename: packet_stats.log append: yes # per packet csv output csv: # Output can be disabled here, but it will still have a # performance impact if compiled in. enabled: no filename: packet_stats.csv Example output of summary stats: IP ver Proto cnt min max avg ------ ----- ------ ------ ---------- ------- IPv4 6 19436 11448 5404365 32993 IPv4 256 4 11511 49968 30575 Per Thread module stats: Thread Module IP ver Proto cnt min max avg ------------------------ ------ ----- ------ ------ ---------- ------- TMM_DECODEPCAPFILE IPv4 6 19434 1242 47889 1770 TMM_DETECT IPv4 6 19436 1107 137241 1504 TMM_ALERTFASTLOG IPv4 6 19436 90 1323 155 TMM_ALERTUNIFIED2ALERT IPv4 6 19436 108 1359 138 TMM_ALERTDEBUGLOG IPv4 6 19436 90 1134 154 TMM_LOGHTTPLOG IPv4 6 19436 414 5392089 7944 TMM_STREAMTCP IPv4 6 19434 828 1299159 19438 The proto 256 is a counter for handling of pseudo/tunnel packets. Example output of csv: pcap_cnt,ipver,ipproto,total,TMM_DECODENFQ,TMM_VERDICTNFQ,TMM_RECEIVENFQ,TMM_RECEIVEPCAP,TMM_RECEIVEPCAPFILE,TMM_DECODEPCAP,TMM_DECODEPCAPFILE,TMM_RECEIVEPFRING,TMM_DECODEPFRING,TMM_DETECT,TMM_ALERTFASTLOG,TMM_ALERTFASTLOG4,TMM_ALERTFASTLOG6,TMM_ALERTUNIFIEDLOG,TMM_ALERTUNIFIEDALERT,TMM_ALERTUNIFIED2ALERT,TMM_ALERTPRELUDE,TMM_ALERTDEBUGLOG,TMM_ALERTSYSLOG,TMM_LOGDROPLOG,TMM_ALERTSYSLOG4,TMM_ALERTSYSLOG6,TMM_RESPONDREJECT,TMM_LOGHTTPLOG,TMM_LOGHTTPLOG4,TMM_LOGHTTPLOG6,TMM_PCAPLOG,TMM_STREAMTCP,TMM_DECODEIPFW,TMM_VERDICTIPFW,TMM_RECEIVEIPFW,TMM_RECEIVEERFFILE,TMM_DECODEERFFILE,TMM_RECEIVEERFDAG,TMM_DECODEERFDAG,threading 1,4,6,172008,0,0,0,0,0,0,47889,0,0,48582,1323,0,0,0,0,1359,0,1134,0,0,0,0,0,8028,0,0,0,49356,0,0,0,0,0,0,0,14337 First line of the file contains labels. 2 example gnuplot scripts added to plot the data.
14 years ago
#include "tm-threads.h"
#include "runmodes.h"
#ifdef PROFILING
#include "util-profiling.h"
#endif
#include "reputation.h"
#define DETECT_ENGINE_DEFAULT_INSPECTION_RECURSION_LIMIT 3000
static uint32_t detect_engine_ctx_id = 1;
static DetectEngineThreadCtx *DetectEngineThreadCtxInitForReload(
ThreadVars *tv, DetectEngineCtx *new_de_ctx);
static uint8_t DetectEngineCtxLoadConf(DetectEngineCtx *);
static DetectEngineMasterCtx g_master_de_ctx = { SCMUTEX_INITIALIZER, 0, NULL, NULL, TENANT_SELECTOR_UNKNOWN, NULL,};
static DetectEngineThreadCtx *DetectEngineThreadCtxInitForMT(ThreadVars *tv);
/* 2 - for each direction */
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
DetectEngineAppInspectionEngine *app_inspection_engine[FLOW_PROTO_DEFAULT][ALPROTO_MAX][2];
#if 0
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
static void DetectEnginePrintAppInspectionEngines(DetectEngineAppInspectionEngine *list[][ALPROTO_MAX][2])
{
printf("\n");
AppProto alproto = ALPROTO_UNKNOWN + 1;
for ( ; alproto < ALPROTO_MAX; alproto++) {
printf("alproto - %d\n", alproto);
int dir = 0;
for ( ; dir < 2; dir++) {
printf(" direction - %d\n", dir);
DetectEngineAppInspectionEngine *engine = list[alproto][dir];
while (engine != NULL) {
printf(" engine->alproto - %"PRIu16"\n", engine->alproto);
printf(" engine->dir - %"PRIu16"\n", engine->dir);
printf(" engine->sm_list - %d\n", engine->sm_list);
printf(" engine->inspect_flags - %"PRIu32"\n", engine->inspect_flags);
printf(" engine->match_flags - %"PRIu32"\n", engine->match_flags);
printf("\n");
engine = engine->next;
}
} /* for ( ; dir < 2; dir++) */
} /* for ( ; alproto < ALPROTO_MAX; alproto++) */
return;
}
#endif
void DetectEngineRegisterAppInspectionEngines(void)
{
struct tmp_t {
uint8_t ipproto;
AppProto alproto;
int32_t sm_list;
uint32_t inspect_flags;
uint16_t dir;
int (*Callback)(ThreadVars *tv,
DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx,
Signature *sig, Flow *f,
uint8_t flags, void *alstate,
void *tx, uint64_t tx_id);
};
struct tmp_t data_toserver[] = {
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
{ IPPROTO_TCP,
ALPROTO_HTTP,
DETECT_SM_LIST_UMATCH,
DE_STATE_FLAG_URI_INSPECT,
0,
DetectEngineInspectPacketUris },
{ IPPROTO_TCP,
ALPROTO_HTTP,
DETECT_SM_LIST_HRLMATCH,
DE_STATE_FLAG_HRL_INSPECT,
0,
DetectEngineInspectHttpRequestLine },
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
{ IPPROTO_TCP,
ALPROTO_HTTP,
DETECT_SM_LIST_HCBDMATCH,
DE_STATE_FLAG_HCBD_INSPECT,
0,
DetectEngineInspectHttpClientBody },
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
{ IPPROTO_TCP,
ALPROTO_HTTP,
DETECT_SM_LIST_HHDMATCH,
DE_STATE_FLAG_HHD_INSPECT,
0,
DetectEngineInspectHttpHeader },
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
{ IPPROTO_TCP,
ALPROTO_HTTP,
DETECT_SM_LIST_HRHDMATCH,
DE_STATE_FLAG_HRHD_INSPECT,
0,
DetectEngineInspectHttpRawHeader },
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
{ IPPROTO_TCP,
ALPROTO_HTTP,
DETECT_SM_LIST_HMDMATCH,
DE_STATE_FLAG_HMD_INSPECT,
0,
DetectEngineInspectHttpMethod },
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
{ IPPROTO_TCP,
ALPROTO_HTTP,
DETECT_SM_LIST_HCDMATCH,
DE_STATE_FLAG_HCD_INSPECT,
0,
DetectEngineInspectHttpCookie },
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
{ IPPROTO_TCP,
ALPROTO_HTTP,
DETECT_SM_LIST_HRUDMATCH,
DE_STATE_FLAG_HRUD_INSPECT,
0,
DetectEngineInspectHttpRawUri },
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
{ IPPROTO_TCP,
ALPROTO_HTTP,
DETECT_SM_LIST_FILEMATCH,
DE_STATE_FLAG_FILE_TS_INSPECT,
0,
DetectFileInspectHttp },
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
{ IPPROTO_TCP,
ALPROTO_HTTP,
DETECT_SM_LIST_HUADMATCH,
DE_STATE_FLAG_HUAD_INSPECT,
0,
DetectEngineInspectHttpUA },
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
{ IPPROTO_TCP,
ALPROTO_HTTP,
DETECT_SM_LIST_HHHDMATCH,
DE_STATE_FLAG_HHHD_INSPECT,
0,
DetectEngineInspectHttpHH },
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
{ IPPROTO_TCP,
ALPROTO_HTTP,
DETECT_SM_LIST_HRHHDMATCH,
DE_STATE_FLAG_HRHHD_INSPECT,
0,
DetectEngineInspectHttpHRH },
/* DNS */
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
{ IPPROTO_TCP,
ALPROTO_DNS,
DETECT_SM_LIST_DNSQUERYNAME_MATCH,
DE_STATE_FLAG_DNSQUERYNAME_INSPECT,
0,
DetectEngineInspectDnsQueryName },
/* specifically for UDP, register again
* allows us to use the alproto w/o translation
* in the detection engine */
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
{ IPPROTO_UDP,
ALPROTO_DNS,
DETECT_SM_LIST_DNSQUERYNAME_MATCH,
DE_STATE_FLAG_DNSQUERYNAME_INSPECT,
0,
DetectEngineInspectDnsQueryName },
{ IPPROTO_TCP,
ALPROTO_DNS,
DETECT_SM_LIST_DNSREQUEST_MATCH,
DE_STATE_FLAG_DNSREQUEST_INSPECT,
0,
DetectEngineInspectDnsRequest },
/* specifically for UDP, register again
* allows us to use the alproto w/o translation
* in the detection engine */
{ IPPROTO_UDP,
ALPROTO_DNS,
DETECT_SM_LIST_DNSREQUEST_MATCH,
DE_STATE_FLAG_DNSREQUEST_INSPECT,
0,
DetectEngineInspectDnsRequest },
/* SMTP */
{ IPPROTO_TCP,
ALPROTO_SMTP,
DETECT_SM_LIST_FILEMATCH,
DE_STATE_FLAG_FILE_TS_INSPECT,
0,
DetectFileInspectSmtp },
/* Modbus */
{ IPPROTO_TCP,
ALPROTO_MODBUS,
DETECT_SM_LIST_MODBUS_MATCH,
DE_STATE_FLAG_MODBUS_INSPECT,
0,
DetectEngineInspectModbus },
/* file_data smtp */
{ IPPROTO_TCP,
ALPROTO_SMTP,
DETECT_SM_LIST_FILEDATA,
DE_STATE_FLAG_FD_SMTP_INSPECT,
0,
DetectEngineInspectSMTPFiledata },
};
struct tmp_t data_toclient[] = {
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
{ IPPROTO_TCP,
ALPROTO_HTTP,
DETECT_SM_LIST_FILEDATA,
DE_STATE_FLAG_HSBD_INSPECT,
1,
DetectEngineInspectHttpServerBody },
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
{ IPPROTO_TCP,
ALPROTO_HTTP,
DETECT_SM_LIST_HHDMATCH,
DE_STATE_FLAG_HHD_INSPECT,
1,
DetectEngineInspectHttpHeader },
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
{ IPPROTO_TCP,
ALPROTO_HTTP,
DETECT_SM_LIST_HRHDMATCH,
DE_STATE_FLAG_HRHD_INSPECT,
1,
DetectEngineInspectHttpRawHeader },
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
{ IPPROTO_TCP,
ALPROTO_HTTP,
DETECT_SM_LIST_HCDMATCH,
DE_STATE_FLAG_HCD_INSPECT,
1,
DetectEngineInspectHttpCookie },
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
{ IPPROTO_TCP,
ALPROTO_HTTP,
DETECT_SM_LIST_FILEMATCH,
DE_STATE_FLAG_FILE_TC_INSPECT,
1,
DetectFileInspectHttp },
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
{ IPPROTO_TCP,
ALPROTO_HTTP,
DETECT_SM_LIST_HSMDMATCH,
DE_STATE_FLAG_HSMD_INSPECT,
1,
DetectEngineInspectHttpStatMsg },
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
{ IPPROTO_TCP,
ALPROTO_HTTP,
DETECT_SM_LIST_HSCDMATCH,
DE_STATE_FLAG_HSCD_INSPECT,
1,
DetectEngineInspectHttpStatCode },
/* Modbus */
{ IPPROTO_TCP,
ALPROTO_MODBUS,
DETECT_SM_LIST_MODBUS_MATCH,
DE_STATE_FLAG_MODBUS_INSPECT,
0,
DetectEngineInspectModbus },
{ IPPROTO_TCP,
ALPROTO_DNS,
DETECT_SM_LIST_DNSRESPONSE_MATCH,
DE_STATE_FLAG_DNSRESPONSE_INSPECT,
1,
DetectEngineInspectDnsResponse },
/* specifically for UDP, register again
* allows us to use the alproto w/o translation
* in the detection engine */
{ IPPROTO_UDP,
ALPROTO_DNS,
DETECT_SM_LIST_DNSRESPONSE_MATCH,
DE_STATE_FLAG_DNSRESPONSE_INSPECT,
1,
DetectEngineInspectDnsResponse },
};
size_t i;
for (i = 0 ; i < sizeof(data_toserver) / sizeof(struct tmp_t); i++) {
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
DetectEngineRegisterAppInspectionEngine(data_toserver[i].ipproto,
data_toserver[i].alproto,
data_toserver[i].dir,
data_toserver[i].sm_list,
data_toserver[i].inspect_flags,
data_toserver[i].Callback,
app_inspection_engine);
}
for (i = 0 ; i < sizeof(data_toclient) / sizeof(struct tmp_t); i++) {
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
DetectEngineRegisterAppInspectionEngine(data_toclient[i].ipproto,
data_toclient[i].alproto,
data_toclient[i].dir,
data_toclient[i].sm_list,
data_toclient[i].inspect_flags,
data_toclient[i].Callback,
app_inspection_engine);
}
#if 0
DetectEnginePrintAppInspectionEngines(app_inspection_engine);
#endif
return;
}
static void AppendAppInspectionEngine(DetectEngineAppInspectionEngine *engine,
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
DetectEngineAppInspectionEngine *list[][ALPROTO_MAX][2])
{
/* append to the list */
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
DetectEngineAppInspectionEngine *tmp = list[FlowGetProtoMapping(engine->ipproto)][engine->alproto][engine->dir];
DetectEngineAppInspectionEngine *insert = NULL;
while (tmp != NULL) {
if (tmp->dir == engine->dir &&
(tmp->sm_list == engine->sm_list ||
tmp->inspect_flags == engine->inspect_flags
)) {
SCLogError(SC_ERR_DETECT_PREPARE, "App Inspection Engine already "
"registered for this direction(%"PRIu16") ||"
"sm_list(%d) || "
"[inspect(%"PRIu32")]_flags",
tmp->dir, tmp->sm_list, tmp->inspect_flags);
exit(EXIT_FAILURE);
}
insert = tmp;
tmp = tmp->next;
}
if (insert == NULL)
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
list[FlowGetProtoMapping(engine->ipproto)][engine->alproto][engine->dir] = engine;
else
insert->next = engine;
return;
}
void DetectEngineRegisterAppInspectionEngine(uint8_t ipproto,
AppProto alproto,
uint16_t dir,
int32_t sm_list,
uint32_t inspect_flags,
int (*Callback)(ThreadVars *tv,
DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx,
Signature *sig, Flow *f,
uint8_t flags, void *alstate,
void *tx, uint64_t tx_id),
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
DetectEngineAppInspectionEngine *list[][ALPROTO_MAX][2])
{
if ((list == NULL) ||
(alproto <= ALPROTO_UNKNOWN || alproto >= ALPROTO_FAILED) ||
(dir > 1) ||
(sm_list < DETECT_SM_LIST_MATCH || sm_list >= DETECT_SM_LIST_MAX) ||
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
(Callback == NULL))
{
SCLogError(SC_ERR_INVALID_ARGUMENTS, "Invalid arguments");
exit(EXIT_FAILURE);
}
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
DetectEngineAppInspectionEngine *tmp = list[FlowGetProtoMapping(ipproto)][alproto][dir];
while (tmp != NULL) {
if (tmp->sm_list == sm_list && tmp->Callback == Callback) {
return;
}
tmp = tmp->next;
}
DetectEngineAppInspectionEngine *new_engine = SCMalloc(sizeof(DetectEngineAppInspectionEngine));
if (unlikely(new_engine == NULL)) {
exit(EXIT_FAILURE);
}
memset(new_engine, 0, sizeof(*new_engine));
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
new_engine->ipproto = ipproto;
new_engine->alproto = alproto;
new_engine->dir = dir;
new_engine->sm_list = sm_list;
new_engine->inspect_flags = inspect_flags;
new_engine->Callback = Callback;
AppendAppInspectionEngine(new_engine, list);
return;
}
/* code to control the main thread to do a reload */
enum DetectEngineSyncState {
IDLE, /**< ready to start a reload */
RELOAD, /**< command main thread to do the reload */
DONE, /**< main thread telling us reload is done */
};
typedef struct DetectEngineSyncer_ {
SCMutex m;
enum DetectEngineSyncState state;
} DetectEngineSyncer;
static DetectEngineSyncer detect_sync = { SCMUTEX_INITIALIZER, IDLE };
/* tell main to start reloading */
int DetectEngineReloadStart(void)
{
int r = 0;
SCMutexLock(&detect_sync.m);
if (detect_sync.state == IDLE) {
detect_sync.state = RELOAD;
} else {
r = -1;
}
SCMutexUnlock(&detect_sync.m);
return r;
}
/* main thread checks this to see if it should start */
int DetectEngineReloadIsStart(void)
{
int r = 0;
SCMutexLock(&detect_sync.m);
if (detect_sync.state == RELOAD) {
r = 1;
}
SCMutexUnlock(&detect_sync.m);
return r;
}
/* main thread sets done when it's done */
void DetectEngineReloadSetDone(void)
{
SCMutexLock(&detect_sync.m);
detect_sync.state = DONE;
SCMutexUnlock(&detect_sync.m);
}
/* caller loops this until it returns 1 */
int DetectEngineReloadIsDone(void)
{
int r = 0;
SCMutexLock(&detect_sync.m);
if (detect_sync.state == DONE) {
r = 1;
detect_sync.state = IDLE;
}
SCMutexUnlock(&detect_sync.m);
return r;
}
/** \internal
* \brief Update detect threads with new detect engine
*
* Atomically update each detect thread with a new thread context
* that is associated to the new detection engine(s).
*
* If called in unix socket mode, it's possible that we don't have
* detect threads yet.
*
* \retval -1 error
* \retval 0 no detection threads
* \retval 1 successful reload
*/
static int DetectEngineReloadThreads(DetectEngineCtx *new_de_ctx)
{
SCEnter();
int i = 0;
int no_of_detect_tvs = 0;
ThreadVars *tv = NULL;
/* count detect threads in use */
SCMutexLock(&tv_root_lock);
tv = tv_root[TVT_PPT];
while (tv) {
/* obtain the slots for this TV */
TmSlot *slots = tv->tm_slots;
while (slots != NULL) {
TmModule *tm = TmModuleGetById(slots->tm_id);
if (suricata_ctl_flags != 0) {
SCLogInfo("rule reload interupted by engine shutdown");
SCMutexUnlock(&tv_root_lock);
return -1;
}
if (!(tm->flags & TM_FLAG_DETECT_TM)) {
slots = slots->slot_next;
continue;
}
no_of_detect_tvs++;
break;
}
tv = tv->next;
}
SCMutexUnlock(&tv_root_lock);
/* can be zero in unix socket mode */
if (no_of_detect_tvs == 0) {
return 0;
}
SCLogNotice("rule reload starting");
/* prepare swap structures */
DetectEngineThreadCtx *old_det_ctx[no_of_detect_tvs];
DetectEngineThreadCtx *new_det_ctx[no_of_detect_tvs];
ThreadVars *detect_tvs[no_of_detect_tvs];
memset(old_det_ctx, 0x00, (no_of_detect_tvs * sizeof(DetectEngineThreadCtx *)));
memset(new_det_ctx, 0x00, (no_of_detect_tvs * sizeof(DetectEngineThreadCtx *)));
memset(detect_tvs, 0x00, (no_of_detect_tvs * sizeof(ThreadVars *)));
/* start the process of swapping detect threads ctxs */
/* get reference to tv's and setup new_det_ctx array */
SCMutexLock(&tv_root_lock);
tv = tv_root[TVT_PPT];
while (tv) {
/* obtain the slots for this TV */
TmSlot *slots = tv->tm_slots;
while (slots != NULL) {
TmModule *tm = TmModuleGetById(slots->tm_id);
if (suricata_ctl_flags != 0) {
SCMutexUnlock(&tv_root_lock);
goto error;
}
if (!(tm->flags & TM_FLAG_DETECT_TM)) {
slots = slots->slot_next;
continue;
}
old_det_ctx[i] = SC_ATOMIC_GET(slots->slot_data);
detect_tvs[i] = tv;
if (new_de_ctx != NULL)
new_det_ctx[i] = DetectEngineThreadCtxInitForReload(tv, new_de_ctx);
else
new_det_ctx[i] = DetectEngineThreadCtxInitForMT(tv);
if (new_det_ctx[i] == NULL) {
SCLogError(SC_ERR_LIVE_RULE_SWAP, "Detect engine thread init "
"failure in live rule swap. Let's get out of here");
SCMutexUnlock(&tv_root_lock);
goto error;
}
SCLogDebug("live rule swap created new det_ctx - %p and de_ctx "
"- %p\n", new_det_ctx[i], new_de_ctx);
i++;
break;
}
tv = tv->next;
}
BUG_ON(i != no_of_detect_tvs);
/* atomicly replace the det_ctx data */
i = 0;
tv = tv_root[TVT_PPT];
while (tv) {
/* find the correct slot */
TmSlot *slots = tv->tm_slots;
while (slots != NULL) {
if (suricata_ctl_flags != 0) {
return -1;
}
TmModule *tm = TmModuleGetById(slots->tm_id);
if (!(tm->flags & TM_FLAG_DETECT_TM)) {
slots = slots->slot_next;
continue;
}
SCLogDebug("swapping new det_ctx - %p with older one - %p",
new_det_ctx[i], SC_ATOMIC_GET(slots->slot_data));
(void)SC_ATOMIC_SET(slots->slot_data, new_det_ctx[i++]);
break;
}
tv = tv->next;
}
SCMutexUnlock(&tv_root_lock);
/* threads now all have new data, however they may not have started using
* it and may still use the old data */
SCLogInfo("Live rule swap has swapped %d old det_ctx's with new ones, "
"along with the new de_ctx", no_of_detect_tvs);
/* inject a fake packet if the detect thread isn't using the new ctx yet,
* this speeds up the process */
for (i = 0; i < no_of_detect_tvs; i++) {
int break_out = 0;
int pseudo_pkt_inserted = 0;
usleep(1000);
while (SC_ATOMIC_GET(new_det_ctx[i]->so_far_used_by_detect) != 1) {
if (suricata_ctl_flags != 0) {
break_out = 1;
break;
}
if (pseudo_pkt_inserted == 0) {
pseudo_pkt_inserted = 1;
if (detect_tvs[i]->inq != NULL) {
Packet *p = PacketGetFromAlloc();
if (p != NULL) {
p->flags |= PKT_PSEUDO_STREAM_END;
PacketQueue *q = &trans_q[detect_tvs[i]->inq->id];
SCMutexLock(&q->mutex_q);
PacketEnqueue(q, p);
SCCondSignal(&q->cond_q);
SCMutexUnlock(&q->mutex_q);
}
}
}
usleep(1000);
}
if (break_out)
break;
SCLogDebug("new_det_ctx - %p used by detect engine", new_det_ctx[i]);
}
/* this is to make sure that if someone initiated shutdown during a live
* rule swap, the live rule swap won't clean up the old det_ctx and
* de_ctx, till all detect threads have stopped working and sitting
* silently after setting RUNNING_DONE flag and while waiting for
* THV_DEINIT flag */
if (i != no_of_detect_tvs) { // not all threads we swapped
ThreadVars *tv = tv_root[TVT_PPT];
while (tv) {
/* obtain the slots for this TV */
TmSlot *slots = tv->tm_slots;
while (slots != NULL) {
TmModule *tm = TmModuleGetById(slots->tm_id);
if (!(tm->flags & TM_FLAG_DETECT_TM)) {
slots = slots->slot_next;
continue;
}
while (!TmThreadsCheckFlag(tv, THV_RUNNING_DONE)) {
usleep(100);
}
slots = slots->slot_next;
}
tv = tv->next;
}
}
/* free all the ctxs */
for (i = 0; i < no_of_detect_tvs; i++) {
SCLogDebug("Freeing old_det_ctx - %p used by detect",
old_det_ctx[i]);
DetectEngineThreadCtxDeinit(NULL, old_det_ctx[i]);
}
SRepReloadComplete();
SCLogNotice("rule reload complete");
return 1;
error:
for (i = 0; i < no_of_detect_tvs; i++) {
if (new_det_ctx[i] != NULL)
DetectEngineThreadCtxDeinit(NULL, new_det_ctx[i]);
}
return -1;
}
static DetectEngineCtx *DetectEngineCtxInitReal(int minimal, const char *prefix)
{
DetectEngineCtx *de_ctx;
ConfNode *seq_node = NULL;
ConfNode *insp_recursion_limit_node = NULL;
ConfNode *de_engine_node = NULL;
char *insp_recursion_limit = NULL;
de_ctx = SCMalloc(sizeof(DetectEngineCtx));
if (unlikely(de_ctx == NULL))
goto error;
memset(de_ctx,0,sizeof(DetectEngineCtx));
if (minimal) {
de_ctx->minimal = 1;
de_ctx->id = detect_engine_ctx_id++;
return de_ctx;
}
if (prefix != NULL) {
strlcpy(de_ctx->config_prefix, prefix, sizeof(de_ctx->config_prefix));
}
if (ConfGetBool("engine.init-failure-fatal", (int *)&(de_ctx->failure_fatal)) != 1) {
SCLogDebug("ConfGetBool could not load the value.");
}
de_engine_node = ConfGetNode("detect-engine");
if (de_engine_node != NULL) {
TAILQ_FOREACH(seq_node, &de_engine_node->head, next) {
if (strcmp(seq_node->val, "inspection-recursion-limit") != 0)
continue;
insp_recursion_limit_node = ConfNodeLookupChild(seq_node, seq_node->val);
if (insp_recursion_limit_node == NULL) {
SCLogError(SC_ERR_INVALID_YAML_CONF_ENTRY, "Error retrieving conf "
"entry for detect-engine:inspection-recursion-limit");
break;
}
insp_recursion_limit = insp_recursion_limit_node->val;
SCLogDebug("Found detect-engine:inspection-recursion-limit - %s:%s",
insp_recursion_limit_node->name, insp_recursion_limit_node->val);
break;
}
}
if (insp_recursion_limit != NULL) {
de_ctx->inspection_recursion_limit = atoi(insp_recursion_limit);
} else {
de_ctx->inspection_recursion_limit =
DETECT_ENGINE_DEFAULT_INSPECTION_RECURSION_LIMIT;
}
if (de_ctx->inspection_recursion_limit == 0)
de_ctx->inspection_recursion_limit = -1;
SCLogDebug("de_ctx->inspection_recursion_limit: %d",
de_ctx->inspection_recursion_limit);
de_ctx->mpm_matcher = PatternMatchDefaultMatcher();
DetectEngineCtxLoadConf(de_ctx);
SigGroupHeadHashInit(de_ctx);
SigGroupHeadMpmHashInit(de_ctx);
SigGroupHeadMpmUriHashInit(de_ctx);
SigGroupHeadSPortHashInit(de_ctx);
SigGroupHeadDPortHashInit(de_ctx);
DetectPortSpHashInit(de_ctx);
DetectPortDpHashInit(de_ctx);
16 years ago
ThresholdHashInit(de_ctx);
VariableNameInitHash(de_ctx);
DetectParseDupSigHashInit(de_ctx);
de_ctx->mpm_pattern_id_store = MpmPatternIdTableInitHash();
if (de_ctx->mpm_pattern_id_store == NULL) {
goto error;
}
/* init iprep... ignore errors for now */
(void)SRepInit(de_ctx);
#ifdef PROFILING
SCProfilingKeywordInitCounters(de_ctx);
#endif
SCClassConfLoadClassficationConfigFile(de_ctx, NULL);
SCRConfLoadReferenceConfigFile(de_ctx, NULL);
if (ActionInitConfig() < 0) {
goto error;
}
de_ctx->id = detect_engine_ctx_id++;
return de_ctx;
error:
return NULL;
}
DetectEngineCtx *DetectEngineCtxInitMinimal(void)
{
return DetectEngineCtxInitReal(1, NULL);
}
DetectEngineCtx *DetectEngineCtxInit(void)
{
return DetectEngineCtxInitReal(0, NULL);
}
DetectEngineCtx *DetectEngineCtxInitWithPrefix(const char *prefix)
{
if (prefix == NULL || strlen(prefix) == 0)
return DetectEngineCtxInit();
else
return DetectEngineCtxInitReal(0, prefix);
}
static void DetectEngineCtxFreeThreadKeywordData(DetectEngineCtx *de_ctx)
{
DetectEngineThreadKeywordCtxItem *item = de_ctx->keyword_list;
while (item) {
DetectEngineThreadKeywordCtxItem *next = item->next;
SCFree(item);
item = next;
}
de_ctx->keyword_list = NULL;
}
/**
* \brief Free a DetectEngineCtx::
*
* \param de_ctx DetectEngineCtx:: to be freed
*/
void DetectEngineCtxFree(DetectEngineCtx *de_ctx)
{
if (de_ctx == NULL)
return;
#ifdef PROFILING
if (de_ctx->profile_ctx != NULL) {
SCProfilingRuleDestroyCtx(de_ctx->profile_ctx);
de_ctx->profile_ctx = NULL;
}
if (de_ctx->profile_keyword_ctx != NULL) {
SCProfilingKeywordDestroyCtx(de_ctx);//->profile_keyword_ctx);
// de_ctx->profile_keyword_ctx = NULL;
}
#endif
/* Normally the hashes are freed elsewhere, but
* to be sure look at them again here.
*/
MpmPatternIdTableFreeHash(de_ctx->mpm_pattern_id_store); /* normally cleaned up in SigGroupBuild */
SigGroupHeadHashFree(de_ctx);
SigGroupHeadMpmHashFree(de_ctx);
SigGroupHeadMpmUriHashFree(de_ctx);
SigGroupHeadSPortHashFree(de_ctx);
SigGroupHeadDPortHashFree(de_ctx);
DetectParseDupSigHashFree(de_ctx);
SCSigSignatureOrderingModuleCleanup(de_ctx);
DetectPortSpHashFree(de_ctx);
DetectPortDpHashFree(de_ctx);
16 years ago
ThresholdContextDestroy(de_ctx);
SigCleanSignatures(de_ctx);
VariableNameFreeHash(de_ctx);
if (de_ctx->sig_array)
SCFree(de_ctx->sig_array);
SCClassConfDeInitContext(de_ctx);
SCRConfDeInitContext(de_ctx);
SigGroupCleanup(de_ctx);
if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
MpmFactoryDeRegisterAllMpmCtxProfiles(de_ctx);
}
DetectEngineCtxFreeThreadKeywordData(de_ctx);
SRepDestroy(de_ctx);
/* if we have a config prefix, remove the config from the tree */
if (strlen(de_ctx->config_prefix) > 0) {
/* remove config */
ConfNode *node = ConfGetNode(de_ctx->config_prefix);
if (node != NULL) {
ConfNodeRemove(node); /* frees node */
}
#if 0
ConfDump();
#endif
}
SCFree(de_ctx);
//DetectAddressGroupPrintMemory();
//DetectSigGroupPrintMemory();
//DetectPortPrintMemory();
}
/** \brief Function that load DetectEngineCtx config for grouping sigs
* used by the engine
* \retval 0 if no config provided, 1 if config was provided
* and loaded successfuly
*/
static uint8_t DetectEngineCtxLoadConf(DetectEngineCtx *de_ctx)
{
uint8_t profile = ENGINE_PROFILE_UNKNOWN;
char *de_ctx_profile = NULL;
const char *max_uniq_toclient_src_groups_str = NULL;
const char *max_uniq_toclient_dst_groups_str = NULL;
const char *max_uniq_toclient_sp_groups_str = NULL;
const char *max_uniq_toclient_dp_groups_str = NULL;
const char *max_uniq_toserver_src_groups_str = NULL;
const char *max_uniq_toserver_dst_groups_str = NULL;
const char *max_uniq_toserver_sp_groups_str = NULL;
const char *max_uniq_toserver_dp_groups_str = NULL;
char *sgh_mpm_context = NULL;
ConfNode *de_ctx_custom = ConfGetNode("detect-engine");
ConfNode *opt = NULL;
if (de_ctx_custom != NULL) {
TAILQ_FOREACH(opt, &de_ctx_custom->head, next) {
if (strcmp(opt->val, "profile") == 0) {
de_ctx_profile = opt->head.tqh_first->val;
} else if (strcmp(opt->val, "sgh-mpm-context") == 0) {
sgh_mpm_context = opt->head.tqh_first->val;
}
}
}
if (de_ctx_profile != NULL) {
if (strcmp(de_ctx_profile, "low") == 0) {
profile = ENGINE_PROFILE_LOW;
} else if (strcmp(de_ctx_profile, "medium") == 0) {
profile = ENGINE_PROFILE_MEDIUM;
} else if (strcmp(de_ctx_profile, "high") == 0) {
profile = ENGINE_PROFILE_HIGH;
} else if (strcmp(de_ctx_profile, "custom") == 0) {
profile = ENGINE_PROFILE_CUSTOM;
}
SCLogDebug("Profile for detection engine groups is \"%s\"", de_ctx_profile);
} else {
SCLogDebug("Profile for detection engine groups not provided "
"at suricata.yaml. Using default (\"medium\").");
}
/* detect-engine.sgh-mpm-context option parsing */
if (sgh_mpm_context == NULL || strcmp(sgh_mpm_context, "auto") == 0) {
/* for now, since we still haven't implemented any intelligence into
* understanding the patterns and distributing mpm_ctx across sgh */
New Multi-pattern matcher, ac-tile, optimized for Tile architecture. Aho-Corasick mpm optimized for Tilera Tile-Gx architecture. Based on the util-mpm-ac.c code base. The primary optimizations are: 1) Matching function used Tilera specific instructions. 2) Alphabet compression to reduce delta table size to increase cache utilization and performance. The basic observation is that not all 256 ASCII characters are used by the set of multiple patterns in a group for which a DFA is created. The first reason is that Suricata's pattern matching is case-insensitive, so all uppercase characters are converted to lowercase, leaving a hole of 26 characters in the alphabet. Previously, this hole was simply left in the middle of the alphabet and thus in the generated Next State (delta) tables. A new, smaller, alphabet is created using a translation table of 256 bytes per mpm group. Previously, there was one global translation table for converting upper case to lowercase. Additional, unused characters are found by creating a histogram of all the characters in all the patterns. Then all the characters with zero counts are mapped to one character (0) in the new alphabet. Since These characters appear in no pattern, they can all be mapped to a single character and still result in the same matches being found. Zero was chosen for the value in the new alphabet since this "character" is more likely to appear in the input. The unused character always results in the next state being state zero, but that fact is not currently used by the code, since special casing takes additional instructions. The characters that do appear in some pattern are mapped to consecutive characters in the new alphabet, starting at 1. This results in a dense packing of next state values in the delta tables and additionally can allow for a smaller number of columns in that table, thus using less memory and better packing into the cache. The size of the new alphabet is the number of used characters plus 1 for the unused catch-all character. The alphabet size is rounded up to the next larger power-of-2 so that multiplication by the alphabet size can be done with a shift. It might be possible to use a multiply instruction, so that the exact alphabet size could be used, which would further reduce the size of the delta tables, increase cache density and not require the specialized search functions. The multiply would likely add 1 cycle to the inner search loop. Since the multiply by alphabet-size is cleverly merged with a mask instruction (in the SINDEX macro), specialized versions of the SCACSearch function are generated for alphabet sizes 256, 128, 64, 32 and 16. This is done by including the file util-mpm-ac-small.c multiple times with a redefined SINDEX macro. A function pointer is then stored in the mpm context for the search function. For alpha bit sizes of 8 or smaller, the number of states usually small, so the DFA is already very small, so there is little difference using the 16 state search function. The SCACSearch function is also specialized by the size of the value stored in the next state (delta) tables, either 16-bits or 32-bits. This removes a conditional inside the Search function. That conditional is only called once, but doesn't hurt to remove it. 16-bits are used for up to 32K states, with the sign bit set for states with matches. Future optimization: The state-has-match values is only needed per state, not per next state, so checking the next-state sign bit could be replaced with reading a different value, at the cost of an additional load, but increasing the 16-bit next state span to 64K. Since the order of the characters in the new alphabet doesn't matter, the new alphabet could be sorted by the frequency of the characters in the expected input stream for that multi-pattern matcher. This would group more frequent characters into the same cache lines, thus increasing the probability of reusing a cache-line. All the next state values for each state live in their own set of cache-lines. With power-of-two sizes alphabets, these don't overlap. So either 32 or 16 character's next states are loaded in each cache line load. If the alphabet size is not an exact power-of-2, then the last cache-line is not completely full and up to 31*2 bytes of that line could be wasted per state. The next state table could be transposed, so that all the next states for a specific character are stored sequentially, this could be better if some characters, for example the unused character, are much more frequent.
12 years ago
if (de_ctx->mpm_matcher == DEFAULT_MPM || de_ctx->mpm_matcher == MPM_AC_GFBS ||
#ifdef __SC_CUDA_SUPPORT__
de_ctx->mpm_matcher == MPM_AC_BS || de_ctx->mpm_matcher == MPM_AC_CUDA) {
#else
de_ctx->mpm_matcher == MPM_AC_BS) {
#endif
de_ctx->sgh_mpm_context = ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE;
} else {
de_ctx->sgh_mpm_context = ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL;
}
} else {
if (strcmp(sgh_mpm_context, "single") == 0) {
de_ctx->sgh_mpm_context = ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE;
} else if (strcmp(sgh_mpm_context, "full") == 0) {
#ifdef __SC_CUDA_SUPPORT__
if (de_ctx->mpm_matcher == MPM_AC_CUDA) {
SCLogError(SC_ERR_INVALID_YAML_CONF_ENTRY, "You can't use "
"the cuda version of our mpm ac, i.e. \"ac-cuda\" "
"along with \"full\" \"sgh-mpm-context\". "
"Allowed values are \"single\" and \"auto\".");
exit(EXIT_FAILURE);
}
#endif
de_ctx->sgh_mpm_context = ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL;
} else {
SCLogError(SC_ERR_INVALID_YAML_CONF_ENTRY, "You have supplied an "
"invalid conf value for detect-engine.sgh-mpm-context-"
"%s", sgh_mpm_context);
exit(EXIT_FAILURE);
}
}
if (run_mode == RUNMODE_UNITTEST) {
de_ctx->sgh_mpm_context = ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL;
}
opt = NULL;
switch (profile) {
case ENGINE_PROFILE_LOW:
de_ctx->max_uniq_toclient_src_groups = 2;
de_ctx->max_uniq_toclient_dst_groups = 2;
de_ctx->max_uniq_toclient_sp_groups = 2;
de_ctx->max_uniq_toclient_dp_groups = 3;
de_ctx->max_uniq_toserver_src_groups = 2;
de_ctx->max_uniq_toserver_dst_groups = 2;
de_ctx->max_uniq_toserver_sp_groups = 2;
de_ctx->max_uniq_toserver_dp_groups = 3;
break;
case ENGINE_PROFILE_HIGH:
de_ctx->max_uniq_toclient_src_groups = 15;
de_ctx->max_uniq_toclient_dst_groups = 15;
de_ctx->max_uniq_toclient_sp_groups = 15;
de_ctx->max_uniq_toclient_dp_groups = 20;
de_ctx->max_uniq_toserver_src_groups = 15;
de_ctx->max_uniq_toserver_dst_groups = 15;
de_ctx->max_uniq_toserver_sp_groups = 15;
de_ctx->max_uniq_toserver_dp_groups = 40;
break;
case ENGINE_PROFILE_CUSTOM:
TAILQ_FOREACH(opt, &de_ctx_custom->head, next) {
if (strcmp(opt->val, "custom-values") == 0) {
max_uniq_toclient_src_groups_str = ConfNodeLookupChildValue
(opt->head.tqh_first, "toclient-src-groups");
max_uniq_toclient_dst_groups_str = ConfNodeLookupChildValue
(opt->head.tqh_first, "toclient-dst-groups");
max_uniq_toclient_sp_groups_str = ConfNodeLookupChildValue
(opt->head.tqh_first, "toclient-sp-groups");
max_uniq_toclient_dp_groups_str = ConfNodeLookupChildValue
(opt->head.tqh_first, "toclient-dp-groups");
max_uniq_toserver_src_groups_str = ConfNodeLookupChildValue
(opt->head.tqh_first, "toserver-src-groups");
max_uniq_toserver_dst_groups_str = ConfNodeLookupChildValue
(opt->head.tqh_first, "toserver-dst-groups");
max_uniq_toserver_sp_groups_str = ConfNodeLookupChildValue
(opt->head.tqh_first, "toserver-sp-groups");
max_uniq_toserver_dp_groups_str = ConfNodeLookupChildValue
(opt->head.tqh_first, "toserver-dp-groups");
}
}
if (max_uniq_toclient_src_groups_str != NULL) {
if (ByteExtractStringUint16(&de_ctx->max_uniq_toclient_src_groups, 10,
strlen(max_uniq_toclient_src_groups_str),
(const char *)max_uniq_toclient_src_groups_str) <= 0) {
de_ctx->max_uniq_toclient_src_groups = 4;
SCLogWarning(SC_ERR_SIZE_PARSE, "parsing '%s' for "
"toclient-src-groups failed, using %u",
max_uniq_toclient_src_groups_str,
de_ctx->max_uniq_toclient_src_groups);
}
} else {
de_ctx->max_uniq_toclient_src_groups = 4;
}
if (max_uniq_toclient_dst_groups_str != NULL) {
if (ByteExtractStringUint16(&de_ctx->max_uniq_toclient_dst_groups, 10,
strlen(max_uniq_toclient_dst_groups_str),
(const char *)max_uniq_toclient_dst_groups_str) <= 0) {
de_ctx->max_uniq_toclient_dst_groups = 4;
SCLogWarning(SC_ERR_SIZE_PARSE, "parsing '%s' for "
"toclient-dst-groups failed, using %u",
max_uniq_toclient_dst_groups_str,
de_ctx->max_uniq_toclient_dst_groups);
}
} else {
de_ctx->max_uniq_toclient_dst_groups = 4;
}
if (max_uniq_toclient_sp_groups_str != NULL) {
if (ByteExtractStringUint16(&de_ctx->max_uniq_toclient_sp_groups, 10,
strlen(max_uniq_toclient_sp_groups_str),
(const char *)max_uniq_toclient_sp_groups_str) <= 0) {
de_ctx->max_uniq_toclient_sp_groups = 4;
SCLogWarning(SC_ERR_SIZE_PARSE, "parsing '%s' for "
"toclient-sp-groups failed, using %u",
max_uniq_toclient_sp_groups_str,
de_ctx->max_uniq_toclient_sp_groups);
}
} else {
de_ctx->max_uniq_toclient_sp_groups = 4;
}
if (max_uniq_toclient_dp_groups_str != NULL) {
if (ByteExtractStringUint16(&de_ctx->max_uniq_toclient_dp_groups, 10,
strlen(max_uniq_toclient_dp_groups_str),
(const char *)max_uniq_toclient_dp_groups_str) <= 0) {
de_ctx->max_uniq_toclient_dp_groups = 6;
SCLogWarning(SC_ERR_SIZE_PARSE, "parsing '%s' for "
"toclient-dp-groups failed, using %u",
max_uniq_toclient_dp_groups_str,
de_ctx->max_uniq_toclient_dp_groups);
}
} else {
de_ctx->max_uniq_toclient_dp_groups = 6;
}
if (max_uniq_toserver_src_groups_str != NULL) {
if (ByteExtractStringUint16(&de_ctx->max_uniq_toserver_src_groups, 10,
strlen(max_uniq_toserver_src_groups_str),
(const char *)max_uniq_toserver_src_groups_str) <= 0) {
de_ctx->max_uniq_toserver_src_groups = 4;
SCLogWarning(SC_ERR_SIZE_PARSE, "parsing '%s' for "
"toserver-src-groups failed, using %u",
max_uniq_toserver_src_groups_str,
de_ctx->max_uniq_toserver_src_groups);
}
} else {
de_ctx->max_uniq_toserver_src_groups = 4;
}
if (max_uniq_toserver_dst_groups_str != NULL) {
if (ByteExtractStringUint16(&de_ctx->max_uniq_toserver_dst_groups, 10,
strlen(max_uniq_toserver_dst_groups_str),
(const char *)max_uniq_toserver_dst_groups_str) <= 0) {
de_ctx->max_uniq_toserver_dst_groups = 8;
SCLogWarning(SC_ERR_SIZE_PARSE, "parsing '%s' for "
"toserver-dst-groups failed, using %u",
max_uniq_toserver_dst_groups_str,
de_ctx->max_uniq_toserver_dst_groups);
}
} else {
de_ctx->max_uniq_toserver_dst_groups = 8;
}
if (max_uniq_toserver_sp_groups_str != NULL) {
if (ByteExtractStringUint16(&de_ctx->max_uniq_toserver_sp_groups, 10,
strlen(max_uniq_toserver_sp_groups_str),
(const char *)max_uniq_toserver_sp_groups_str) <= 0) {
de_ctx->max_uniq_toserver_sp_groups = 4;
SCLogWarning(SC_ERR_SIZE_PARSE, "parsing '%s' for "
"toserver-sp-groups failed, using %u",
max_uniq_toserver_sp_groups_str,
de_ctx->max_uniq_toserver_sp_groups);
}
} else {
de_ctx->max_uniq_toserver_sp_groups = 4;
}
if (max_uniq_toserver_dp_groups_str != NULL) {
if (ByteExtractStringUint16(&de_ctx->max_uniq_toserver_dp_groups, 10,
strlen(max_uniq_toserver_dp_groups_str),
(const char *)max_uniq_toserver_dp_groups_str) <= 0) {
de_ctx->max_uniq_toserver_dp_groups = 30;
SCLogWarning(SC_ERR_SIZE_PARSE, "parsing '%s' for "
"toserver-dp-groups failed, using %u",
max_uniq_toserver_dp_groups_str,
de_ctx->max_uniq_toserver_dp_groups);
}
} else {
de_ctx->max_uniq_toserver_dp_groups = 30;
}
break;
/* Default (or no config provided) is profile medium */
case ENGINE_PROFILE_MEDIUM:
case ENGINE_PROFILE_UNKNOWN:
default:
de_ctx->max_uniq_toclient_src_groups = 4;
de_ctx->max_uniq_toclient_dst_groups = 4;
de_ctx->max_uniq_toclient_sp_groups = 4;
de_ctx->max_uniq_toclient_dp_groups = 6;
de_ctx->max_uniq_toserver_src_groups = 4;
de_ctx->max_uniq_toserver_dst_groups = 8;
de_ctx->max_uniq_toserver_sp_groups = 4;
de_ctx->max_uniq_toserver_dp_groups = 30;
break;
}
if (profile == ENGINE_PROFILE_UNKNOWN)
return 0;
return 1;
}
/*
* getting & (re)setting the internal sig i
*/
//inline uint32_t DetectEngineGetMaxSigId(DetectEngineCtx *de_ctx)
11 years ago
//{
// return de_ctx->signum;
//}
void DetectEngineResetMaxSigId(DetectEngineCtx *de_ctx)
{
de_ctx->signum = 0;
}
static int DetectEngineThreadCtxInitKeywords(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx)
{
if (de_ctx->keyword_id > 0) {
det_ctx->keyword_ctxs_array = SCMalloc(de_ctx->keyword_id * sizeof(void *));
if (det_ctx->keyword_ctxs_array == NULL) {
SCLogError(SC_ERR_DETECT_PREPARE, "setting up thread local detect ctx");
return TM_ECODE_FAILED;
}
memset(det_ctx->keyword_ctxs_array, 0x00, de_ctx->keyword_id * sizeof(void *));
det_ctx->keyword_ctxs_size = de_ctx->keyword_id;
DetectEngineThreadKeywordCtxItem *item = de_ctx->keyword_list;
while (item) {
det_ctx->keyword_ctxs_array[item->id] = item->InitFunc(item->data);
if (det_ctx->keyword_ctxs_array[item->id] == NULL) {
SCLogError(SC_ERR_DETECT_PREPARE, "setting up thread local detect ctx "
"for keyword \"%s\" failed", item->name);
return TM_ECODE_FAILED;
}
item = item->next;
}
}
return TM_ECODE_OK;
}
static void DetectEngineThreadCtxDeinitKeywords(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx)
{
if (de_ctx->keyword_id > 0) {
DetectEngineThreadKeywordCtxItem *item = de_ctx->keyword_list;
while (item) {
if (det_ctx->keyword_ctxs_array[item->id] != NULL)
item->FreeFunc(det_ctx->keyword_ctxs_array[item->id]);
item = item->next;
}
det_ctx->keyword_ctxs_size = 0;
SCFree(det_ctx->keyword_ctxs_array);
det_ctx->keyword_ctxs_array = NULL;
}
}
/** \internal
* \brief Helper for DetectThread setup functions
*/
static TmEcode ThreadCtxDoInit (DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx)
{
int i;
16 years ago
/** \todo we still depend on the global mpm_ctx here
*
* Initialize the thread pattern match ctx with the max size
* of the content and uricontent id's so our match lookup
* table is always big enough
*/
PatternMatchThreadPrepare(&det_ctx->mtc, de_ctx->mpm_matcher, DetectContentMaxId(de_ctx));
PatternMatchThreadPrepare(&det_ctx->mtcs, de_ctx->mpm_matcher, DetectContentMaxId(de_ctx));
PatternMatchThreadPrepare(&det_ctx->mtcu, de_ctx->mpm_matcher, DetectUricontentMaxId(de_ctx));
16 years ago
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
PmqSetup(&det_ctx->pmq, de_ctx->max_fp_id);
for (i = 0; i < DETECT_SMSG_PMQ_NUM; i++) {
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
PmqSetup(&det_ctx->smsg_pmq[i], de_ctx->max_fp_id);
}
16 years ago
/* sized to the max of our sgh settings. A max setting of 0 implies that all
* sgh's have: sgh->non_mpm_store_cnt == 0 */
if (de_ctx->non_mpm_store_cnt_max > 0) {
det_ctx->non_mpm_id_array = SCCalloc(de_ctx->non_mpm_store_cnt_max, sizeof(SigIntId));
BUG_ON(det_ctx->non_mpm_id_array == NULL);
}
16 years ago
/* IP-ONLY */
DetectEngineIPOnlyThreadInit(de_ctx,&det_ctx->io_ctx);
/* DeState */
if (de_ctx->sig_array_len > 0) {
det_ctx->de_state_sig_array_len = de_ctx->sig_array_len;
det_ctx->de_state_sig_array = SCMalloc(det_ctx->de_state_sig_array_len * sizeof(uint8_t));
if (det_ctx->de_state_sig_array == NULL) {
return TM_ECODE_FAILED;
}
memset(det_ctx->de_state_sig_array, 0,
det_ctx->de_state_sig_array_len * sizeof(uint8_t));
det_ctx->match_array_len = de_ctx->sig_array_len;
det_ctx->match_array = SCMalloc(det_ctx->match_array_len * sizeof(Signature *));
if (det_ctx->match_array == NULL) {
return TM_ECODE_FAILED;
}
memset(det_ctx->match_array, 0,
det_ctx->match_array_len * sizeof(Signature *));
}
/* byte_extract storage */
det_ctx->bj_values = SCMalloc(sizeof(*det_ctx->bj_values) *
(de_ctx->byte_extract_max_local_id + 1));
if (det_ctx->bj_values == NULL) {
return TM_ECODE_FAILED;
}
DetectEngineThreadCtxInitKeywords(de_ctx, det_ctx);
#ifdef PROFILING
SCProfilingRuleThreadSetup(de_ctx->profile_ctx, det_ctx);
SCProfilingKeywordThreadSetup(de_ctx->profile_keyword_ctx, det_ctx);
#endif
SC_ATOMIC_INIT(det_ctx->so_far_used_by_detect);
return TM_ECODE_OK;
}
/** \brief initialize thread specific detection engine context
*
* \note there is a special case when using delayed detect. In this case the
* function is called twice per thread. The first time the rules are not
* yet loaded. de_ctx->delayed_detect_initialized will be 0. The 2nd
* time they will be loaded. de_ctx->delayed_detect_initialized will be 1.
* This is needed to do the per thread counter registration before the
* packet runtime starts. In delayed detect mode, the first call will
* return a NULL ptr through the data ptr.
*
* \param tv ThreadVars for this thread
* \param initdata pointer to de_ctx
* \param data[out] pointer to store our thread detection ctx
*
* \retval TM_ECODE_OK if all went well
* \retval TM_ECODE_FAILED on serious erro
*/
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
{
if (DetectEngineMultiTenantEnabled()) {
DetectEngineThreadCtx *mt_det_ctx = DetectEngineThreadCtxInitForMT(tv);
*data = (void *)mt_det_ctx;
return (mt_det_ctx == NULL) ? TM_ECODE_FAILED : TM_ECODE_OK;
}
/* first register the counter. In delayed detect mode we exit right after if the
* rules haven't been loaded yet. */
uint16_t counter_alerts = StatsRegisterCounter("detect.alert", tv);
#ifdef PROFILING
uint16_t counter_mpm_list = StatsRegisterAvgCounter("detect.mpm_list", tv);
uint16_t counter_nonmpm_list = StatsRegisterAvgCounter("detect.nonmpm_list", tv);
uint16_t counter_fnonmpm_list = StatsRegisterAvgCounter("detect.fnonmpm_list", tv);
uint16_t counter_match_list = StatsRegisterAvgCounter("detect.match_list", tv);
#endif
DetectEngineThreadCtx *det_ctx = SCMalloc(sizeof(DetectEngineThreadCtx));
if (unlikely(det_ctx == NULL))
return TM_ECODE_FAILED;
memset(det_ctx, 0, sizeof(DetectEngineThreadCtx));
det_ctx->tv = tv;
det_ctx->de_ctx = DetectEngineGetCurrent();
if (det_ctx->de_ctx == NULL) {
#ifdef UNITTESTS
if (RunmodeIsUnittests()) {
det_ctx->de_ctx = (DetectEngineCtx *)initdata;
} else {
DetectEngineThreadCtxDeinit(tv, det_ctx);
return TM_ECODE_FAILED;
}
#else
DetectEngineThreadCtxDeinit(tv, det_ctx);
return TM_ECODE_FAILED;
#endif
}
if (det_ctx->de_ctx->minimal == 0) {
if (ThreadCtxDoInit(det_ctx->de_ctx, det_ctx) != TM_ECODE_OK) {
DetectEngineThreadCtxDeinit(tv, det_ctx);
return TM_ECODE_FAILED;
}
}
/** alert counter setup */
det_ctx->counter_alerts = counter_alerts;
#ifdef PROFILING
det_ctx->counter_mpm_list = counter_mpm_list;
det_ctx->counter_nonmpm_list = counter_nonmpm_list;
det_ctx->counter_fnonmpm_list = counter_fnonmpm_list;
det_ctx->counter_match_list = counter_match_list;
#endif
/* pass thread data back to caller */
*data = (void *)det_ctx;
return TM_ECODE_OK;
}
/**
* \internal
* \brief initialize a det_ctx for reload cases
* \param new_de_ctx the new detection engine
* \retval det_ctx detection engine thread ctx or NULL in case of error
*/
static DetectEngineThreadCtx *DetectEngineThreadCtxInitForReload(
ThreadVars *tv, DetectEngineCtx *new_de_ctx)
{
DetectEngineThreadCtx *det_ctx = SCMalloc(sizeof(DetectEngineThreadCtx));
if (unlikely(det_ctx == NULL))
return NULL;
memset(det_ctx, 0, sizeof(DetectEngineThreadCtx));
det_ctx->tenant_id = new_de_ctx->tenant_id;
det_ctx->tv = tv;
det_ctx->de_ctx = DetectEngineReference(new_de_ctx);
if (det_ctx->de_ctx == NULL) {
SCFree(det_ctx);
return NULL;
}
/* most of the init happens here */
if (ThreadCtxDoInit(det_ctx->de_ctx, det_ctx) != TM_ECODE_OK) {
DetectEngineDeReference(&det_ctx->de_ctx);
SCFree(det_ctx);
return NULL;
}
/** alert counter setup */
det_ctx->counter_alerts = StatsRegisterCounter("detect.alert", tv);
#ifdef PROFILING
uint16_t counter_mpm_list = StatsRegisterAvgCounter("detect.mpm_list", tv);
uint16_t counter_nonmpm_list = StatsRegisterAvgCounter("detect.nonmpm_list", tv);
uint16_t counter_fnonmpm_list = StatsRegisterAvgCounter("detect.fnonmpm_list", tv);
uint16_t counter_match_list = StatsRegisterAvgCounter("detect.match_list", tv);
det_ctx->counter_mpm_list = counter_mpm_list;
det_ctx->counter_nonmpm_list = counter_nonmpm_list;
det_ctx->counter_fnonmpm_list = counter_fnonmpm_list;
det_ctx->counter_match_list = counter_match_list;
#endif
return det_ctx;
16 years ago
}
void DetectEngineThreadCtxFree(DetectEngineThreadCtx *det_ctx)
{
if (det_ctx->tenant_array != NULL) {
SCFree(det_ctx->tenant_array);
det_ctx->tenant_array = NULL;
}
#ifdef PROFILING
SCProfilingRuleThreadCleanup(det_ctx);
SCProfilingKeywordThreadCleanup(det_ctx);
#endif
DetectEngineIPOnlyThreadDeinit(&det_ctx->io_ctx);
16 years ago
/** \todo get rid of this static */
if (det_ctx->de_ctx != NULL) {
PatternMatchThreadDestroy(&det_ctx->mtc, det_ctx->de_ctx->mpm_matcher);
PatternMatchThreadDestroy(&det_ctx->mtcs, det_ctx->de_ctx->mpm_matcher);
PatternMatchThreadDestroy(&det_ctx->mtcu, det_ctx->de_ctx->mpm_matcher);
}
PmqFree(&det_ctx->pmq);
int i;
for (i = 0; i < DETECT_SMSG_PMQ_NUM; i++) {
PmqFree(&det_ctx->smsg_pmq[i]);
}
if (det_ctx->non_mpm_id_array != NULL)
SCFree(det_ctx->non_mpm_id_array);
if (det_ctx->de_state_sig_array != NULL)
SCFree(det_ctx->de_state_sig_array);
if (det_ctx->match_array != NULL)
SCFree(det_ctx->match_array);
if (det_ctx->bj_values != NULL)
SCFree(det_ctx->bj_values);
/* HHD temp storage */
for (i = 0; i < det_ctx->hhd_buffers_size; i++) {
if (det_ctx->hhd_buffers[i] != NULL)
SCFree(det_ctx->hhd_buffers[i]);
}
if (det_ctx->hhd_buffers)
SCFree(det_ctx->hhd_buffers);
det_ctx->hhd_buffers = NULL;
if (det_ctx->hhd_buffers_len)
SCFree(det_ctx->hhd_buffers_len);
det_ctx->hhd_buffers_len = NULL;
/* HSBD */
if (det_ctx->hsbd != NULL) {
SCLogDebug("det_ctx hsbd %u", det_ctx->hsbd_buffers_size);
for (i = 0; i < det_ctx->hsbd_buffers_size; i++) {
if (det_ctx->hsbd[i].buffer != NULL) {
HTPFree(det_ctx->hsbd[i].buffer, det_ctx->hsbd[i].buffer_size);
}
}
SCFree(det_ctx->hsbd);
}
/* HSCB */
if (det_ctx->hcbd != NULL) {
SCLogDebug("det_ctx hcbd %u", det_ctx->hcbd_buffers_size);
for (i = 0; i < det_ctx->hcbd_buffers_size; i++) {
if (det_ctx->hcbd[i].buffer != NULL)
SCFree(det_ctx->hcbd[i].buffer);
SCLogDebug("det_ctx->hcbd[i].buffer_size %u", det_ctx->hcbd[i].buffer_size);
}
SCFree(det_ctx->hcbd);
}
if (det_ctx->de_ctx != NULL) {
DetectEngineThreadCtxDeinitKeywords(det_ctx->de_ctx, det_ctx);
#ifdef UNITTESTS
if (!RunmodeIsUnittests() || det_ctx->de_ctx->ref_cnt > 0)
DetectEngineDeReference(&det_ctx->de_ctx);
#else
DetectEngineDeReference(&det_ctx->de_ctx);
#endif
}
SCFree(det_ctx);
}
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
{
DetectEngineThreadCtx *det_ctx = (DetectEngineThreadCtx *)data;
if (det_ctx == NULL) {
SCLogWarning(SC_ERR_INVALID_ARGUMENTS, "argument \"data\" NULL");
return TM_ECODE_OK;
}
if (det_ctx->mt_det_ctxs_hash != NULL) {
HashTableFree(det_ctx->mt_det_ctxs_hash);
det_ctx->mt_det_ctxs_hash = NULL;
}
DetectEngineThreadCtxFree(det_ctx);
16 years ago
return TM_ECODE_OK;
16 years ago
}
void DetectEngineThreadCtxInfo(ThreadVars *t, DetectEngineThreadCtx *det_ctx)
{
16 years ago
/* XXX */
PatternMatchThreadPrint(&det_ctx->mtc, det_ctx->de_ctx->mpm_matcher);
PatternMatchThreadPrint(&det_ctx->mtcu, det_ctx->de_ctx->mpm_matcher);
16 years ago
}
/** \brief Register Thread keyword context Funcs
*
* \param de_ctx detection engine to register in
* \param name keyword name for error printing
* \param InitFunc function ptr
* \param data keyword init data to pass to Func
* \param FreeFunc function ptr
* \param mode 0 normal (ctx per keyword instance) 1 shared (one ctx per det_ct)
*
* \retval id for retrieval of ctx at runtime
* \retval -1 on error
*
* \note make sure "data" remains valid and it free'd elsewhere. It's
* recommended to store it in the keywords global ctx so that
* it's freed when the de_ctx is freed.
*/
int DetectRegisterThreadCtxFuncs(DetectEngineCtx *de_ctx, const char *name, void *(*InitFunc)(void *), void *data, void (*FreeFunc)(void *), int mode)
{
BUG_ON(de_ctx == NULL || InitFunc == NULL || FreeFunc == NULL || data == NULL);
if (mode) {
DetectEngineThreadKeywordCtxItem *item = de_ctx->keyword_list;
while (item != NULL) {
if (strcmp(name, item->name) == 0) {
return item->id;
}
item = item->next;
}
}
DetectEngineThreadKeywordCtxItem *item = SCMalloc(sizeof(DetectEngineThreadKeywordCtxItem));
if (unlikely(item == NULL))
return -1;
memset(item, 0x00, sizeof(DetectEngineThreadKeywordCtxItem));
item->InitFunc = InitFunc;
item->FreeFunc = FreeFunc;
item->data = data;
item->name = name;
item->next = de_ctx->keyword_list;
de_ctx->keyword_list = item;
item->id = de_ctx->keyword_id++;
return item->id;
}
/** \brief Retrieve thread local keyword ctx by id
*
* \param det_ctx detection engine thread ctx to retrieve the ctx from
* \param id id of the ctx returned by DetectRegisterThreadCtxInitFunc at
* keyword init.
*
* \retval ctx or NULL on error
*/
void *DetectThreadCtxGetKeywordThreadCtx(DetectEngineThreadCtx *det_ctx, int id)
{
if (id < 0 || id > det_ctx->keyword_ctxs_size || det_ctx->keyword_ctxs_array == NULL)
return NULL;
return det_ctx->keyword_ctxs_array[id];
}
/** \brief Check if detection is enabled
* \retval bool true or false */
int DetectEngineEnabled(void)
{
DetectEngineMasterCtx *master = &g_master_de_ctx;
SCMutexLock(&master->lock);
if (master->list == NULL) {
SCMutexUnlock(&master->lock);
return 0;
}
SCMutexUnlock(&master->lock);
return 1;
}
DetectEngineCtx *DetectEngineGetCurrent(void)
{
DetectEngineMasterCtx *master = &g_master_de_ctx;
SCMutexLock(&master->lock);
if (master->list == NULL) {
SCMutexUnlock(&master->lock);
return NULL;
}
master->list->ref_cnt++;
SCLogDebug("master->list %p ref_cnt %u", master->list, master->list->ref_cnt);
SCMutexUnlock(&master->lock);
return master->list;
}
DetectEngineCtx *DetectEngineReference(DetectEngineCtx *de_ctx)
{
if (de_ctx == NULL)
return NULL;
de_ctx->ref_cnt++;
return de_ctx;
}
/** TODO locking? Not needed if this is a one time setting at startup */
int DetectEngineMultiTenantEnabled(void)
{
DetectEngineMasterCtx *master = &g_master_de_ctx;
return (master->multi_tenant_enabled);
}
/** \brief load a tenant from a yaml file
*
* \param tenant_id the tenant id by which the config is known
* \param filename full path of a yaml file
*
* \retval 0 ok
* \retval -1 failed
*/
int DetectEngineMultiTenantLoadTenant(uint32_t tenant_id, const char *filename)
{
DetectEngineCtx *de_ctx = NULL;
char prefix[64];
snprintf(prefix, sizeof(prefix), "multi-detect.%d", tenant_id);
#ifdef OS_WIN32
struct _stat st;
if(_stat(filename, &st) != 0) {
#else
struct stat st;
if(stat(filename, &st) != 0) {
#endif /* OS_WIN32 */
SCLogError(SC_ERR_FOPEN, "failed to stat file %s", filename);
goto error;
}
de_ctx = DetectEngineGetByTenantId(tenant_id);
if (de_ctx != NULL) {
SCLogError(SC_ERR_MT_DUPLICATE_TENANT, "tenant %u already registered",
tenant_id);
DetectEngineDeReference(&de_ctx);
goto error;
}
if (ConfYamlLoadFileWithPrefix(filename, prefix) != 0) {
SCLogError(SC_ERR_CONF_YAML_ERROR, "failed to load yaml %s", filename);
goto error;
}
ConfNode *node = ConfGetNode(prefix);
if (node == NULL) {
SCLogError(SC_ERR_CONF_YAML_ERROR, "failed to properly setup yaml %s", filename);
goto error;
}
de_ctx = DetectEngineCtxInitWithPrefix(prefix);
if (de_ctx == NULL) {
SCLogError(SC_ERR_INITIALIZATION, "initializing detection engine "
"context failed.");
goto error;
}
SCLogDebug("de_ctx %p with prefix %s", de_ctx, de_ctx->config_prefix);
de_ctx->tenant_id = tenant_id;
if (SigLoadSignatures(de_ctx, NULL, 0) < 0) {
SCLogError(SC_ERR_NO_RULES_LOADED, "Loading signatures failed.");
goto error;
}
DetectEngineAddToMaster(de_ctx);
return 0;
error:
if (de_ctx != NULL) {
DetectEngineCtxFree(de_ctx);
}
return -1;
}
/**
* \brief setup multi-detect / multi-tenancy
*
* See if MT is enabled. If so, setup the selector, tenants and mappings.
* Tenants and mappings are optional, and can also dynamically be added
* and removed from the unix socket.
*/
void DetectEngineMultiTenantSetup(void)
{
DetectEngineMasterCtx *master = &g_master_de_ctx;
int failure_fatal = 0;
(void)ConfGetBool("engine.init-failure-fatal", &failure_fatal);
int enabled = 0;
(void)ConfGetBool("multi-detect.enabled", &enabled);
if (enabled == 1) {
SCMutexLock(&master->lock);
master->multi_tenant_enabled = 1;
char *handler = NULL;
if (ConfGet("multi-detect.selector", &handler) == 1) {
SCLogInfo("selector %s", handler);
if (strcmp(handler, "vlan") == 0) {
master->tenant_selector = TENANT_SELECTOR_VLAN;
} else if (strcmp(handler, "direct") == 0) {
master->tenant_selector = TENANT_SELECTOR_DIRECT;
} else {
SCLogError(SC_ERR_INVALID_VALUE, "unknown value %s "
"multi-detect.selector", handler);
SCMutexUnlock(&master->lock);
goto error;
}
}
SCMutexUnlock(&master->lock);
SCLogInfo("multi-detect is enabled (multi tenancy). Selector: %s", handler);
/* traffic -- tenant mappings */
ConfNode *mappings_root_node = ConfGetNode("multi-detect.mappings");
ConfNode *mapping_node = NULL;
if (mappings_root_node != NULL) {
TAILQ_FOREACH(mapping_node, &mappings_root_node->head, next) {
if (strcmp(mapping_node->val, "vlan") == 0) {
ConfNode *tenant_id_node = ConfNodeLookupChild(mapping_node, "tenant-id");
if (tenant_id_node == NULL)
goto bad_mapping;
ConfNode *vlan_id_node = ConfNodeLookupChild(mapping_node, "vlan-id");
if (vlan_id_node == NULL)
goto bad_mapping;
SCLogInfo("vlan %s %s", tenant_id_node->val, vlan_id_node->val);
uint32_t tenant_id = 0;
if (ByteExtractStringUint32(&tenant_id, 10, strlen(tenant_id_node->val),
tenant_id_node->val) == -1)
{
SCLogError(SC_ERR_INVALID_ARGUMENT, "tenant-id "
"of %s is invalid", tenant_id_node->val);
goto bad_mapping;
}
uint16_t vlan_id = 0;
if (ByteExtractStringUint16(&vlan_id, 10, strlen(vlan_id_node->val),
vlan_id_node->val) == -1)
{
SCLogError(SC_ERR_INVALID_ARGUMENT, "vlan-id "
"of %s is invalid", vlan_id_node->val);
goto bad_mapping;
}
if (DetectEngineTentantRegisterVlanId(tenant_id, (uint32_t)vlan_id) != 0) {
goto error;
}
} else {
SCLogWarning(SC_ERR_INVALID_VALUE, "multi-detect.mappings expects a list of 'vlan's. Not %s", mapping_node->val);
goto bad_mapping;
}
continue;
bad_mapping:
if (failure_fatal)
goto error;
}
}
/* tenants */
ConfNode *tenants_root_node = ConfGetNode("multi-detect.tenants");
ConfNode *tenant_node = NULL;
if (tenants_root_node != NULL) {
TAILQ_FOREACH(tenant_node, &tenants_root_node->head, next) {
if (strcmp(tenant_node->val, "tenant") != 0) {
SCLogWarning(SC_ERR_INVALID_VALUE, "multi-detect.tenants expects a list of 'tenant's. Not %s", tenant_node->val);
goto bad_tenant;
}
ConfNode *id_node = ConfNodeLookupChild(tenant_node, "id");
if (id_node == NULL)
goto bad_tenant;
ConfNode *yaml_node = ConfNodeLookupChild(tenant_node, "yaml");
if (yaml_node == NULL)
goto bad_tenant;
uint32_t tenant_id = 0;
if (ByteExtractStringUint32(&tenant_id, 10, strlen(id_node->val),
id_node->val) == -1)
{
SCLogError(SC_ERR_INVALID_ARGUMENT, "tenant_id "
"of %s is invalid", id_node->val);
goto bad_tenant;
}
SCLogInfo("tenant id: %u, %s", tenant_id, yaml_node->val);
if (DetectEngineMultiTenantLoadTenant(tenant_id, yaml_node->val) != 0) {
/* error logged already */
goto bad_tenant;
}
continue;
bad_tenant:
if (failure_fatal)
goto error;
}
}
if (DetectEngineMTApply() < 0) {
SCLogError(SC_ERR_DETECT_PREPARE, "initializing the detection engine failed");
goto error;
}
} else {
SCLogDebug("multi-detect not enabled (multi tenancy)");
}
error:
return;
}
uint32_t DetectEngineTentantGetIdFromVlanId(const void *ctx, const Packet *p)
{
const DetectEngineThreadCtx *det_ctx = ctx;
uint32_t x = 0;
uint32_t vlan_id = 0;
if (p->vlan_idx == 0)
return 0;
vlan_id = p->vlan_id[0];
if (det_ctx == NULL || det_ctx->tenant_array == NULL || det_ctx->tenant_array_size == 0)
return 0;
/* not very efficient, but for now we're targeting only limited amounts.
* Can use hash/tree approach later. */
for (x = 0; x < det_ctx->tenant_array_size; x++) {
if (det_ctx->tenant_array[x].traffic_id == vlan_id)
return det_ctx->tenant_array[x].tenant_id;
}
return 0;
}
static int DetectEngineTentantRegisterSelector(enum DetectEngineTenantSelectors selector,
uint32_t tenant_id, uint32_t traffic_id)
{
DetectEngineMasterCtx *master = &g_master_de_ctx;
SCMutexLock(&master->lock);
if (!(master->tenant_selector == TENANT_SELECTOR_UNKNOWN || master->tenant_selector == selector)) {
SCLogInfo("conflicting selector already set");
SCMutexUnlock(&master->lock);
return -1;
}
DetectEngineTenantMapping *m = master->tenant_mapping_list;
while (m) {
if (m->traffic_id == traffic_id) {
SCLogInfo("traffic id already registered");
SCMutexUnlock(&master->lock);
return -1;
}
m = m->next;
}
DetectEngineTenantMapping *map = SCCalloc(1, sizeof(*map));
if (map == NULL) {
SCLogInfo("memory fail");
SCMutexUnlock(&master->lock);
return -1;
}
map->traffic_id = traffic_id;
map->tenant_id = tenant_id;
map->next = master->tenant_mapping_list;
master->tenant_mapping_list = map;
master->tenant_selector = selector;
SCLogInfo("tenant handler %u %u %u registered", selector, tenant_id, traffic_id);
SCMutexUnlock(&master->lock);
return 0;
}
static int DetectEngineTentantUnregisterSelector(enum DetectEngineTenantSelectors selector,
uint32_t tenant_id, uint32_t traffic_id)
{
DetectEngineMasterCtx *master = &g_master_de_ctx;
SCMutexLock(&master->lock);
if (master->tenant_mapping_list == NULL) {
SCMutexUnlock(&master->lock);
return -1;
}
DetectEngineTenantMapping *prev = NULL;
DetectEngineTenantMapping *map = master->tenant_mapping_list;
while (map) {
if (map->traffic_id == traffic_id &&
map->tenant_id == tenant_id)
{
if (prev != NULL)
prev->next = map->next;
else
master->tenant_mapping_list = map->next;
map->next = NULL;
SCFree(map);
SCLogInfo("tenant handler %u %u %u unregistered", selector, tenant_id, traffic_id);
SCMutexUnlock(&master->lock);
return 0;
}
prev = map;
map = map->next;
}
SCMutexUnlock(&master->lock);
return -1;
}
int DetectEngineTentantRegisterVlanId(uint32_t tenant_id, uint16_t vlan_id)
{
return DetectEngineTentantRegisterSelector(TENANT_SELECTOR_VLAN, tenant_id, (uint32_t)vlan_id);
}
int DetectEngineTentantUnregisterVlanId(uint32_t tenant_id, uint16_t vlan_id)
{
return DetectEngineTentantUnregisterSelector(TENANT_SELECTOR_VLAN, tenant_id, (uint32_t)vlan_id);
}
int DetectEngineTentantRegisterPcapFile(uint32_t tenant_id)
{
SCLogInfo("registering %u %d 0", TENANT_SELECTOR_DIRECT, tenant_id);
return DetectEngineTentantRegisterSelector(TENANT_SELECTOR_DIRECT, tenant_id, 0);
}
int DetectEngineTentantUnregisterPcapFile(uint32_t tenant_id)
{
SCLogInfo("unregistering %u %d 0", TENANT_SELECTOR_DIRECT, tenant_id);
return DetectEngineTentantUnregisterSelector(TENANT_SELECTOR_DIRECT, tenant_id, 0);
}
uint32_t DetectEngineTentantGetIdFromPcap(const void *ctx, const Packet *p)
{
return p->pcap_v.tenant_id;
}
DetectEngineCtx *DetectEngineGetByTenantId(int tenant_id)
{
DetectEngineMasterCtx *master = &g_master_de_ctx;
SCMutexLock(&master->lock);
if (master->list == NULL) {
SCMutexUnlock(&master->lock);
return NULL;
}
DetectEngineCtx *de_ctx = master->list;
while (de_ctx) {
if (de_ctx->tenant_id == tenant_id) {
de_ctx->ref_cnt++;
break;
}
de_ctx = de_ctx->next;
}
SCMutexUnlock(&master->lock);
return de_ctx;
}
void DetectEngineDeReference(DetectEngineCtx **de_ctx)
{
BUG_ON((*de_ctx)->ref_cnt == 0);
(*de_ctx)->ref_cnt--;
*de_ctx = NULL;
}
static int DetectEngineAddToList(DetectEngineCtx *instance)
{
DetectEngineMasterCtx *master = &g_master_de_ctx;
if (instance == NULL)
return -1;
if (master->list == NULL) {
master->list = instance;
} else {
instance->next = master->list;
master->list = instance;
}
return 0;
}
int DetectEngineAddToMaster(DetectEngineCtx *de_ctx)
{
int r;
if (de_ctx == NULL)
return -1;
SCLogDebug("adding de_ctx %p to master", de_ctx);
DetectEngineMasterCtx *master = &g_master_de_ctx;
SCMutexLock(&master->lock);
r = DetectEngineAddToList(de_ctx);
SCMutexUnlock(&master->lock);
return r;
}
int DetectEngineMoveToFreeList(DetectEngineCtx *de_ctx)
{
DetectEngineMasterCtx *master = &g_master_de_ctx;
SCMutexLock(&master->lock);
DetectEngineCtx *instance = master->list;
if (instance == NULL) {
SCMutexUnlock(&master->lock);
return -1;
}
/* remove from active list */
if (instance == de_ctx) {
master->list = instance->next;
} else {
DetectEngineCtx *prev = instance;
instance = instance->next; /* already checked first element */
while (instance) {
DetectEngineCtx *next = instance->next;
if (instance == de_ctx) {
prev->next = instance->next;
break;
}
prev = instance;
instance = next;
}
if (instance == NULL) {
SCMutexUnlock(&master->lock);
return -1;
}
}
/* instance is now detached from list */
instance->next = NULL;
/* add to free list */
if (master->free_list == NULL) {
master->free_list = instance;
} else {
instance->next = master->free_list;
master->free_list = instance;
}
SCLogDebug("detect engine %p moved to free list (%u refs)", de_ctx, de_ctx->ref_cnt);
SCMutexUnlock(&master->lock);
return 0;
}
void DetectEnginePruneFreeList(void)
{
DetectEngineMasterCtx *master = &g_master_de_ctx;
SCMutexLock(&master->lock);
DetectEngineCtx *prev = NULL;
DetectEngineCtx *instance = master->free_list;
while (instance) {
DetectEngineCtx *next = instance->next;
SCLogDebug("detect engine %p has %u ref(s)", instance, instance->ref_cnt);
if (instance->ref_cnt == 0) {
if (prev == NULL) {
master->free_list = next;
} else {
prev->next = next;
}
SCLogDebug("freeing detect engine %p", instance);
DetectEngineCtxFree(instance);
instance = NULL;
}
prev = instance;
instance = next;
}
SCMutexUnlock(&master->lock);
}
static int reloads = 0;
/** \brief Reload the detection engine
*
* \param filename YAML file to load for the detect config
*
* \retval -1 error
* \retval 0 ok
*/
int DetectEngineReload(const char *filename)
{
DetectEngineCtx *new_de_ctx = NULL;
DetectEngineCtx *old_de_ctx = NULL;
char prefix[128] = "";
if (filename != NULL) {
snprintf(prefix, sizeof(prefix), "detect-engine-reloads.%d", reloads++);
if (ConfYamlLoadFileWithPrefix(filename, prefix) != 0) {
SCLogError(SC_ERR_CONF_YAML_ERROR, "failed to load yaml %s", filename);
return -1;
}
ConfNode *node = ConfGetNode(prefix);
if (node == NULL) {
SCLogError(SC_ERR_CONF_YAML_ERROR, "failed to properly setup yaml %s", filename);
return -1;
}
#if 0
ConfDump();
#endif
}
/* get a reference to the current de_ctx */
old_de_ctx = DetectEngineGetCurrent();
if (old_de_ctx == NULL)
return -1;
SCLogDebug("get ref to old_de_ctx %p", old_de_ctx);
/* get new detection engine */
new_de_ctx = DetectEngineCtxInitWithPrefix(prefix);
if (new_de_ctx == NULL) {
SCLogError(SC_ERR_INITIALIZATION, "initializing detection engine "
"context failed.");
DetectEngineDeReference(&old_de_ctx);
return -1;
}
if (SigLoadSignatures(new_de_ctx, NULL, 0) != 0) {
DetectEngineCtxFree(new_de_ctx);
DetectEngineDeReference(&old_de_ctx);
return -1;
}
SCThresholdConfInitContext(new_de_ctx, NULL);
SCLogDebug("set up new_de_ctx %p", new_de_ctx);
/* add to master */
DetectEngineAddToMaster(new_de_ctx);
/* move to old free list */
DetectEngineMoveToFreeList(old_de_ctx);
DetectEngineDeReference(&old_de_ctx);
SCLogDebug("going to reload the threads to use new_de_ctx %p", new_de_ctx);
/* update the threads */
DetectEngineReloadThreads(new_de_ctx);
SCLogDebug("threads now run new_de_ctx %p", new_de_ctx);
/* walk free list, freeing the old_de_ctx */
DetectEnginePruneFreeList();
SCLogDebug("old_de_ctx should have been freed");
return 0;
}
static uint32_t TenantIdHash(HashTable *h, void *data, uint16_t data_len)
{
DetectEngineThreadCtx *det_ctx = (DetectEngineThreadCtx *)data;
return det_ctx->tenant_id % h->array_size;
}
static char TenantIdCompare(void *d1, uint16_t d1_len, void *d2, uint16_t d2_len)
{
DetectEngineThreadCtx *det1 = (DetectEngineThreadCtx *)d1;
DetectEngineThreadCtx *det2 = (DetectEngineThreadCtx *)d2;
return (det1->tenant_id == det2->tenant_id);
}
static void TenantIdFree(void *d)
{
DetectEngineThreadCtxFree(d);
}
/** NOTE: master MUST be locked before calling this */
static DetectEngineThreadCtx *DetectEngineThreadCtxInitForMT(ThreadVars *tv)
{
DetectEngineMasterCtx *master = &g_master_de_ctx;
DetectEngineTenantMapping *map_array = NULL;
uint32_t map_array_size = 0;
uint32_t map_cnt = 0;
int max_tenant_id = 0;
DetectEngineCtx *list = master->list;
if (master->tenant_selector == TENANT_SELECTOR_UNKNOWN) {
SCLogError(SC_ERR_MT_NO_SELECTOR, "no tenant selector set: "
"set using multi-detect.selector");
return NULL;
}
uint32_t tcnt = 0;
while (list) {
if (list->tenant_id > max_tenant_id)
max_tenant_id = list->tenant_id;
list = list->next;
tcnt++;
}
HashTable *mt_det_ctxs_hash = HashTableInit(tcnt * 2, TenantIdHash, TenantIdCompare, TenantIdFree);
BUG_ON(mt_det_ctxs_hash == NULL);
if (max_tenant_id == 0) {
SCLogInfo("no tenants left, or none registered yet");
} else {
max_tenant_id++;
DetectEngineTenantMapping *map = master->tenant_mapping_list;
while (map) {
map_cnt++;
map = map->next;
}
if (map_cnt > 0) {
map_array_size = map_cnt + 1;
map_array = SCCalloc(map_array_size, sizeof(*map_array));
if (map_array == NULL)
goto error;
/* fill the array */
map_cnt = 0;
map = master->tenant_mapping_list;
while (map) {
BUG_ON(map_cnt > map_array_size);
map_array[map_cnt].traffic_id = map->traffic_id;
map_array[map_cnt].tenant_id = map->tenant_id;
map_cnt++;
map = map->next;
}
}
/* set up hash for tenant lookup */
list = master->list;
while (list) {
if (list->tenant_id != 0) {
DetectEngineThreadCtx *mt_det_ctx = DetectEngineThreadCtxInitForReload(tv, list);
if (mt_det_ctx == NULL)
goto error;
BUG_ON(HashTableAdd(mt_det_ctxs_hash, mt_det_ctx, 0) != 0);
}
list = list->next;
}
}
DetectEngineThreadCtx *det_ctx = SCCalloc(1, sizeof(DetectEngineThreadCtx));
if (det_ctx == NULL) {
goto error;
}
det_ctx->mt_det_ctxs_hash = mt_det_ctxs_hash;
/* first register the counter. In delayed detect mode we exit right after if the
* rules haven't been loaded yet. */
uint16_t counter_alerts = StatsRegisterCounter("detect.alert", tv);
#ifdef PROFILING
uint16_t counter_mpm_list = StatsRegisterAvgCounter("detect.mpm_list", tv);
uint16_t counter_nonmpm_list = StatsRegisterAvgCounter("detect.nonmpm_list", tv);
uint16_t counter_fnonmpm_list = StatsRegisterAvgCounter("detect.fnonmpm_list", tv);
uint16_t counter_match_list = StatsRegisterAvgCounter("detect.match_list", tv);
#endif
/** alert counter setup */
det_ctx->counter_alerts = counter_alerts;
#ifdef PROFILING
det_ctx->counter_mpm_list = counter_mpm_list;
det_ctx->counter_nonmpm_list = counter_nonmpm_list;
det_ctx->counter_fnonmpm_list = counter_fnonmpm_list;
det_ctx->counter_match_list = counter_match_list;
#endif
det_ctx->mt_det_ctxs_cnt = max_tenant_id;
det_ctx->tenant_array = map_array;
det_ctx->tenant_array_size = map_array_size;
switch (master->tenant_selector) {
case TENANT_SELECTOR_UNKNOWN:
SCLogDebug("TENANT_SELECTOR_UNKNOWN");
break;
case TENANT_SELECTOR_VLAN:
det_ctx->TenantGetId = DetectEngineTentantGetIdFromVlanId;
SCLogDebug("TENANT_SELECTOR_VLAN");
break;
case TENANT_SELECTOR_DIRECT:
det_ctx->TenantGetId = DetectEngineTentantGetIdFromPcap;
SCLogDebug("TENANT_SELECTOR_DIRECT");
break;
}
return det_ctx;
error:
return NULL;
}
int DetectEngineMTApply(void)
{
DetectEngineMasterCtx *master = &g_master_de_ctx;
SCMutexLock(&master->lock);
if (master->tenant_selector == TENANT_SELECTOR_UNKNOWN) {
SCLogInfo("error, no tenant selector");
SCMutexUnlock(&master->lock);
return -1;
}
DetectEngineCtx *minimal_de_ctx = NULL;
/* if we have no tenants, we need a minimal on */
if (master->list == NULL) {
minimal_de_ctx = master->list = DetectEngineCtxInitMinimal();
SCLogDebug("no tenants, using minimal %p", minimal_de_ctx);
} else if (master->list->next == NULL && master->list->tenant_id == 0) {
minimal_de_ctx = master->list;
SCLogDebug("no tenants, using original %p", minimal_de_ctx);
}
/* update the threads */
SCLogDebug("MT reload starting");
DetectEngineReloadThreads(minimal_de_ctx);
SCLogDebug("MT reload done");
SCMutexUnlock(&master->lock);
/* walk free list, freeing the old_de_ctx */
DetectEnginePruneFreeList();
SCLogDebug("old_de_ctx should have been freed");
return 0;
}
const char *DetectSigmatchListEnumToString(enum DetectSigmatchListEnum type)
{
switch (type) {
case DETECT_SM_LIST_MATCH:
return "packet";
case DETECT_SM_LIST_PMATCH:
return "packet/stream payload";
case DETECT_SM_LIST_UMATCH:
return "http uri";
case DETECT_SM_LIST_HRUDMATCH:
return "http raw uri";
case DETECT_SM_LIST_HCBDMATCH:
return "http client body";
case DETECT_SM_LIST_FILEDATA:
return "http server body";
case DETECT_SM_LIST_HHDMATCH:
return "http headers";
case DETECT_SM_LIST_HRHDMATCH:
return "http raw headers";
case DETECT_SM_LIST_HSMDMATCH:
return "http stat msg";
case DETECT_SM_LIST_HSCDMATCH:
return "http stat code";
case DETECT_SM_LIST_HHHDMATCH:
return "http host";
case DETECT_SM_LIST_HRHHDMATCH:
return "http raw host header";
case DETECT_SM_LIST_HMDMATCH:
return "http method";
case DETECT_SM_LIST_HCDMATCH:
return "http cookie";
case DETECT_SM_LIST_HUADMATCH:
return "http user-agent";
case DETECT_SM_LIST_HRLMATCH:
return "http request line";
case DETECT_SM_LIST_APP_EVENT:
return "app layer events";
case DETECT_SM_LIST_AMATCH:
return "generic app layer";
case DETECT_SM_LIST_DMATCH:
return "dcerpc";
case DETECT_SM_LIST_TMATCH:
return "tag";
case DETECT_SM_LIST_FILEMATCH:
return "file";
case DETECT_SM_LIST_DNSQUERYNAME_MATCH:
return "dns query name";
case DETECT_SM_LIST_DNSREQUEST_MATCH:
return "dns request";
case DETECT_SM_LIST_DNSRESPONSE_MATCH:
return "dns response";
case DETECT_SM_LIST_MODBUS_MATCH:
return "modbus";
case DETECT_SM_LIST_POSTMATCH:
return "post-match";
case DETECT_SM_LIST_SUPPRESS:
return "suppress";
case DETECT_SM_LIST_THRESHOLD:
return "threshold";
case DETECT_SM_LIST_MAX:
return "max (internal)";
case DETECT_SM_LIST_NOTSET:
return "not set (internal)";
}
return "error";
}
/*************************************Unittest*********************************/
#ifdef UNITTESTS
static int DetectEngineInitYamlConf(char *conf)
{
ConfCreateContextBackup();
ConfInit();
return ConfYamlLoadString(conf, strlen(conf));
}
static void DetectEngineDeInitYamlConf(void)
{
ConfDeInit();
ConfRestoreContextBackup();
return;
}
static int DetectEngineTest01(void)
{
char *conf =
"%YAML 1.1\n"
"---\n"
"detect-engine:\n"
" - profile: medium\n"
" - custom-values:\n"
" toclient_src_groups: 2\n"
" toclient_dst_groups: 2\n"
" toclient_sp_groups: 2\n"
" toclient_dp_groups: 3\n"
" toserver_src_groups: 2\n"
" toserver_dst_groups: 4\n"
" toserver_sp_groups: 2\n"
" toserver_dp_groups: 25\n"
" - inspection-recursion-limit: 0\n";
DetectEngineCtx *de_ctx = NULL;
int result = 0;
if (DetectEngineInitYamlConf(conf) == -1)
return 0;
de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
result = (de_ctx->inspection_recursion_limit == -1);
end:
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
DetectEngineDeInitYamlConf();
return result;
}
static int DetectEngineTest02(void)
{
char *conf =
"%YAML 1.1\n"
"---\n"
"detect-engine:\n"
" - profile: medium\n"
" - custom-values:\n"
" toclient_src_groups: 2\n"
" toclient_dst_groups: 2\n"
" toclient_sp_groups: 2\n"
" toclient_dp_groups: 3\n"
" toserver_src_groups: 2\n"
" toserver_dst_groups: 4\n"
" toserver_sp_groups: 2\n"
" toserver_dp_groups: 25\n"
" - inspection-recursion-limit:\n";
DetectEngineCtx *de_ctx = NULL;
int result = 0;
if (DetectEngineInitYamlConf(conf) == -1)
return 0;
de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
result = (de_ctx->inspection_recursion_limit == -1);
end:
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
DetectEngineDeInitYamlConf();
return result;
}
static int DetectEngineTest03(void)
{
char *conf =
"%YAML 1.1\n"
"---\n"
"detect-engine:\n"
" - profile: medium\n"
" - custom-values:\n"
" toclient_src_groups: 2\n"
" toclient_dst_groups: 2\n"
" toclient_sp_groups: 2\n"
" toclient_dp_groups: 3\n"
" toserver_src_groups: 2\n"
" toserver_dst_groups: 4\n"
" toserver_sp_groups: 2\n"
" toserver_dp_groups: 25\n";
DetectEngineCtx *de_ctx = NULL;
int result = 0;
if (DetectEngineInitYamlConf(conf) == -1)
return 0;
de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
result = (de_ctx->inspection_recursion_limit ==
DETECT_ENGINE_DEFAULT_INSPECTION_RECURSION_LIMIT);
end:
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
DetectEngineDeInitYamlConf();
return result;
}
static int DetectEngineTest04(void)
{
char *conf =
"%YAML 1.1\n"
"---\n"
"detect-engine:\n"
" - profile: medium\n"
" - custom-values:\n"
" toclient_src_groups: 2\n"
" toclient_dst_groups: 2\n"
" toclient_sp_groups: 2\n"
" toclient_dp_groups: 3\n"
" toserver_src_groups: 2\n"
" toserver_dst_groups: 4\n"
" toserver_sp_groups: 2\n"
" toserver_dp_groups: 25\n"
" - inspection-recursion-limit: 10\n";
DetectEngineCtx *de_ctx = NULL;
int result = 0;
if (DetectEngineInitYamlConf(conf) == -1)
return 0;
de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
result = (de_ctx->inspection_recursion_limit == 10);
end:
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
DetectEngineDeInitYamlConf();
return result;
}
int DummyTestAppInspectionEngine01(ThreadVars *tv,
DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx,
Signature *sig,
Flow *f,
uint8_t flags,
void *alstate,
void *tx, uint64_t tx_id)
{
return 0;
}
int DummyTestAppInspectionEngine02(ThreadVars *tv,
DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx,
Signature *sig,
Flow *f,
uint8_t flags,
void *alstate,
void *tx, uint64_t tx_id)
{
return 0;
}
int DetectEngineTest05(void)
{
int result = 0;
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
int ip = 0;
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
DetectEngineAppInspectionEngine *engine_list[FLOW_PROTO_DEFAULT][ALPROTO_MAX][2];
memset(engine_list, 0, sizeof(engine_list));
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
DetectEngineRegisterAppInspectionEngine(IPPROTO_TCP,
ALPROTO_HTTP,
0 /* STREAM_TOSERVER */,
DETECT_SM_LIST_UMATCH,
DE_STATE_FLAG_URI_INSPECT,
DummyTestAppInspectionEngine01,
engine_list);
int alproto = ALPROTO_UNKNOWN + 1;
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
for (ip = 0; ip < FLOW_PROTO_DEFAULT; ip++) {
for ( ; alproto < ALPROTO_FAILED; alproto++) {
int dir = 0;
for ( ; dir < 2; dir++) {
if (alproto == ALPROTO_HTTP && dir == 0) {
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
if (engine_list[ip][alproto][dir]->next != NULL) {
printf("more than one entry found\n");
goto end;
}
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
DetectEngineAppInspectionEngine *engine = engine_list[ip][alproto][dir];
if (engine->alproto != alproto ||
engine->dir != dir ||
engine->sm_list != DETECT_SM_LIST_UMATCH ||
engine->inspect_flags != DE_STATE_FLAG_URI_INSPECT ||
engine->Callback != DummyTestAppInspectionEngine01) {
printf("failed for http and dir(0-toserver)\n");
goto end;
}
} /* if (alproto == ALPROTO_HTTP && dir == 0) */
if (alproto == ALPROTO_HTTP && dir == 1) {
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
if (engine_list[ip][alproto][dir] != NULL) {
printf("failed for http and dir(1-toclient)\n");
goto end;
}
}
if (alproto != ALPROTO_HTTP &&
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
engine_list[ip][alproto][0] != NULL &&
engine_list[ip][alproto][1] != NULL) {
printf("failed for protocol %d\n", alproto);
goto end;
}
} /* for ( ; dir < 2 ..)*/
} /* for ( ; alproto < ALPROTO_FAILED; ..) */
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
}
result = 1;
end:
return result;
}
int DetectEngineTest06(void)
{
int result = 0;
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
int ip = 0;
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
DetectEngineAppInspectionEngine *engine_list[FLOW_PROTO_DEFAULT][ALPROTO_MAX][2];
memset(engine_list, 0, sizeof(engine_list));
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
DetectEngineRegisterAppInspectionEngine(IPPROTO_TCP,
ALPROTO_HTTP,
0 /* STREAM_TOSERVER */,
DETECT_SM_LIST_UMATCH,
DE_STATE_FLAG_URI_INSPECT,
DummyTestAppInspectionEngine01,
engine_list);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
DetectEngineRegisterAppInspectionEngine(IPPROTO_TCP,
ALPROTO_HTTP,
1 /* STREAM_TOCLIENT */,
DETECT_SM_LIST_UMATCH,
DE_STATE_FLAG_URI_INSPECT,
DummyTestAppInspectionEngine02,
engine_list);
int alproto = ALPROTO_UNKNOWN + 1;
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
for (ip = 0; ip < FLOW_PROTO_DEFAULT; ip++) {
for ( ; alproto < ALPROTO_FAILED; alproto++) {
int dir = 0;
for ( ; dir < 2; dir++) {
if (alproto == ALPROTO_HTTP && dir == 0) {
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
if (engine_list[ip][alproto][dir]->next != NULL) {
printf("more than one entry found\n");
goto end;
}
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
DetectEngineAppInspectionEngine *engine = engine_list[ip][alproto][dir];
if (engine->alproto != alproto ||
engine->dir != dir ||
engine->sm_list != DETECT_SM_LIST_UMATCH ||
engine->inspect_flags != DE_STATE_FLAG_URI_INSPECT ||
engine->Callback != DummyTestAppInspectionEngine01) {
printf("failed for http and dir(0-toserver)\n");
goto end;
}
} /* if (alproto == ALPROTO_HTTP && dir == 0) */
if (alproto == ALPROTO_HTTP && dir == 1) {
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
if (engine_list[ip][alproto][dir]->next != NULL) {
printf("more than one entry found\n");
goto end;
}
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
DetectEngineAppInspectionEngine *engine = engine_list[ip][alproto][dir];
if (engine->alproto != alproto ||
engine->dir != dir ||
engine->sm_list != DETECT_SM_LIST_UMATCH ||
engine->inspect_flags != DE_STATE_FLAG_URI_INSPECT ||
engine->Callback != DummyTestAppInspectionEngine02) {
printf("failed for http and dir(0-toclient)\n");
goto end;
}
} /* if (alproto == ALPROTO_HTTP && dir == 1) */
if (alproto != ALPROTO_HTTP &&
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
engine_list[ip][alproto][0] != NULL &&
engine_list[ip][alproto][1] != NULL) {
printf("failed for protocol %d\n", alproto);
goto end;
}
} /* for ( ; dir < 2 ..)*/
} /* for ( ; alproto < ALPROTO_FAILED; ..) */
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
}
result = 1;
end:
return result;
}
int DetectEngineTest07(void)
{
int result = 0;
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
int ip = 0;
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
DetectEngineAppInspectionEngine *engine_list[FLOW_PROTO_DEFAULT][ALPROTO_MAX][2];
memset(engine_list, 0, sizeof(engine_list));
struct test_data_t {
int32_t sm_list;
uint32_t inspect_flags;
uint16_t dir;
int (*Callback)(ThreadVars *tv,
DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx,
Signature *sig, Flow *f,
uint8_t flags, void *alstate,
void *tx, uint64_t tx_id);
};
struct test_data_t data[] = {
{ DETECT_SM_LIST_UMATCH,
DE_STATE_FLAG_URI_INSPECT,
0,
DummyTestAppInspectionEngine01 },
{ DETECT_SM_LIST_HCBDMATCH,
DE_STATE_FLAG_HCBD_INSPECT,
0,
DummyTestAppInspectionEngine02 },
{ DETECT_SM_LIST_FILEDATA,
DE_STATE_FLAG_HSBD_INSPECT,
1,
DummyTestAppInspectionEngine02 },
{ DETECT_SM_LIST_HHDMATCH,
DE_STATE_FLAG_HHD_INSPECT,
0,
DummyTestAppInspectionEngine01 },
{ DETECT_SM_LIST_HRHDMATCH,
DE_STATE_FLAG_HRHD_INSPECT,
0,
DummyTestAppInspectionEngine01 },
{ DETECT_SM_LIST_HMDMATCH,
DE_STATE_FLAG_HMD_INSPECT,
0,
DummyTestAppInspectionEngine02 },
{ DETECT_SM_LIST_HCDMATCH,
DE_STATE_FLAG_HCD_INSPECT,
0,
DummyTestAppInspectionEngine01 },
{ DETECT_SM_LIST_HRUDMATCH,
DE_STATE_FLAG_HRUD_INSPECT,
0,
DummyTestAppInspectionEngine01 },
{ DETECT_SM_LIST_FILEMATCH,
DE_STATE_FLAG_FILE_TS_INSPECT,
0,
DummyTestAppInspectionEngine02 },
{ DETECT_SM_LIST_FILEMATCH,
DE_STATE_FLAG_FILE_TC_INSPECT,
1,
DummyTestAppInspectionEngine02 },
{ DETECT_SM_LIST_HSMDMATCH,
DE_STATE_FLAG_HSMD_INSPECT,
0,
DummyTestAppInspectionEngine01 },
{ DETECT_SM_LIST_HSCDMATCH,
DE_STATE_FLAG_HSCD_INSPECT,
0,
DummyTestAppInspectionEngine01 },
{ DETECT_SM_LIST_HUADMATCH,
DE_STATE_FLAG_HUAD_INSPECT,
0,
DummyTestAppInspectionEngine02 },
};
size_t i = 0;
for ( ; i < sizeof(data) / sizeof(struct test_data_t); i++) {
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
DetectEngineRegisterAppInspectionEngine(IPPROTO_TCP,
ALPROTO_HTTP,
data[i].dir /* STREAM_TOCLIENT */,
data[i].sm_list,
data[i].inspect_flags,
data[i].Callback,
engine_list);
}
#if 0
DetectEnginePrintAppInspectionEngines(engine_list);
#endif
int alproto = ALPROTO_UNKNOWN + 1;
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
for (ip = 0; ip < FLOW_PROTO_DEFAULT; ip++) {
for ( ; alproto < ALPROTO_FAILED; alproto++) {
int dir = 0;
for ( ; dir < 2; dir++) {
if (alproto == ALPROTO_HTTP) {
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
DetectEngineAppInspectionEngine *engine = engine_list[ip][alproto][dir];
size_t i = 0;
for ( ; i < (sizeof(data) / sizeof(struct test_data_t)); i++) {
if (data[i].dir != dir)
continue;
if (engine->alproto != ALPROTO_HTTP ||
engine->dir != data[i].dir ||
engine->sm_list != data[i].sm_list ||
engine->inspect_flags != data[i].inspect_flags ||
engine->Callback != data[i].Callback) {
printf("failed for http\n");
goto end;
}
engine = engine->next;
}
} else {
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
if (engine_list[ip][alproto][0] != NULL &&
engine_list[ip][alproto][1] != NULL) {
printf("failed for protocol %d\n", alproto);
goto end;
}
} /* else */
} /* for ( ; dir < 2; dir++) */
} /* for ( ; alproto < ALPROTO_FAILED; ..) */
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
}
result = 1;
end:
return result;
}
static int DetectEngineTest08(void)
{
char *conf =
"%YAML 1.1\n"
"---\n"
"detect-engine:\n"
" - profile: custom\n"
" - custom-values:\n"
" toclient-src-groups: 20\n"
" toclient-dst-groups: 21\n"
" toclient-sp-groups: 22\n"
" toclient-dp-groups: 23\n"
" toserver-src-groups: 24\n"
" toserver-dst-groups: 25\n"
" toserver-sp-groups: 26\n"
" toserver-dp-groups: 27\n";
DetectEngineCtx *de_ctx = NULL;
int result = 0;
if (DetectEngineInitYamlConf(conf) == -1)
return 0;
de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
if (de_ctx->max_uniq_toclient_src_groups == 20 &&
de_ctx->max_uniq_toclient_dst_groups == 21 &&
de_ctx->max_uniq_toclient_sp_groups == 22 &&
de_ctx->max_uniq_toclient_dp_groups == 23 &&
de_ctx->max_uniq_toserver_src_groups == 24 &&
de_ctx->max_uniq_toserver_dst_groups == 25 &&
de_ctx->max_uniq_toserver_sp_groups == 26 &&
de_ctx->max_uniq_toserver_dp_groups == 27)
result = 1;
end:
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
DetectEngineDeInitYamlConf();
return result;
}
/** \test bug 892 bad values */
static int DetectEngineTest09(void)
{
char *conf =
"%YAML 1.1\n"
"---\n"
"detect-engine:\n"
" - profile: custom\n"
" - custom-values:\n"
" toclient-src-groups: BA\n"
" toclient-dst-groups: BA\n"
" toclient-sp-groups: BA\n"
" toclient-dp-groups: BA\n"
" toserver-src-groups: BA\n"
" toserver-dst-groups: BA\n"
" toserver-sp-groups: BA\n"
" toserver-dp-groups: BA\n"
" - inspection-recursion-limit: 10\n";
DetectEngineCtx *de_ctx = NULL;
int result = 0;
if (DetectEngineInitYamlConf(conf) == -1)
return 0;
de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
if (de_ctx->max_uniq_toclient_src_groups == 4 &&
de_ctx->max_uniq_toclient_dst_groups == 4 &&
de_ctx->max_uniq_toclient_sp_groups == 4 &&
de_ctx->max_uniq_toclient_dp_groups == 6 &&
de_ctx->max_uniq_toserver_src_groups == 4 &&
de_ctx->max_uniq_toserver_dst_groups == 8 &&
de_ctx->max_uniq_toserver_sp_groups == 4 &&
de_ctx->max_uniq_toserver_dp_groups == 30)
result = 1;
end:
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
DetectEngineDeInitYamlConf();
return result;
}
#endif
void DetectEngineRegisterTests()
{
#ifdef UNITTESTS
UtRegisterTest("DetectEngineTest01", DetectEngineTest01, 1);
UtRegisterTest("DetectEngineTest02", DetectEngineTest02, 1);
UtRegisterTest("DetectEngineTest03", DetectEngineTest03, 1);
UtRegisterTest("DetectEngineTest04", DetectEngineTest04, 1);
UtRegisterTest("DetectEngineTest05", DetectEngineTest05, 1);
UtRegisterTest("DetectEngineTest06", DetectEngineTest06, 1);
UtRegisterTest("DetectEngineTest07", DetectEngineTest07, 1);
UtRegisterTest("DetectEngineTest08", DetectEngineTest08, 1);
UtRegisterTest("DetectEngineTest09", DetectEngineTest09, 1);
#endif
return;
}