detect: output sgh stats

Output stats for the rule groups into a json format.
pull/1980/head
Victor Julien 11 years ago
parent 810d2d3ec6
commit 4ba1ac55f0

@ -2921,6 +2921,313 @@ int RuleMpmIsNegated(const Signature *s)
return (cd->flags & DETECT_CONTENT_NEGATED);
}
#ifdef HAVE_LIBJANSSON
json_t *RulesGroupPrintSghStats(const SigGroupHead *sgh)
{
uint32_t mpm_cnt = 0;
uint32_t nonmpm_cnt = 0;
uint32_t negmpm_cnt = 0;
uint32_t any5_cnt = 0;
uint32_t payload_no_mpm_cnt = 0;
uint32_t syn_cnt = 0;
uint32_t mpms_total = 0;
uint32_t mpms_min = 0;
uint32_t mpms_max = 0;
struct {
uint32_t total;
uint32_t cnt;
uint32_t min;
uint32_t max;
} mpm_stats[DETECT_SM_LIST_MAX];
memset(mpm_stats, 0x00, sizeof(mpm_stats));
uint32_t alstats[ALPROTO_MAX] = {0};
uint32_t mpm_sizes[DETECT_SM_LIST_MAX][256];
memset(mpm_sizes, 0, sizeof(mpm_sizes));
uint32_t alproto_mpm_bufs[ALPROTO_MAX][DETECT_SM_LIST_MAX];
memset(alproto_mpm_bufs, 0, sizeof(alproto_mpm_bufs));
json_t *js = json_object();
if (unlikely(js == NULL))
return NULL;
json_t *js_array = json_array();
const Signature *s;
uint32_t x;
for (x = 0; x < sgh->sig_cnt; x++) {
s = sgh->match_array[x];
if (s == NULL)
continue;
#if 0
json_t *js_sig = json_object();
if (unlikely(js == NULL))
continue;
json_object_set_new(js_sig, "sig_id", json_integer(s->id));
#endif
int any = 0;
if (s->proto.flags & DETECT_PROTO_ANY) {
any++;
}
if (s->flags & SIG_FLAG_DST_ANY) {
any++;
}
if (s->flags & SIG_FLAG_SRC_ANY) {
any++;
}
if (s->flags & SIG_FLAG_DP_ANY) {
any++;
}
if (s->flags & SIG_FLAG_SP_ANY) {
any++;
}
if (any == 5) {
any5_cnt++;
}
if (s->mpm_sm == NULL) {
nonmpm_cnt++;
if (s->sm_lists[DETECT_SM_LIST_MATCH] != NULL) {
SCLogDebug("SGH %p Non-MPM inspecting only packets. Rule %u", sgh, s->id);
}
DetectPort *sp = s->sp;
DetectPort *dp = s->dp;
if (s->flags & SIG_FLAG_TOSERVER && (dp->port == 0 && dp->port2 == 65535)) {
SCLogDebug("SGH %p Non-MPM toserver and to 'any'. Rule %u", sgh, s->id);
}
if (s->flags & SIG_FLAG_TOCLIENT && (sp->port == 0 && sp->port2 == 65535)) {
SCLogDebug("SGH %p Non-MPM toclient and to 'any'. Rule %u", sgh, s->id);
}
if (DetectFlagsSignatureNeedsSynPackets(s)) {
syn_cnt++;
}
} else {
int mpm_list = SigMatchListSMBelongsTo(s, s->mpm_sm);
BUG_ON(mpm_list < 0);
const DetectContentData *cd = (const DetectContentData *)s->mpm_sm->ctx;
uint32_t size = cd->content_len < 256 ? cd->content_len : 255;
mpm_sizes[mpm_list][size]++;
if (s->alproto != ALPROTO_UNKNOWN) {
alproto_mpm_bufs[s->alproto][mpm_list]++;
}
if (mpm_list == DETECT_SM_LIST_PMATCH) {
if (size == 1) {
DetectPort *sp = s->sp;
DetectPort *dp = s->dp;
if (s->flags & SIG_FLAG_TOSERVER) {
if (dp->port == 0 && dp->port2 == 65535) {
SCLogDebug("SGH %p toserver 1byte fast_pattern to ANY. Rule %u", sgh, s->id);
} else {
SCLogDebug("SGH %p toserver 1byte fast_pattern to port(s) %u-%u. Rule %u", sgh, dp->port, dp->port2, s->id);
}
}
if (s->flags & SIG_FLAG_TOCLIENT) {
if (sp->port == 0 && sp->port2 == 65535) {
SCLogDebug("SGH %p toclient 1byte fast_pattern to ANY. Rule %u", sgh, s->id);
} else {
SCLogDebug("SGH %p toclient 1byte fast_pattern to port(s) %u-%u. Rule %u", sgh, sp->port, sp->port2, s->id);
}
}
}
}
uint32_t w = PatternStrength(cd->content, cd->content_len);
mpms_total += w;
if (mpms_min == 0)
mpms_min = w;
if (w < mpms_min)
mpms_min = w;
if (w > mpms_max)
mpms_max = w;
mpm_stats[mpm_list].total += w;
mpm_stats[mpm_list].cnt++;
if (mpm_stats[mpm_list].min == 0 || w < mpm_stats[mpm_list].min)
mpm_stats[mpm_list].min = w;
if (w > mpm_stats[mpm_list].max)
mpm_stats[mpm_list].max = w;
mpm_cnt++;
if (w < 10) {
SCLogDebug("SGH %p Weak MPM Pattern on %s. Rule %u", sgh, DetectListToString(mpm_list), s->id);
}
if (w < 10 && any == 5) {
SCLogDebug("SGH %p Weak MPM Pattern on %s, rule is 5xAny. Rule %u", sgh, DetectListToString(mpm_list), s->id);
}
if (cd->flags & DETECT_CONTENT_NEGATED) {
SCLogDebug("SGH %p MPM Pattern on %s, is negated. Rule %u", sgh, DetectListToString(mpm_list), s->id);
negmpm_cnt++;
}
}
if (RuleInspectsPayloadHasNoMpm(s)) {
SCLogDebug("SGH %p No MPM. Payload inspecting. Rule %u", sgh, s->id);
payload_no_mpm_cnt++;
}
if (s->alproto != ALPROTO_UNKNOWN) {
alstats[s->alproto]++;
}
// json_array_append_new(js_array, js_sig);
}
json_object_set_new(js, "rules", js_array);
json_t *stats = json_object();
json_object_set_new(stats, "total", json_integer(sgh->sig_cnt));
json_t *types = json_object();
json_object_set_new(types, "mpm", json_integer(mpm_cnt));
json_object_set_new(types, "non_mpm", json_integer(nonmpm_cnt));
json_object_set_new(types, "negated_mpm", json_integer(negmpm_cnt));
json_object_set_new(types, "payload_but_no_mpm", json_integer(payload_no_mpm_cnt));
json_object_set_new(types, "syn", json_integer(syn_cnt));
json_object_set_new(types, "any5", json_integer(any5_cnt));
json_object_set_new(stats, "types", types);
int i;
for (i = 0; i < ALPROTO_MAX; i++) {
if (alstats[i] > 0) {
json_t *app = json_object();
json_object_set_new(app, "total", json_integer(alstats[i]));
for (x = 0; x < DETECT_SM_LIST_MAX; x++) {
if (alproto_mpm_bufs[i][x] == 0)
continue;
json_object_set_new(app, DetectListToHumanString(x), json_integer(alproto_mpm_bufs[i][x]));
}
json_object_set_new(stats, AppProtoToString(i), app);
}
}
json_t *mpm_js = json_object();
for (i = 0; i < DETECT_SM_LIST_MAX; i++) {
if (mpm_stats[i].cnt > 0) {
json_t *mpm_sizes_array = json_array();
for (x = 0; x < 256; x++) {
if (mpm_sizes[i][x] == 0)
continue;
json_t *e = json_object();
json_object_set_new(e, "size", json_integer(x));
json_object_set_new(e, "count", json_integer(mpm_sizes[i][x]));
json_array_append_new(mpm_sizes_array, e);
}
json_t *buf = json_object();
json_object_set_new(buf, "total", json_integer(mpm_stats[i].cnt));
json_object_set_new(buf, "avg_strength", json_integer(mpm_stats[i].total / mpm_stats[i].cnt));
json_object_set_new(buf, "min_strength", json_integer(mpm_stats[i].min));
json_object_set_new(buf, "max_strength", json_integer(mpm_stats[i].max));
json_object_set_new(buf, "sizes", mpm_sizes_array);
json_object_set_new(mpm_js, DetectListToHumanString(i), buf);
}
}
json_object_set_new(stats, "mpm", mpm_js);
json_object_set_new(js, "stats", stats);
json_object_set_new(js, "whitelist", json_integer(sgh->init->whitelist));
return js;
}
#endif /* HAVE_LIBJANSSON */
void RulesDumpGrouping(const DetectEngineCtx *de_ctx)
{
#ifdef HAVE_LIBJANSSON
json_t *js = json_object();
if (unlikely(js == NULL))
return;
int p;
for (p = 0; p < 256; p++) {
if (p == IPPROTO_TCP || p == IPPROTO_UDP) {
const char *name = (p == IPPROTO_TCP) ? "tcp" : "udp";
json_t *tcp = json_object();
json_t *ts_array = json_array();
DetectPort *list = (p == IPPROTO_TCP) ? de_ctx->flow_gh[1].tcp :
de_ctx->flow_gh[1].udp;
while (list != NULL) {
json_t *port = json_object();
json_object_set_new(port, "port", json_integer(list->port));
json_object_set_new(port, "port2", json_integer(list->port2));
json_t *tcp_ts = RulesGroupPrintSghStats(list->sh);
json_object_set_new(port, "rulegroup", tcp_ts);
json_array_append_new(ts_array, port);
list = list->next;
}
json_object_set_new(tcp, "toserver", ts_array);
json_t *tc_array = json_array();
list = (p == IPPROTO_TCP) ? de_ctx->flow_gh[0].tcp :
de_ctx->flow_gh[0].udp;
while (list != NULL) {
json_t *port = json_object();
json_object_set_new(port, "port", json_integer(list->port));
json_object_set_new(port, "port2", json_integer(list->port2));
json_t *tcp_tc = RulesGroupPrintSghStats(list->sh);
json_object_set_new(port, "rulegroup", tcp_tc);
json_array_append_new(tc_array, port);
list = list->next;
}
json_object_set_new(tcp, "toclient", tc_array);
json_object_set_new(js, name, tcp);
}
}
const char *filename = "rule_group.json";
const char *log_dir = ConfigGetLogDirectory();
char log_path[PATH_MAX] = "";
snprintf(log_path, sizeof(log_path), "%s/%s", log_dir, filename);
FILE *fp = fopen(log_path, "w");
if (fp == NULL) {
return;
}
char *js_s = json_dumps(js,
JSON_PRESERVE_ORDER|JSON_ESCAPE_SLASH);
if (unlikely(js_s == NULL)) {
fclose(fp);
return;
}
json_object_clear(js);
json_decref(js);
fprintf(fp, "%s\n", js_s);
free(js_s);
fclose(fp);
#endif
return;
}
int RulesGroupByProto(DetectEngineCtx *de_ctx)
{
Signature *s = de_ctx->sig_list;
@ -3018,6 +3325,7 @@ int RulesGroupByProto(DetectEngineCtx *de_ctx)
de_ctx->gh_unique++;
own++;
} else {
SCLogDebug("proto group %d sgh %p is a copy", p, sgh_tc[p]);
@ -3734,6 +4042,8 @@ int SigAddressPrepareStage4(DetectEngineCtx *de_ctx)
de_ctx->sgh_array_cnt = 0;
de_ctx->sgh_array_size = 0;
RulesDumpGrouping(de_ctx);
SCReturnInt(0);
}

Loading…
Cancel
Save