/*- * Copyright (c) 2005 Andrey Simonenko * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "config.h" #ifndef lint static const char rcsid[] ATTR_UNUSED = "@(#)$Id: ipastat_main.c,v 1.1.4.2 2007/05/11 16:29:59 simon Exp $"; #endif /* !lint */ #include #include #include #include #include #include #include #include "ipa_mod.h" #include "dlapi.h" #include "confcommon.h" #include "memfunc.h" #include "ipastat_conf.h" #include "ipastat_log.h" #include "ipastat_main.h" #include "ipastat_rules.h" #include "ipastat_time.h" #include "ipastat_st.h" const char *x_pat = NULL; /* -q -x */ regex_t x_reg; /* Compiled x_pat. */ regex_t *x_reg_ptr = NULL; /* NULL or &x_reg. */ u_int a_flag = A_FLAG_ABSENT; /* -q -a ... */ ipa_mem_type *m_anon; /* Anonymous memory allocations. */ ipa_mem_type *m_result; /* Memory used for query results. */ static int need_nl_raw = 0; /* Non-zero if new line is needed in raw output. */ /* * If some rule has several buffers with statistics for * several time intervals, then keep them in rule_stat_list * structure. */ struct rule_stat { STAILQ_ENTRY(rule_stat) link; /* All rule_stat for rule. */ u_int n; /* Number of elements in buf. */ struct ipa_rule_stat *buf; /* Buffer with statistics for rule. */ const struct opt_tint *opt_tint; /* Time interval. */ }; STAILQ_HEAD(rule_stat_list, rule_stat); #ifdef WITH_LIMITS /* * If some limit has several buffers with statistics for * several time intervals, then keep them in limit_stat_list * structure. */ struct limit_stat { STAILQ_ENTRY(limit_stat) link; /* All limit_stat for limit. */ u_int n; /* Number of elements in buf. */ struct ipa_limit_state *buf; /* Buffer with statistics for limit. */ const struct opt_tint *opt_tint; /* Time interval. */ }; STAILQ_HEAD(limit_stat_list, limit_stat); #endif /* WITH_LIMITS */ #ifdef WITH_ANY_LIMITS /* * Description of several entities. */ struct entity_desc { u_int n; /* Number of elements in desc_list. */ struct ipa_entity_desc *desc_list; /* Array of descriptions. */ }; #endif static int output(const char *, ...) ATTR_FORMAT(printf, 1, 2); static int output(const char *format, ...) { va_list ap; va_start(ap, format); if (vprintf(format, ap) < 0) { logmsg(IPA_LOG_ERR, "output: vprintf failed"); return -1; } va_end(ap); return 0; } static const char * plural_trailing(u_int n) { return n != 1 ? "s" : ""; } static int print_line(size_t len) { while (len--) if (printf("-") < 0) { logmsg(IPA_LOG_ERR, "print_line: printf failed"); return -1; } return 0; } static int output_flush(void) { if (fflush(stdout) != 0) { logmsg(IPA_LOG_ERR, "output_flush: fflush(stdout)"); return -1; } return 0; } static int output_ipa_tm(const char *msg, const char sep, const ipa_tm *tm, u_int is_set) { if (output("%s %c ", msg, sep) < 0) goto failed; if (is_set) { if (output("%d.%02d.%02d/%02d:%02d:%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec) < 0) goto failed; } else { if (output("-\n") < 0) goto failed; } return 0; failed: logmsgx(IPA_LOG_INFO, "output_ipa_tm: output failed"); return -1; } static int cmp_entity_desc(const void *p1, const void *p2) { return strcmp( ((const struct ipa_entity_desc *)p1)->name, ((const struct ipa_entity_desc *)p2)->name); } static int output_desc_list_raw(const char *what, u_int n, const struct ipa_entity_desc *desc_list) { size_t len, name_width, info_width; const struct ipa_entity_desc *desc; name_width = strlen(what); info_width = 4; /* strlen("info") */ for (desc = desc_list; desc < desc_list + n; ++desc) { len = strlen(desc->name); if (name_width < len) name_width = len; if (desc->info != NULL) { len = strlen(desc->info); if (info_width < len) info_width = len; } } ++info_width; if (output("%-*s | Info\n", (int)name_width, what) < 0) goto failed; if (print_line(name_width) < 0 || output("-+") < 0 || print_line(info_width) < 0 || output("\n") < 0) goto failed; for (desc = desc_list; desc < desc_list + n; ++desc) if ((desc->info != NULL ? output("%-*s | %s\n", (int)name_width, desc->name, desc->info) : output("%-*s |\n", (int)name_width, desc->name)) < 0) goto failed; if (print_line(name_width) < 0 || output("-+") < 0 || print_line(info_width) < 0 || output("\n\n") < 0) goto failed; if (output(" * %u line%s\n", n, plural_trailing(n)) < 0) goto failed; if (output_flush() < 0) { logmsgx(IPA_LOG_ERR, "output_entity_desc_raw: output_flush failed"); return -1; } return 0; failed: logmsgx(IPA_LOG_ERR, "output_entity_desc_raw: output failed"); return -1; } static void free_desc_list(u_int n, struct ipa_entity_desc *desc_list) { struct ipa_entity_desc *desc; if (desc_list != NULL) { for (desc = desc_list; desc < desc_list + n; ++desc) { mem_free(desc->name, m_result); mem_free(desc->info, m_result); } mem_free(desc_list, m_result); } } static int show_rules_list(void) { int error; u_int n; const struct st_list *st_list; struct ipa_entity_desc *desc_list; st_list = cur_opt_st != NULL ? cur_opt_st->st_list : global_st_list; error = -1; if (st_get_rules_list(st_list, &n, &desc_list) < 0) { logmsgx(IPA_LOG_ERR, "show_rules_list: st_get_rules_list failed"); desc_list = NULL; goto done; } qsort(desc_list, n, sizeof *desc_list, cmp_entity_desc); if (output_desc_list_raw("Rule", n, desc_list) < 0) { logmsgx(IPA_LOG_ERR, "show_rules_list: output_desc_list_raw failed"); goto done; } error = 0; done: free_desc_list(n, desc_list); return error; } static int output_rule_stat_raw(const struct opt_rule *opt_rule) { u_int curyear, curmon, curmday; u_int ndays, ndays_tot; uint64_t cnt_day, cnt_sum, cnt_tot; const struct rule *rule; const struct ipa_rule_stat *stat, *stat_end; const struct rule_stat *rule_stat; const struct rule_stat_list *rule_stat_list; if (need_nl_raw) { if (output("\n") < 0) goto failed; } else need_nl_raw = 1; rule = opt_rule->rule; if (output("Rule : %s\nInfo : %s\n", rule->rule_name, rule->rule_info != NULL ? rule->rule_info : "") < 0) goto failed; rule_stat_list = opt_rule->data; ndays_tot = 0; cnt_tot = UINT64_C(0); STAILQ_FOREACH(rule_stat, rule_stat_list, link) { if (output_ipa_tm("\nFrom", ':', &rule_stat->opt_tint->tm1, 1) < 0) goto failed; if (output_ipa_tm("To ", ':', &rule_stat->opt_tint->tm2, 1) < 0) goto failed; cnt_sum = UINT64_C(0); if (rule_stat->n != 0) { stat = rule_stat->buf; stat_end = stat + rule_stat->n; curyear = stat->year; curmon = stat->mon; curmday = stat->mday; cnt_day = UINT64_C(0); ndays = 1; if (output("\nTimestamp | Counter | Per day\n-----------------------------+----------------------+---------------------") < 0) goto failed; for (;;) { if (output("\n%u.%02u.%02u/%02u:%02u:%02u-%02u:%02u:%02u | %20"PRIu64" |", stat->year, stat->mon, stat->mday, stat->h1, stat->m1, stat->s1, stat->h2, stat->m2, stat->s2, stat->cnt) < 0) goto failed; if (cnt_day < UINT64_MAX - stat->cnt) cnt_day += stat->cnt; else cnt_day = UINT64_MAX; if (++stat == stat_end) break; if (curmday != stat->mday || curmon != stat->mon || curyear != stat->year) { curmday = stat->mday; curmon = stat->mon; curyear = stat->year; ndays++; if (cnt_sum < UINT64_MAX - cnt_day) cnt_sum += cnt_day; else cnt_sum = UINT64_MAX; if (cnt_day != UINT64_MAX) { if (output(" %20"PRIu64, cnt_day) < 0) goto failed; } else { if (output(" %20s", "TOO_BIG") < 0) goto failed; } cnt_day = UINT64_C(0); } } if (cnt_day != UINT64_MAX) { if (output(" %20"PRIu64, cnt_day) < 0) goto failed; } else { if (output(" %20s", "TOO_BIG") < 0) goto failed; } if (output("\n-----------------------------+----------------------+---------------------") < 0 || output("\n") < 0) goto failed; if (cnt_sum < UINT64_MAX - cnt_day) cnt_sum += cnt_day; else cnt_sum = UINT64_MAX; } else ndays = 0; if (cnt_sum != UINT64_MAX) { if (output("\n * Summary %"PRIu64" (%u day%s)\n", cnt_sum, ndays, plural_trailing(ndays)) < 0) goto failed; } else { if (output("\n * Summary TOO_BIG (%u day%s)\n", ndays, plural_trailing(ndays)) < 0) goto failed; } ndays_tot += ndays; if (cnt_tot < UINT64_MAX - cnt_sum) cnt_tot += cnt_sum; else cnt_tot = UINT64_MAX; } if (cnt_tot != UINT64_MAX) { if (output("\n * Total %"PRIu64" (%u day%s)\n", cnt_tot, ndays_tot, plural_trailing(ndays_tot)) < 0) goto failed; } else { if (output("\n * Total TOO_BIG (%u day%s)\n", ndays_tot, plural_trailing(ndays_tot)) < 0) goto failed; } if (output_flush() < 0) { logmsgx(IPA_LOG_ERR, "output_rule_stat_raw: output_flush failed"); return -1; } return 0; failed: logmsgx(IPA_LOG_ERR, "output_rule_stat_raw: output failed"); return -1; } static int show_rules_stat(void) { int error; u_int n; struct ipa_rule_stat *buf; struct rule *rule; struct opt_rule *opt_rule; struct rule_stat *rule_stat, *rule_stat_next; struct rule_stat_list *rule_stat_list; const struct opt_tint *opt_tint; error = -1; STAILQ_FOREACH(opt_rule, &opt_rules_list, link) { rule = opt_rule->rule; if (rule->rule_info == NULL) if (st_get_rule_info(rule, &rule->rule_info) < 0) { logmsgx(IPA_LOG_ERR, "show_rules_stat: st_get_rule_info failed"); goto done; } if ( (rule_stat_list = mem_malloc(sizeof *rule_stat_list, m_anon)) == NULL) { logmsgx(IPA_LOG_ERR, "show_rules_stat: mem_malloc failed"); goto done; } STAILQ_INIT(rule_stat_list); opt_rule->data = rule_stat_list; STAILQ_FOREACH(opt_tint, &opt_tint_list, link) { if (st_get_rule_stat(rule, &opt_tint->tm1, &opt_tint->tm2, opt_tint->exact, &n, &buf) < 0) { logmsgx(IPA_LOG_ERR, "show_rules_stat: st_get_rule_stat failed"); goto done; } if ( (rule_stat = mem_malloc(sizeof *rule_stat, m_anon)) == NULL) { logmsgx(IPA_LOG_ERR, "show_rules_stat: mem_malloc failed"); mem_free(buf, m_result); goto done; } rule_stat->n = n; rule_stat->buf = buf; rule_stat->opt_tint = opt_tint; STAILQ_INSERT_TAIL(rule_stat_list, rule_stat, link); } } STAILQ_FOREACH(opt_rule, &opt_rules_list, link) if (output_rule_stat_raw(opt_rule) < 0) { logmsgx(IPA_LOG_ERR, "show_rules_stat: output_rule_stat_raw failed"); goto done; } error = 0; done: STAILQ_FOREACH(opt_rule, &opt_rules_list, link) { rule_stat_list = opt_rule->data; if (rule_stat_list != NULL) { for (rule_stat = STAILQ_FIRST(rule_stat_list); rule_stat != NULL; rule_stat = rule_stat_next) { rule_stat_next = STAILQ_NEXT(rule_stat, link); mem_free(rule_stat->buf, m_result); mem_free(rule_stat, m_anon); } mem_free(rule_stat_list, m_anon); } } return error; } #ifdef WITH_ANY_LIMITS static int output_any_limits_list_raw(const struct opt_rule *opt_rule, const char *what) { const struct rule *rule; const struct entity_desc *entity_desc; if (need_nl_raw) { if (output("\n") < 0) goto failed; } else need_nl_raw = 1; rule = opt_rule->rule; if (output("Rule : %s\nInfo : %s\n\n", rule->rule_name, rule->rule_info != NULL ? rule->rule_info : "") < 0) goto failed; entity_desc = opt_rule->data; if (output_desc_list_raw(what, entity_desc->n, entity_desc->desc_list) < 0) { logmsgx(IPA_LOG_ERR, "output_any_limits_list: output_desc_list_raw failed"); goto failed; } if (output_flush() < 0) { logmsgx(IPA_LOG_ERR, "output_any_limits_list_raw: output_flush failed"); return -1; } return 0; failed: logmsgx(IPA_LOG_ERR, "output_any_limits_list_raw: output failed"); return -1; } #endif /* WITH_ANY_LIMITS */ #ifdef WITH_LIMITS static int show_limits_list(void) { int error; u_int n; struct rule *rule; struct opt_rule *opt_rule; struct entity_desc *entity_desc; struct ipa_entity_desc *desc_list; error = -1; STAILQ_FOREACH(opt_rule, &opt_rules_list, link) { rule = opt_rule->rule; if (rule->rule_info == NULL) if (st_get_rule_info(rule, &rule->rule_info) < 0) { logmsgx(IPA_LOG_ERR, "show_limits_list: st_get_rule_info failed"); goto done; } if (st_get_limits_list(rule, &n, &desc_list) < 0) { logmsgx(IPA_LOG_ERR, "show_limits_list: st_get_limits_list failed"); goto done; } if ( (entity_desc = mem_malloc(sizeof *entity_desc, m_anon)) == NULL) { logmsgx(IPA_LOG_ERR, "show_limits_list: mem_malloc failed"); free_desc_list(n, desc_list); goto done; } entity_desc->desc_list = desc_list; entity_desc->n = n; opt_rule->data = entity_desc; qsort(desc_list, n, sizeof *desc_list, cmp_entity_desc); } STAILQ_FOREACH(opt_rule, &opt_rules_list, link) if (output_any_limits_list_raw(opt_rule, "Limit") < 0) { logmsgx(IPA_LOG_ERR, "show_limits_list: output_any_limits_list_raw failed"); goto done; } error = 0; done: STAILQ_FOREACH(opt_rule, &opt_rules_list, link) if ( (entity_desc = opt_rule->data) != NULL) { free_desc_list(entity_desc->n, entity_desc->desc_list); mem_free(entity_desc, m_anon); } return error; } #define LIMIT_START_STR "Start " #define LIMIT_RESTART_STR "Restart " #define LIMIT_RESTART_EXEC_STR "Restart exec" #define LIMIT_REACH_STR "Reach " #define LIMIT_REACH_EXEC_STR "Reach exec " #define LIMIT_EXPIRE_STR "Expire " #define LIMIT_EXPIRE_EXEC_STR "Expire exec " #define LIMIT_UPDATED_STR "Updated " struct limit_event { const char *name; u_int set; u_int idx; }; #define EVENT_TBL_ENTRY(X) { LIMIT_ ## X ## _STR, IPA_LIMIT_EVENT_ ## X ## _SET, IPA_LIMIT_EVENT_ ## X } static const struct limit_event limit_event_tbl[] = { EVENT_TBL_ENTRY(START), EVENT_TBL_ENTRY(RESTART), EVENT_TBL_ENTRY(RESTART_EXEC), EVENT_TBL_ENTRY(REACH), EVENT_TBL_ENTRY(REACH_EXEC), EVENT_TBL_ENTRY(EXPIRE), EVENT_TBL_ENTRY(EXPIRE_EXEC), EVENT_TBL_ENTRY(UPDATED) }; #undef EVENT_TBL_ENTRY static int output_limits_stat_raw(const struct opt_rule *opt_rule) { const struct rule *rule; const struct limit *limit; const struct opt_limit *opt_limit; const struct ipa_limit_state *state, *state_end; const struct limit_stat *limit_stat; const struct limit_stat_list *limit_stat_list; const struct limit_event *event; if (need_nl_raw) { if (output("\n") < 0) goto failed; } else need_nl_raw = 1; rule = opt_rule->rule; if (output("Rule : %s\nInfo : %s\n", rule->rule_name, rule->rule_info != NULL ? rule->rule_info : "") < 0) goto failed; STAILQ_FOREACH(opt_limit, &opt_rule->opt_limits, link) { limit = opt_limit->limit; if (output("\nLimit : %s\nInfo : %s\n", limit->limit_name, limit->limit_info != NULL ? limit->limit_info : "") < 0) goto failed; limit_stat_list = opt_limit->data; STAILQ_FOREACH(limit_stat, limit_stat_list, link) { if (limit_stat->opt_tint == NULL) { if (output("\nFrom : current\nTo : current\n") < 0) goto failed; } else { if (output_ipa_tm("\nFrom ", ':', &limit_stat->opt_tint->tm1, 1) < 0) goto failed; if (output_ipa_tm("To ", ':', &limit_stat->opt_tint->tm2, 1) < 0) goto failed; } if (limit_stat->n != 0) { state = limit_stat->buf; state_end = state + limit_stat->n; for (; state != state_end; ++state) { if (output("\n-------------+---------------------\n") < 0) goto failed; if (state->lim != UINT64_C(0) || limit_stat->opt_tint != NULL) { for (event = limit_event_tbl; event < limit_event_tbl + IPA_LIMIT_EVENT_NUM; ++event) if (output_ipa_tm(event->name, '|', &state->event_date[event->idx], state->event_date_set & event->set) < 0) goto failed; if (output("Limit | %20"PRIu64"\nCounter | %20"PRIu64"", state->lim, state->cnt) < 0) goto failed; } else { for (event = limit_event_tbl; event < limit_event_tbl + IPA_LIMIT_EVENT_NUM; ++event) if (output("%s |\n", event->name) < 0) goto failed; if (output("Limit | NOT_REGISTERED\nCounter |") < 0) goto failed; } } if (output("\n-------------+---------------------\n") < 0) goto failed; } if (output("\n * %u state%s\n", limit_stat->n, plural_trailing(limit_stat->n)) < 0) goto failed; } } if (output_flush() < 0) { logmsgx(IPA_LOG_ERR, "output_limits_stat_raw: output_flush failed"); return -1; } return 0; failed: logmsgx(IPA_LOG_ERR, "output_limits_stat_raw: output failed"); return -1; } static int show_limits_stat(void) { int error; u_int n; struct ipa_limit_state *buf; struct rule *rule; struct limit *limit; struct opt_rule *opt_rule; struct opt_limit *opt_limit; struct limit_stat *limit_stat, *limit_stat_next; struct limit_stat_list *limit_stat_list; const struct opt_tint *opt_tint; error = -1; STAILQ_FOREACH(opt_rule, &opt_rules_list, link) { rule = opt_rule->rule; if (rule->rule_info == NULL) if (st_get_rule_info(rule, &rule->rule_info) < 0) { logmsgx(IPA_LOG_ERR, "show_limits_stat: st_get_rule_info failed"); goto done; } STAILQ_FOREACH(opt_limit, &opt_rule->opt_limits, link) { limit = opt_limit->limit; if (limit->limit_info == NULL) if (st_get_limit_info(rule, limit, &limit->limit_info) < 0) { logmsgx(IPA_LOG_ERR, "show_limits_stat: st_get_limit_info failed"); goto done; } if ( (limit_stat_list = mem_malloc(sizeof *limit_stat_list, m_anon)) == NULL) { logmsgx(IPA_LOG_ERR, "show_limits_stat: mem_malloc failed"); goto done; } STAILQ_INIT(limit_stat_list); opt_limit->data = limit_stat_list; if (STAILQ_EMPTY(&opt_tint_list)) { if (st_get_limit_stat(rule, limit, (ipa_tm *)NULL, (ipa_tm *)NULL, &n, &buf) < 0) { logmsgx(IPA_LOG_ERR, "show_limits_stat: st_get_limit_stat failed"); goto done; } if ( (limit_stat = mem_malloc(sizeof *limit_stat, m_anon)) == NULL) { logmsgx(IPA_LOG_ERR, "show_limits_stat: mem_malloc failed"); mem_free(buf, m_result); goto done; } limit_stat->n = n; limit_stat->buf = buf; limit_stat->opt_tint = NULL; STAILQ_INSERT_TAIL(limit_stat_list, limit_stat, link); } else STAILQ_FOREACH(opt_tint, &opt_tint_list, link) { if (st_get_limit_stat(rule, limit, &opt_tint->tm1, &opt_tint->tm2, &n, &buf) < 0) { logmsgx(IPA_LOG_ERR, "show_limits_stat: st_get_limit_stat failed"); goto done; } if ( (limit_stat = mem_malloc(sizeof *limit_stat, m_anon)) == NULL) { logmsgx(IPA_LOG_ERR, "show_limits_stat: mem_malloc failed"); mem_free(buf, m_result); goto done; } limit_stat->n = n; limit_stat->buf = buf; limit_stat->opt_tint = opt_tint; STAILQ_INSERT_TAIL(limit_stat_list, limit_stat, link); } } } STAILQ_FOREACH(opt_rule, &opt_rules_list, link) if (output_limits_stat_raw(opt_rule) < 0) { logmsgx(IPA_LOG_ERR, "show_limits_stat: output_limits_stat_raw failed"); goto done; } error = 0; done: STAILQ_FOREACH(opt_rule, &opt_rules_list, link) STAILQ_FOREACH(opt_limit, &opt_rule->opt_limits, link) { limit_stat_list = opt_limit->data; if (limit_stat_list != NULL) { for (limit_stat = STAILQ_FIRST(limit_stat_list); limit_stat != NULL; limit_stat = limit_stat_next) { limit_stat_next = STAILQ_NEXT(limit_stat, link); mem_free(limit_stat->buf, m_result); mem_free(limit_stat, m_anon); } mem_free(limit_stat_list, m_anon); } } return error; } #endif /* WITH_LIMITS */ #ifdef WITH_THRESHOLDS static int show_thresholds_list(void) { int error; u_int n; struct rule *rule; struct entity_desc *entity_desc; struct ipa_entity_desc *desc_list; struct opt_rule *opt_rule; error = -1; STAILQ_FOREACH(opt_rule, &opt_rules_list, link) { rule = opt_rule->rule; if (rule->rule_info == NULL) if (st_get_rule_info(rule, &rule->rule_info) < 0) { logmsgx(IPA_LOG_ERR, "show_thresholds_list: st_get_rule_info failed"); goto done; } if (st_get_thresholds_list(rule, &n, &desc_list) < 0) { logmsgx(IPA_LOG_ERR, "show_thresholds_list: st_get_thresholds_list failed"); goto done; } if ( (entity_desc = mem_malloc(sizeof *entity_desc, m_anon)) == NULL) { logmsgx(IPA_LOG_ERR, "show_thresholds_list: mem_malloc failed"); free_desc_list(n, desc_list); goto done; } entity_desc->desc_list = desc_list; entity_desc->n = n; opt_rule->data = entity_desc; qsort(desc_list, n, sizeof *desc_list, cmp_entity_desc); } STAILQ_FOREACH(opt_rule, &opt_rules_list, link) if (output_any_limits_list_raw(opt_rule, "Threshold") < 0) { logmsgx(IPA_LOG_ERR, "show_thresholds_list: output_any_limits_list_raw failed"); goto done; } error = 0; done: STAILQ_FOREACH(opt_rule, &opt_rules_list, link) if ( (entity_desc = opt_rule->data) != NULL) { free_desc_list(entity_desc->n, entity_desc->desc_list); mem_free(entity_desc, m_anon); } return error; } static int output_thresholds_stat_raw(const struct opt_rule *opt_rule) { const struct rule *rule; const struct threshold *threshold; const struct ipa_threshold_state *state; const struct opt_threshold *opt_threshold; if (need_nl_raw) { if (output("\n") < 0) goto failed; } else need_nl_raw = 1; rule = opt_rule->rule; if (output("Rule : %s\nInfo : %s\n", rule->rule_name, rule->rule_info != NULL ? rule->rule_info : "") < 0) goto failed; STAILQ_FOREACH(opt_threshold, &opt_rule->opt_thresholds, link) { threshold = opt_threshold->threshold; if (output("\nThreshold : %s\nInfo : %s\n\n", threshold->threshold_name, threshold->threshold_info != NULL ? threshold->threshold_info : "") < 0) goto failed; state = &opt_threshold->data; if (output("----------+---------------------\n") < 0) goto failed; if (state->thr != UINT64_C(0)) { if (output_ipa_tm("From ", '|', &state->tm_from, 1) < 0) goto failed; if (output_ipa_tm("Updated ", '|', &state->tm_updated, 1) < 0) goto failed; if (output("Threshold | %20"PRIu64"\nCounter | %20"PRIu64"\n", state->thr, state->cnt) < 0) goto failed; } else { if (output("From |\nUpdated |\nThreshold | NOT_REGISTERED\nCounter |\n") < 0) goto failed; } if (output("----------+---------------------\n") < 0) goto failed; } if (output_flush() < 0) { logmsgx(IPA_LOG_ERR, "output_thresholds_stat_raw: output_flush failed"); return -1; } return 0; failed: logmsgx(IPA_LOG_ERR, "output_thresholds_stat_raw: output failed"); return -1; } static int show_thresholds_stat(void) { int error; struct rule *rule; struct threshold *threshold; struct opt_rule *opt_rule; struct opt_threshold *opt_threshold; error = -1; STAILQ_FOREACH(opt_rule, &opt_rules_list, link) { rule = opt_rule->rule; if (rule->rule_info == NULL) if (st_get_rule_info(rule, &rule->rule_info) < 0) { logmsgx(IPA_LOG_ERR, "show_thresholds_stat: st_get_rule_info failed"); goto done; } STAILQ_FOREACH(opt_threshold, &opt_rule->opt_thresholds, link) { threshold = opt_threshold->threshold; if (threshold->threshold_info == NULL) if (st_get_threshold_info(rule, threshold, &threshold->threshold_info) < 0) { logmsgx(IPA_LOG_ERR, "show_thresholds_stat: st_get_threshold_info failed"); goto done; } if (st_get_threshold_stat(rule, threshold, &opt_threshold->data) < 0) { logmsgx(IPA_LOG_ERR, "show_thresholds_stat: st_get_threshold_stat failed"); goto done; } } } STAILQ_FOREACH(opt_rule, &opt_rules_list, link) if (output_thresholds_stat_raw(opt_rule) < 0) { logmsgx(IPA_LOG_ERR, "show_thresholds_stat: output_thresholds_stat_raw failed"); goto done; } error = 0; done: return error; } #endif /* WITH_THRESHOLDS */ int ipastat_main(void) { int error; /* Check if there is any query in -q. */ if (a_flag != A_FLAG_RULES && STAILQ_EMPTY(&opt_rules_list)) { logmsgx(IPA_LOG_WARNING, "ipastat_main: no query is given"); return 0; } /* Pre-init statistics modules. */ if (pre_init_st_mods() < 0) { logmsgx(IPA_LOG_ERR, "ipastat_main: pre_init_st_mods failed"); return -1; } /* Init rules, limits or thresholds. */ if (init_rules() < 0) { logmsgx(IPA_LOG_ERR, "ipastat_main: init_rules failed"); return -1; } /* Init statistics modules. */ if (init_st_mods() < 0) { logmsgx(IPA_LOG_ERR, "ipastat_main: init_st_mods failed"); return -1; } error = 0; switch (a_flag) { case A_FLAG_ABSENT: switch (cur_opt_rule->type) { case OPT_RULE_RULE: if (STAILQ_EMPTY(&opt_tint_list)) init_opt_tint_default(); error = show_rules_stat(); break; #ifdef WITH_LIMITS case OPT_RULE_LIMIT: error = show_limits_stat(); break; #endif #ifdef WITH_THRESHOLDS case OPT_RULE_THRESHOLD: error = show_thresholds_stat(); break; #endif } break; case A_FLAG_RULES: error = show_rules_list(); break; #ifdef WITH_LIMITS case A_FLAG_LIMITS: error = show_limits_list(); break; #endif #ifdef WITH_THRESHOLDS case A_FLAG_THRESHOLDS: error = show_thresholds_list(); break; #endif } return error; } int deinit_all(void) { int error = 0; /* First deinit rules. */ if (deinit_rules() < 0) { logmsgx(IPA_LOG_ERR, "deinit_all: deinit_rules failed"); error = -1; } /* Deinit statistics modules. */ if (deinit_st_mods() < 0) { logmsgx(IPA_LOG_ERR, "deinit_all: deinit_st_mods failed"); error = -1; } return error; }