From: Victor Julien Date: Sat, 15 Feb 2025 18:20:14 +0000 (+0100) Subject: detect/profile: convert rule grouping dump to json builder X-Git-Tag: suricata-8.0.0-beta1~429 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4b855aa4a967c764af223c58e36eaaf11331c039;p=thirdparty%2Fsuricata.git detect/profile: convert rule grouping dump to json builder Ticket: #7558. --- diff --git a/src/detect-engine-build.c b/src/detect-engine-build.c index 7c9b66013e..fd73520ba9 100644 --- a/src/detect-engine-build.c +++ b/src/detect-engine-build.c @@ -599,7 +599,7 @@ static bool RuleMpmIsNegated(const Signature *s) return (cd->flags & DETECT_CONTENT_NEGATED) ? true : false; } -static json_t *RulesGroupPrintSghStats(const DetectEngineCtx *de_ctx, const SigGroupHead *sgh, +static JsonBuilder *RulesGroupPrintSghStats(const DetectEngineCtx *de_ctx, const SigGroupHead *sgh, const int add_rules, const int add_mpm_stats) { uint32_t prefilter_cnt = 0; @@ -636,14 +636,13 @@ static json_t *RulesGroupPrintSghStats(const DetectEngineCtx *de_ctx, const SigG if (sgh->init == NULL) return NULL; - json_t *js = json_object(); + JsonBuilder *js = jb_new_object(); if (unlikely(js == NULL)) return NULL; - json_object_set_new(js, "id", json_integer(sgh->id)); - - json_t *js_array = json_array(); + jb_set_uint(js, "id", sgh->id); + jb_open_array(js, "rules"); for (uint32_t x = 0; x < sgh->init->sig_cnt; x++) { const Signature *s = sgh->init->match_array[x]; if (s == NULL) @@ -766,35 +765,37 @@ static json_t *RulesGroupPrintSghStats(const DetectEngineCtx *de_ctx, const SigG alstats[s->alproto]++; if (add_rules) { - json_t *js_sig = json_object(); - if (unlikely(js == NULL)) - continue; - json_object_set_new(js_sig, "sig_id", json_integer(s->id)); - json_array_append_new(js_array, js_sig); + JsonBuilder *e = jb_new_object(); + if (e != NULL) { + jb_set_uint(e, "sig_id", s->id); + jb_close(e); + jb_append_object(js, e); + jb_free(e); + } } } + jb_close(js); - json_object_set_new(js, "rules", js_array); + jb_open_object(js, "stats"); + jb_set_uint(js, "total", sgh->init->sig_cnt); - json_t *stats = json_object(); - json_object_set_new(stats, "total", json_integer(sgh->init->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, "mpm_depth", json_integer(mpm_depth_cnt)); - json_object_set_new(types, "mpm_endswith", json_integer(mpm_endswith_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, "prefilter", json_integer(prefilter_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); + jb_open_object(js, "types"); + jb_set_uint(js, "mpm", mpm_cnt); + jb_set_uint(js, "non_mpm", nonmpm_cnt); + jb_set_uint(js, "mpm_depth", mpm_depth_cnt); + jb_set_uint(js, "mpm_endswith", mpm_endswith_cnt); + jb_set_uint(js, "negated_mpm", negmpm_cnt); + jb_set_uint(js, "payload_but_no_mpm", payload_no_mpm_cnt); + jb_set_uint(js, "prefilter", prefilter_cnt); + jb_set_uint(js, "syn", syn_cnt); + jb_set_uint(js, "any5", any5_cnt); + jb_close(js); for (AppProto i = 0; i < g_alproto_max; i++) { if (alstats[i] > 0) { - json_t *app = json_object(); - json_object_set_new(app, "total", json_integer(alstats[i])); + const char *proto_name = (i == ALPROTO_UNKNOWN) ? "payload" : AppProtoToString(i); + jb_open_object(js, proto_name); + jb_set_uint(js, "total", alstats[i]); for (int y = 0; y < max_buffer_type_id; y++) { if (alproto_mpm_bufs[i][y] == 0) @@ -806,54 +807,59 @@ static json_t *RulesGroupPrintSghStats(const DetectEngineCtx *de_ctx, const SigG else name = DetectEngineBufferTypeGetNameById(de_ctx, y); - json_object_set_new(app, name, json_integer(alproto_mpm_bufs[i][y])); + jb_set_uint(js, name, alproto_mpm_bufs[i][y]); } - - const char *proto_name = (i == ALPROTO_UNKNOWN) ? "payload" : AppProtoToString(i); - json_object_set_new(stats, proto_name, app); + jb_close(js); } } if (add_mpm_stats) { - json_t *mpm_js = json_object(); + jb_open_object(js, "mpm"); for (int i = 0; i < max_buffer_type_id; i++) { if (mpm_stats[i].cnt > 0) { + const char *name; + if (i < DETECT_SM_LIST_DYNAMIC_START) + name = DetectListToHumanString(i); + else + name = DetectEngineBufferTypeGetNameById(de_ctx, i); + + jb_open_array(js, name); - json_t *mpm_sizes_array = json_array(); for (int y = 0; y < 256; y++) { if (mpm_sizes[i][y] == 0) continue; - json_t *e = json_object(); - json_object_set_new(e, "size", json_integer(y)); - json_object_set_new(e, "count", json_integer(mpm_sizes[i][y])); - json_array_append_new(mpm_sizes_array, e); + JsonBuilder *e = jb_new_object(); + if (e != NULL) { + jb_set_uint(e, "size", y); + jb_set_uint(e, "count", mpm_sizes[i][y]); + jb_close(e); + jb_append_object(js, e); + jb_free(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); - - const char *name; - if (i < DETECT_SM_LIST_DYNAMIC_START) - name = DetectListToHumanString(i); - else - name = DetectEngineBufferTypeGetNameById(de_ctx, i); + JsonBuilder *e = jb_new_object(); + if (e != NULL) { + jb_set_uint(e, "total", mpm_stats[i].cnt); + jb_set_uint(e, "avg_strength", mpm_stats[i].total / mpm_stats[i].cnt); + jb_set_uint(e, "min_strength", mpm_stats[i].min); + jb_set_uint(e, "max_strength", mpm_stats[i].max); + jb_close(e); + jb_append_object(js, e); + jb_free(e); + } - json_object_set_new(mpm_js, name, buf); + jb_close(js); } } - - json_object_set_new(stats, "mpm", mpm_js); + jb_close(js); } - json_object_set_new(js, "stats", stats); + jb_close(js); - json_object_set_new(js, "score", json_integer(sgh->init->score)); + jb_set_uint(js, "score", sgh->init->score); + jb_close(js); return js; } @@ -861,97 +867,90 @@ static json_t *RulesGroupPrintSghStats(const DetectEngineCtx *de_ctx, const SigG static void RulesDumpGrouping(const DetectEngineCtx *de_ctx, const int add_rules, const int add_mpm_stats) { - json_t *js = json_object(); + JsonBuilder *js = jb_new_object(); if (unlikely(js == NULL)) return; - int p; - for (p = 0; p < 256; p++) { + for (int 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; + jb_open_object(js, name); + jb_open_array(js, "toserver"); + const 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)); + JsonBuilder *port = jb_new_object(); + jb_set_uint(port, "port", list->port); + jb_set_uint(port, "port2", list->port2); - json_t *tcp_ts = + JsonBuilder *stats = RulesGroupPrintSghStats(de_ctx, list->sh, add_rules, add_mpm_stats); - json_object_set_new(port, "rulegroup", tcp_ts); - json_array_append_new(ts_array, port); + jb_set_object(port, "rulegroup", stats); + jb_free(stats); + jb_close(port); + jb_append_object(js, port); + jb_free(port); list = list->next; } - json_object_set_new(tcp, "toserver", ts_array); + jb_close(js); // toserver array - json_t *tc_array = json_array(); + jb_open_array(js, "toclient"); 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)); + JsonBuilder *port = jb_new_object(); + jb_set_uint(port, "port", list->port); + jb_set_uint(port, "port2", list->port2); - json_t *tcp_tc = + JsonBuilder *stats = RulesGroupPrintSghStats(de_ctx, list->sh, add_rules, add_mpm_stats); - json_object_set_new(port, "rulegroup", tcp_tc); - json_array_append_new(tc_array, port); + jb_set_object(port, "rulegroup", stats); + jb_free(stats); + jb_close(port); + jb_append_object(js, port); + jb_free(port); list = list->next; } - json_object_set_new(tcp, "toclient", tc_array); - - json_object_set_new(js, name, tcp); + jb_close(js); // toclient array + jb_close(js); } else if (p == IPPROTO_ICMP || p == IPPROTO_ICMPV6) { const char *name = (p == IPPROTO_ICMP) ? "icmpv4" : "icmpv6"; - json_t *o = json_object(); + jb_open_object(js, name); if (de_ctx->flow_gh[1].sgh[p]) { - json_t *ts = json_object(); - json_t *group_ts = RulesGroupPrintSghStats( + jb_open_object(js, "toserver"); + JsonBuilder *stats = RulesGroupPrintSghStats( de_ctx, de_ctx->flow_gh[1].sgh[p], add_rules, add_mpm_stats); - json_object_set_new(ts, "rulegroup", group_ts); - json_object_set_new(o, "toserver", ts); + jb_set_object(js, "rulegroup", stats); + jb_free(stats); + jb_close(js); } if (de_ctx->flow_gh[0].sgh[p]) { - json_t *tc = json_object(); - json_t *group_tc = RulesGroupPrintSghStats( + jb_open_object(js, "toclient"); + JsonBuilder *stats = RulesGroupPrintSghStats( de_ctx, de_ctx->flow_gh[0].sgh[p], add_rules, add_mpm_stats); - json_object_set_new(tc, "rulegroup", group_tc); - json_object_set_new(o, "toclient", tc); + jb_set_object(js, "rulegroup", stats); + jb_free(stats); + jb_close(js); } - json_object_set_new(js, name, o); + jb_close(js); } } + jb_close(js); 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; + if (fp != NULL) { + fwrite(jb_ptr(js), jb_len(js), 1, fp); + (void)fclose(fp); } - - json_object_clear(js); - json_decref(js); - - fprintf(fp, "%s\n", js_s); - free(js_s); - fclose(fp); + jb_free(js); } static int RulesGroupByIPProto(DetectEngineCtx *de_ctx)