/*-
* 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 <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/queue.h>
#include <regex.h>
#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 <pattern> */
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;
}
syntax highlighted by Code2HTML, v. 0.9.1