1 /*-
2 * Copyright (c) 2005 Andrey Simonenko
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #include "config.h"
28
29 #ifndef lint
30 static const char rcsid[] ATTR_UNUSED =
31 "@(#)$Id: ipastat_thresholds.c,v 1.2.2.1 2011/11/15 18:12:29 simon Exp $";
32 #endif /* !lint */
33
34 #include <sys/types.h>
35
36 #include <limits.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 #include "ipa_mod.h"
41
42 #include "queue.h"
43
44 #include "dlapi.h"
45 #include "confcommon.h"
46 #include "memfunc.h"
47
48 #include "ipastat_log.h"
49 #include "ipastat_main.h"
50 #include "ipastat_rules.h"
51 #include "ipastat_st.h"
52
53 char has_opt_thresholds = 0; /* Set if -q ... -t ... */
54
55 #ifdef WITH_THRESHOLDS
56
57 signed char dynamic_thresholds; /* dynamic_thresholds parameter. */
58
59 ipa_mzone *threshold_mzone; /* Mzone for struct threshold{}. */
60
61 struct threshold *
alloc_threshold(void)62 alloc_threshold(void)
63 {
64 struct threshold *threshold;
65
66 threshold = mzone_alloc(threshold_mzone);
67 if (threshold == NULL) {
68 xlogmsgx(IPA_LOG_ERR, "alloc_threshold: mzone_alloc failed");
69 return (NULL);
70 }
71 threshold->info = NULL;
72 threshold->st_list = NULL;
73 threshold->inited = 0;
74 return (threshold);
75 }
76
77 /*
78 * Return pointer to threshold with the give name.
79 */
80 struct threshold *
threshold_by_name(const struct rule * rule,const char * name)81 threshold_by_name(const struct rule *rule, const char *name)
82 {
83 struct threshold *threshold;
84
85 STAILQ_FOREACH(threshold, &rule->thresholds, link)
86 if (strcmp(name, threshold->name) == 0)
87 break;
88 return (threshold);
89 }
90
91 static void
get_min_max_no(const struct opt_thresholds * opt_thresholds,unsigned int * minno,unsigned int * maxno)92 get_min_max_no( const struct opt_thresholds *opt_thresholds,
93 unsigned int *minno, unsigned int *maxno)
94 {
95 const struct threshold *threshold;
96 const struct opt_threshold *opt_threshold;
97
98 *minno = UINT_MAX;
99 *maxno = 0;
100 STAILQ_FOREACH(opt_threshold, opt_thresholds, link) {
101 threshold = opt_threshold->threshold;
102 if (*minno > threshold->no)
103 *minno = threshold->no;
104 if (*maxno < threshold->no)
105 *maxno = threshold->no;
106 }
107 }
108
109 /*
110 * Initialize all thresholds from one rule in modules.
111 */
112 int
init_thresholds(const struct opt_rule * opt_rule)113 init_thresholds(const struct opt_rule *opt_rule)
114 {
115 const struct rule *rule;
116 const struct opt_threshold *opt_threshold;
117 const struct opt_thresholds *opt_thresholds;
118 struct threshold *threshold;
119 unsigned int minno, maxno, no;
120
121 rule = opt_rule->rule;
122 opt_thresholds = &opt_rule->opt_thresholds;
123
124 get_min_max_no(opt_thresholds, &minno, &maxno);
125
126 for (no = minno; no <= maxno; ++no)
127 STAILQ_FOREACH(opt_threshold, opt_thresholds, link) {
128 threshold = opt_threshold->threshold;
129 if (threshold->no == no) {
130 if (!threshold->inited) {
131 threshold->inited = 1;
132 if (st_init_threshold(rule,
133 threshold) < 0) {
134 logbt("init_thresholds");
135 return (-1);
136 }
137 }
138 break;
139 }
140 }
141
142 return (0);
143 }
144
145 int
deinit_thresholds(const struct opt_rule * opt_rule)146 deinit_thresholds(const struct opt_rule *opt_rule)
147 {
148 const struct rule *rule;
149 const struct opt_threshold *opt_threshold;
150 const struct opt_thresholds *opt_thresholds;
151 struct threshold *threshold;
152 unsigned int minno, maxno, no;
153 int rv;
154
155 rule = opt_rule->rule;
156 opt_thresholds = &opt_rule->opt_thresholds;
157
158 get_min_max_no(opt_thresholds, &minno, &maxno);
159
160 rv = 0;
161 for (no = minno; no <= maxno; ++no)
162 STAILQ_FOREACH(opt_threshold, &opt_rule->opt_thresholds, link) {
163 threshold = opt_threshold->threshold;
164 if (threshold->no == no) {
165 if (threshold->inited) {
166 threshold->inited = 0;
167 if (st_deinit_threshold(rule,
168 threshold) < 0) {
169 logbt("deinit_thresholds");
170 rv = -1;
171 }
172 }
173 break;
174 }
175 }
176
177 return (rv);
178 }
179
180 /*
181 * Copy all thresholds from list_src to rule.
182 */
183 int
copy_thresholds(struct rule * rule,const struct thresholds_list * list)184 copy_thresholds(struct rule *rule, const struct thresholds_list *list)
185 {
186 const struct threshold *tsrc;
187 struct threshold *tdst;
188
189 STAILQ_FOREACH(tsrc, list, link) {
190 tdst = mzone_alloc(threshold_mzone);
191 if (tdst == NULL) {
192 xlogmsgx(IPA_LOG_ERR, "copy_thresholds: "
193 "mzone_alloc failed");
194 return (-1);
195 }
196
197 /* Copy settings from source threshold. */
198 *tdst = *tsrc;
199
200 tdst->free_mask = 0;
201
202 /* Link just allocated threshold to rule. */
203 STAILQ_INSERT_TAIL(&rule->thresholds, tdst, link);
204 }
205 return (0);
206 }
207
208 /*
209 * Release memory used by a list of thresholds.
210 */
211 void
free_thresholds(struct thresholds_list * thresholds)212 free_thresholds(struct thresholds_list *thresholds)
213 {
214 struct threshold *threshold, *threshold_next;
215
216 STAILQ_FOREACH_SAFE(threshold, thresholds, link, threshold_next) {
217 if (threshold->free_mask & THRESHOLD_FREE_NAME)
218 mem_free(threshold->name, m_anon);
219 mem_free(threshold->info, m_result);
220 mzone_free(threshold_mzone, threshold);
221 }
222 }
223
224 /*
225 * Add one optional threshold given in the -q -r option.
226 */
227 int
opt_threshold_add(const char * name)228 opt_threshold_add(const char *name)
229 {
230 struct opt_threshold *opt_threshold;
231
232 opt_threshold = mem_malloc(sizeof(*opt_threshold), m_anon);
233 if (opt_threshold == NULL) {
234 logmsgx(IPA_LOG_ERR, "opt_threshold_add: mem_malloc failed");
235 return (-1);
236 }
237
238 opt_threshold->name = name;
239 opt_threshold->opt_st = cur_opt_st;
240
241 cur_opt_rule->type = OPT_RULE_THRESHOLD;
242
243 STAILQ_INSERT_TAIL(&cur_opt_rule->opt_thresholds, opt_threshold, link);
244
245 has_opt_thresholds = 1;
246 return (0);
247 }
248
249 int
opt_thresholds_parse(const struct opt_rule * opt_rule)250 opt_thresholds_parse(const struct opt_rule *opt_rule)
251 {
252 struct rule *rule;
253 struct threshold *threshold;
254 struct opt_threshold *opt_threshold;
255 unsigned int thresholdno;
256
257 if (STAILQ_EMPTY(&opt_rule->opt_thresholds))
258 return (0);
259
260 rule = opt_rule->rule;
261 if (STAILQ_EMPTY(&rule->thresholds))
262 thresholdno = 0;
263 else {
264 threshold = STAILQ_LAST(&rule->thresholds, threshold, link);
265 thresholdno = threshold->no + 1;
266 }
267
268 STAILQ_FOREACH(opt_threshold, &opt_rule->opt_thresholds, link) {
269 threshold = threshold_by_name(rule, opt_threshold->name);
270 if (threshold == NULL) {
271 /*
272 * This threshold is not given in the configuration
273 * file.
274 */
275 if (!dynamic_thresholds) {
276 logmsgx(IPA_LOG_ERR, "opt_thresholds_parse: "
277 "unknown rule %s, threshold %s",
278 rule->name, opt_threshold->name);
279 return (-1);
280 }
281 threshold = alloc_threshold();
282 if (threshold == NULL) {
283 logbt("opt_thresholds_parse");
284 return (-1);
285 }
286 STAILQ_INSERT_TAIL(&rule->thresholds, threshold, link);
287 threshold->no = thresholdno++;
288 threshold->name = (char *)opt_threshold->name;
289 threshold->free_mask = 0;
290 }
291 opt_threshold->threshold = threshold;
292 if (opt_threshold->opt_st != NULL)
293 threshold->st_list = opt_threshold->opt_st->st_list;
294 if (threshold->st_list == NULL)
295 threshold->st_list = rule->st_list;
296 }
297
298 return (0);
299 }
300
301 void
opt_thresholds_free(const struct opt_thresholds * opt_thresholds)302 opt_thresholds_free(const struct opt_thresholds *opt_thresholds)
303 {
304 struct opt_threshold *opt_threshold, *opt_threshold_next;
305
306 STAILQ_FOREACH_SAFE(opt_threshold, opt_thresholds, link,
307 opt_threshold_next)
308 mem_free(opt_threshold, m_anon);
309 }
310 #endif /* WITH_THRESHOLDS */
311