1 /*-
2 * Copyright (c) 2000-2003 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: ipa_db.c,v 1.2 2011/01/23 18:42:34 simon Exp $";
32 #endif /* !lint */
33
34 #include <sys/types.h>
35
36 #include <errno.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <time.h>
41
42 #include "ipa_mod.h"
43
44 #include "queue.h"
45
46 #include "dlapi.h"
47 #include "confcommon.h"
48 #include "memfunc.h"
49 #include "parser.h"
50
51 #include "ipa_ac.h"
52 #include "ipa_db.h"
53 #include "ipa_ctl.h"
54 #include "ipa_cmd.h"
55 #include "ipa_time.h"
56
57 #include "ipa_conf.h"
58 #include "ipa_log.h"
59 #include "ipa_main.h"
60 #include "ipa_rules.h"
61 #include "ipa_autorules.h"
62
63 unsigned int ndb_mods; /* Number of db_mods. */
64
65 signed char debug_db_null; /* debug_db_null parameter. */
66
67 const struct db_list *global_db_list; /* global { db_list } */
68
69 /*
70 * List of all used "db_list" parameters. If some rules use the same
71 * "db_list" parameter, then they share the same struct db_list{}.
72 */
73 struct db_sets db_sets;
74
75 /* List of all database modules. */
76 struct db_mod_list db_mod_list;
77
78 /*
79 * Find a database module by configuration prefix.
80 */
81 struct db_mod *
db_mod_by_prefix(const char * prefix)82 db_mod_by_prefix(const char *prefix)
83 {
84 struct db_mod *db_mod;
85
86 SLIST_FOREACH(db_mod, &db_mod_list, link)
87 if (db_mod->ipa_db_mod->conf_prefix != NULL &&
88 strcmp(db_mod->ipa_db_mod->conf_prefix, prefix) == 0)
89 break;
90 return (db_mod);
91 }
92
93 /*
94 * Find a database module by a name.
95 */
96 struct db_mod *
db_mod_by_name(const char * name)97 db_mod_by_name(const char *name)
98 {
99 struct db_mod *db_mod;
100
101 SLIST_FOREACH(db_mod, &db_mod_list, link)
102 if (strcmp(db_mod->ipa_db_mod->db_name, name) == 0)
103 break;
104 return (db_mod);
105 }
106
107 /*
108 * Release memory held by db_set, including struct db_set{}.
109 */
110 void
free_db_set(struct db_set * set)111 free_db_set(struct db_set *set)
112 {
113 struct db_elem *db, *db_next;
114
115 STAILQ_FOREACH_SAFE(db, &set->list, link, db_next)
116 mem_free(db, m_anon);
117 mem_free(set, m_anon);
118 }
119
120 /*
121 * Release memory held by all db_set.
122 */
123 void
free_db_lists(void)124 free_db_lists(void)
125 {
126 struct db_set *set, *set_next;
127
128 SLIST_FOREACH_SAFE(set, &db_sets, link, set_next)
129 free_db_set(set);
130 }
131
132 #ifdef WITH_LIMITS
133
134 # ifdef WITH_RULES
135 /*
136 * Initialize one static limit.
137 */
138 static int
db_init_statlimit(const struct rule * rule,struct limit * limit)139 db_init_statlimit(const struct rule *rule, struct limit *limit)
140 {
141 if (!STAILQ_EMPTY(limit->db_list)) {
142 const struct db_elem *db;
143
144 STAILQ_FOREACH(db, limit->db_list, link) {
145 if (db->ipa_db_mod->db_init_statlimit == NULL) {
146 logmsgx(IPA_LOG_ERR, "module %s: rule %s,"
147 "limit %s: db_init_statlimit: module does "
148 "not support static limits", db->mod_file,
149 rule->name, limit->name);
150 return (-1);
151 }
152 if (db->ipa_db_mod->db_init_statlimit(rule->no,
153 rule->name, rule->info, limit->no, limit->name,
154 limit->info) < 0) {
155 logmsgx(IPA_LOG_ERR, "module %s: rule %s, "
156 "limit %s: db_init_statlimit failed",
157 db->mod_file, rule->name, limit->name);
158 return (-1);
159 }
160 }
161 } else if (debug_db_null)
162 logdbg("rule %s, limit %s: uses \"null\" database",
163 rule->name, limit->name);
164 mem_free(limit->info, m_parser);
165 limit->info = NULL;
166 return (0);
167 }
168
169 /*
170 * Initialize limits for one static rule in databases.
171 */
172 static int
db_init_statlimits(const struct rule * rule)173 db_init_statlimits(const struct rule *rule)
174 {
175 struct limit *limit;
176
177 STAILQ_FOREACH(limit, &rule->limits, link)
178 if (db_init_statlimit(rule, limit) < 0) {
179 logbt("db_init_statlimits");
180 return (-1);
181 }
182 return (0);
183 }
184 # endif /* WITH_RULES */
185
186 # ifdef WITH_AUTORULES
187 /*
188 * Initialize one dynamic limit.
189 */
190 static int
db_init_dynlimit(const struct autorule * autorule,const struct rule * rule,struct limit * limit)191 db_init_dynlimit(const struct autorule *autorule, const struct rule *rule,
192 struct limit *limit)
193 {
194 if (!STAILQ_EMPTY(limit->db_list)) {
195 const struct db_elem *db;
196
197 STAILQ_FOREACH(db, limit->db_list, link) {
198 if (db->ipa_db_mod->db_init_dynlimit == NULL) {
199 logmsgx(IPA_LOG_ERR, "module %s: autorule %s, "
200 "rule %s, limit %s: db_init_dynlimit: "
201 "module does not support static limits",
202 db->mod_file, autorule->name, rule->name,
203 limit->name);
204 return (-1);
205 }
206 if (db->ipa_db_mod->db_init_dynlimit(autorule->no,
207 rule->no, rule->name, rule->info, limit->no,
208 limit->name, limit->info) < 0) {
209 logmsgx(IPA_LOG_ERR, "module %s: autorule %s, "
210 "rule %s, limit %s: db_init_dynlimit "
211 "failed", db->mod_file, autorule->name,
212 rule->name, limit->name);
213 return (-1);
214 }
215 }
216 } else if (debug_db_null)
217 logdbg("rule %s, limit %s: uses \"null\" database",
218 rule->name, limit->name);
219 return (0);
220 }
221
222 /*
223 * Initialize limits for one dynamic rule in databases.
224 */
225 static int
db_init_dynlimits(const struct autorule * autorule,const struct rule * rule)226 db_init_dynlimits(const struct autorule *autorule, const struct rule *rule)
227 {
228 struct limit *limit;
229
230 STAILQ_FOREACH(limit, &rule->limits, link)
231 if (db_init_dynlimit(autorule, rule, limit) < 0) {
232 logbt("db_init_dynlimits");
233 return (-1);
234 }
235 return (0);
236 }
237
238 # endif /* WITH_AUTORULES */
239
240 /*
241 * Deinitialize limit in one rule in databases.
242 */
243 int
db_deinit_limit(const struct rule * rule,const struct limit * limit)244 db_deinit_limit(const struct rule *rule, const struct limit *limit)
245 {
246 const struct db_elem *db;
247 int rv;
248
249 rv = 0;
250 STAILQ_FOREACH(db, limit->db_list, link)
251 if (db->ipa_db_mod->db_deinit_limit != NULL &&
252 db->ipa_db_mod->db_deinit_limit(rule->no, limit->no) < 0) {
253 logmsgx(IPA_LOG_ERR, "module %s: rule %s, limit %s: "
254 "db_deinit_limit failed", db->mod_file, rule->name,
255 limit->name);
256 rv = -1;
257 }
258 return (rv);
259 }
260
261 /*
262 * Update statistics for one limit.
263 */
264 int
db_update_limit(const struct rule * rule,const struct limit * limit)265 db_update_limit(const struct rule *rule, const struct limit *limit)
266 {
267 const struct db_elem *db;
268 int rv;
269
270 rv = 0;
271 STAILQ_FOREACH(db, limit->db_list, link)
272 if (db->ipa_db_mod->db_update_limit(rule->no,
273 limit->no, &limit->cnt, &curdate) < 0) {
274 logmsgx(IPA_LOG_ERR, "module %s: rule %s, limit %s: "
275 "db_update_limit failed", db->mod_file, rule->name,
276 limit->name);
277 rv = -1;
278 }
279 return (rv);
280 }
281
282 /*
283 * Register limit event for one limit.
284 */
285 int
db_limit_event(const struct rule * rule,struct limit * limit,unsigned int event,const ipa_tm * tm)286 db_limit_event(const struct rule *rule, struct limit *limit,
287 unsigned int event, const ipa_tm *tm)
288 {
289 const struct db_elem *db;
290 int rv;
291
292 if (ctl_enable) {
293 limit->event_date_set |= 1 << event;
294 limit->event_date[event] = *tm;
295 }
296
297 rv = 0;
298 STAILQ_FOREACH(db, limit->db_list, link)
299 if (db->ipa_db_mod->db_limit_event(rule->no, limit->no, event,
300 tm, &curdate) < 0) {
301 logmsgx(IPA_LOG_ERR, "module %s: rule %s, limit %s: "
302 "db_limit_event(EVENT_%s) failed", db->mod_file,
303 rule->name, limit->name, limit_event_msg[event]);
304 rv = -1;
305 }
306 return (rv);
307 }
308
309 /*
310 * Get a state of the limit: use first database which
311 * supports db_get_limit_state method and save its name in
312 * db_name. If any of databases used by the limit does not
313 * support db_get_limit_state method, then set db_name to NULL.
314 */
315 int
db_get_limit_state(const struct rule * rule,const struct limit * limit,struct ipa_limit_state * state,const char ** db_name)316 db_get_limit_state(const struct rule *rule, const struct limit *limit,
317 struct ipa_limit_state *state, const char **db_name)
318 {
319 const struct db_elem *db;
320 int rv;
321
322 STAILQ_FOREACH(db, limit->db_list, link)
323 if (db->ipa_db_mod->db_get_limit_state != NULL) {
324 rv = db->ipa_db_mod->db_get_limit_state(rule->no,
325 limit->no, state);
326 if (rv >= 0) {
327 *db_name = db->ipa_db_mod->db_name;
328 return (rv);
329 }
330 logmsgx(IPA_LOG_ERR, "module %s: rule %s, limit %s: "
331 "db_get_limit_state failed", db->mod_file,
332 rule->name, limit->name);
333 return (-1);
334 }
335 *db_name = NULL;
336 return (0);
337 }
338
339 /*
340 * Set a state of the limit in databases.
341 */
342 int
db_set_limit_state(const struct rule * rule,struct limit * limit,struct ipa_limit_state * state,int new_state)343 db_set_limit_state(const struct rule *rule, struct limit *limit,
344 struct ipa_limit_state *state, int new_state)
345 {
346 const struct db_elem *db;
347 int rv;
348
349 if (ctl_enable) {
350 state->event_date_set |= IPA_LIMIT_EVENT_UPDATED_SET;
351 state->event_date[IPA_LIMIT_EVENT_UPDATED] = curdate;
352 }
353
354 limit->event_date_set = state->event_date_set;
355 memcpy(limit->event_date, state->event_date,
356 sizeof(limit->event_date));
357
358 rv = 0;
359 STAILQ_FOREACH(db, limit->db_list, link)
360 if (db->ipa_db_mod->db_set_limit_state(rule->no,
361 limit->no, state, new_state) < 0) {
362 logmsgx(IPA_LOG_ERR, "module %s: rule %s, limit %s"
363 "db_set_limit_state(%d) failed", db->mod_file,
364 rule->name, limit->name, new_state);
365 rv = -1;
366 }
367 return (rv);
368 }
369
370 /*
371 * Set a limit active/inactive in databases it uses.
372 */
373 int
db_set_limit_active(const struct rule * rule,const struct limit * limit,int active)374 db_set_limit_active(const struct rule *rule, const struct limit *limit,
375 int active)
376 {
377 const struct db_elem *db;
378
379 /* Limit uses own db_list. */
380 STAILQ_FOREACH(db, limit->db_list, link)
381 if (db->ipa_db_mod->db_set_limit_active != NULL)
382 if (db->ipa_db_mod->db_set_limit_active(rule->no,
383 limit->no, active) < 0) {
384 logmsgx(IPA_LOG_ERR, "module %s: rule %s, "
385 "limit %s: db_set_limit_active(%d) failed",
386 db->mod_file, rule->name, limit->name,
387 active);
388 return (-1);
389 }
390 return (0);
391 }
392 #endif /* WITH_LIMITS */
393
394 #ifdef WITH_THRESHOLDS
395
396 # ifdef WITH_RULES
397 /*
398 * Initialize one static threshold.
399 */
400 static int
db_init_statthreshold(const struct rule * rule,struct threshold * threshold)401 db_init_statthreshold(const struct rule *rule, struct threshold *threshold)
402 {
403 if (!STAILQ_EMPTY(threshold->db_list)) {
404 const struct db_elem *db;
405
406 STAILQ_FOREACH(db, threshold->db_list, link) {
407 if (db->ipa_db_mod->db_init_statthreshold == NULL) {
408 logmsgx(IPA_LOG_ERR, "module %s: rule %s, "
409 "threshold %s: db_init_statthreshold: "
410 "module does not support static thresholds",
411 db->mod_file, rule->name, threshold->name);
412 return (-1);
413
414 }
415 if (db->ipa_db_mod->db_init_statthreshold(rule->no,
416 rule->name, rule->info, threshold->no,
417 threshold->name, threshold->info) < 0) {
418 logmsgx(IPA_LOG_ERR, "module %s: rule %s, "
419 "threshold %s: db_init_statthreshold "
420 "failed", db->mod_file, rule->name,
421 threshold->name);
422 return (-1);
423 }
424 }
425 } else if (debug_db_null)
426 logdbg("rule %s, threshold %s: uses \"null\" database",
427 rule->name, threshold->name);
428 mem_free(threshold->info, m_parser);
429 threshold->info = NULL;
430 return (0);
431 }
432
433 /*
434 * Initialize thresholds for one static rule in databases.
435 */
436 static int
db_init_statthresholds(const struct rule * rule)437 db_init_statthresholds(const struct rule *rule)
438 {
439 struct threshold *threshold;
440
441 STAILQ_FOREACH(threshold, &rule->thresholds, link)
442 if (db_init_statthreshold(rule, threshold) < 0) {
443 logbt("db_init_statthresholds");
444 return (-1);
445 }
446 return (0);
447 }
448 # endif /* WITH_RULES */
449
450 # ifdef WITH_AUTORULES
451 /*
452 * Initialize one dynamic threshold.
453 */
454 static int
db_init_dynthreshold(const struct autorule * autorule,const struct rule * rule,struct threshold * threshold)455 db_init_dynthreshold(const struct autorule *autorule, const struct rule *rule,
456 struct threshold *threshold)
457 {
458 if (!STAILQ_EMPTY(threshold->db_list)) {
459 const struct db_elem *db;
460
461 STAILQ_FOREACH(db, threshold->db_list, link) {
462 if (db->ipa_db_mod->db_init_dynthreshold == NULL) {
463 logmsgx(IPA_LOG_ERR, "module %s: autorule %s, "
464 "rule %s, threshold %s: "
465 "db_init_dynthreshold: module does not "
466 "support dynamic thresholds",
467 db->mod_file, autorule->name, rule->name,
468 threshold->name);
469 return (-1);
470 }
471 if (db->ipa_db_mod->db_init_dynthreshold(autorule->no,
472 rule->no, rule->name, rule->info, threshold->no,
473 threshold->name, threshold->info) < 0) {
474 logmsgx(IPA_LOG_ERR, "module %s: autorule %s, "
475 "rule %s, threshold %s: "
476 "db_init_dynthreshold failed",
477 db->mod_file, autorule->name, rule->name,
478 threshold->name);
479 return (-1);
480 }
481 }
482 } else if (debug_db_null)
483 logdbg("rule %s, threshold %s: uses \"null\" database",
484 rule->name, threshold->name);
485 return (0);
486 }
487
488 /*
489 * Initialize thresholds for one dynamic rule in databases.
490 */
491 static int
db_init_dynthresholds(const struct autorule * autorule,const struct rule * rule)492 db_init_dynthresholds(const struct autorule *autorule, const struct rule *rule)
493 {
494 struct threshold *threshold;
495
496 STAILQ_FOREACH(threshold, &rule->thresholds, link)
497 if (db_init_dynthreshold(autorule, rule, threshold) < 0) {
498 logbt("db_init_dynthresholds");
499 return (-1);
500 }
501 return (0);
502 }
503 # endif /* WITH_AUTORULES */
504
505 /*
506 * Deinitialize threshold in one rule in databases.
507 */
508 int
db_deinit_threshold(const struct rule * rule,const struct threshold * threshold)509 db_deinit_threshold(const struct rule *rule, const struct threshold *threshold)
510 {
511 const struct db_elem *db;
512 int rv;
513
514 rv = 0;
515 STAILQ_FOREACH(db, threshold->db_list, link)
516 if (db->ipa_db_mod->db_deinit_threshold != NULL &&
517 db->ipa_db_mod->db_deinit_threshold(rule->no,
518 threshold->no) < 0) {
519 logmsgx(IPA_LOG_ERR, "module %s: rule %s, "
520 "threshold %s: db_deinit_threshold failed",
521 db->mod_file, rule->name, threshold->name);
522 rv = -1;
523 }
524 return (rv);
525 }
526
527 /*
528 * Update statistics for one threshold in databases.
529 */
530 int
db_update_threshold(const struct rule * rule,const struct threshold * threshold)531 db_update_threshold(const struct rule *rule, const struct threshold *threshold)
532 {
533 const struct db_elem *db;
534 int rv;
535
536 rv = 0;
537 STAILQ_FOREACH(db, threshold->db_list, link)
538 if (db->ipa_db_mod->db_update_threshold(rule->no,
539 threshold->no, &threshold->cnt, &threshold->tm_started,
540 &threshold->tm_updated) < 0) {
541 logmsgx(IPA_LOG_ERR, "module %s: rule %s, "
542 "threshold %s: db_update_threshold failed",
543 db->mod_file, rule->name, threshold->name);
544 rv = -1;
545 }
546 return (rv);
547 }
548
549 /*
550 * Get a state of the threshold: use first database which
551 * supports db_get_threshold_state method and save its name in
552 * db_name. If any of databases used by the threshold does not
553 * support db_get_threshold_state method, then set db_name to NULL.
554 */
555 int
db_get_threshold_state(const struct rule * rule,const struct threshold * threshold,struct ipa_threshold_state * state,const char ** db_name)556 db_get_threshold_state(const struct rule *rule,
557 const struct threshold *threshold, struct ipa_threshold_state *state,
558 const char **db_name)
559 {
560 const struct db_elem *db;
561 int rv;
562
563 STAILQ_FOREACH(db, threshold->db_list, link)
564 if (db->ipa_db_mod->db_get_threshold_state != NULL) {
565 rv = db->ipa_db_mod->db_get_threshold_state(rule->no,
566 threshold->no, state);
567 if (rv >= 0) {
568 *db_name = db->ipa_db_mod->db_name;
569 return (rv);
570 }
571 logmsgx(IPA_LOG_ERR, "module %s: rule %s, "
572 "threshold %s: db_get_threshold_state failed",
573 db->mod_file, rule->name, threshold->name);
574 return (-1);
575 }
576 *db_name = NULL;
577 return (0);
578 }
579
580 /*
581 * Set a state of the threshold in databases.
582 */
583 int
db_set_threshold_state(const struct rule * rule,const struct threshold * threshold,const struct ipa_threshold_state * state)584 db_set_threshold_state(const struct rule *rule,
585 const struct threshold *threshold, const struct ipa_threshold_state *state)
586 {
587 const struct db_elem *db;
588 int rv;
589
590 rv = 0;
591 STAILQ_FOREACH(db, threshold->db_list, link)
592 if (db->ipa_db_mod->db_set_threshold_state(rule->no,
593 threshold->no, state) < 0) {
594 logmsgx(IPA_LOG_ERR, "module %s: rule %s, "
595 "threshold %s: db_set_threshold_state failed",
596 db->mod_file, rule->name, threshold->name);
597 rv = -1;
598 }
599 return (rv);
600 }
601
602 /*
603 * Set a threshold active/inactive in databases it uses.
604 */
605 int
db_set_threshold_active(const struct rule * rule,const struct threshold * threshold,int active)606 db_set_threshold_active(const struct rule *rule,
607 const struct threshold *threshold, int active)
608 {
609 const struct db_elem *db;
610
611 /* Threshold uses own db_list. */
612 STAILQ_FOREACH(db, threshold->db_list, link)
613 if (db->ipa_db_mod->db_set_threshold_active != NULL &&
614 db->ipa_db_mod->db_set_threshold_active(rule->no,
615 threshold->no, active) < 0) {
616 logmsgx(IPA_LOG_ERR, "module %s: rule %s, "
617 "threshold %s: db_set_threshold_active(%d) failed",
618 db->mod_file, rule->name, threshold->name, active);
619 return (-1);
620 }
621 return (0);
622 }
623 #endif /* WITH_THRESHOLDS */
624
625 #ifdef WITH_RULES
626 /*
627 * Initialize one static rule in databases, also initialize its
628 * limits and thresholds.
629 */
630 int
db_init_statrule(struct rule * rule)631 db_init_statrule(struct rule *rule)
632 {
633 if (!STAILQ_EMPTY(rule->db_list)) {
634 const struct db_elem *db;
635
636 STAILQ_FOREACH(db, rule->db_list, link) {
637 if (db->ipa_db_mod->db_init_statrule == NULL) {
638 logmsgx(IPA_LOG_ERR, "module %s: rule %s:"
639 "db_init_statrule: module does not support "
640 "static rules", db->mod_file, rule->name);
641 return (-1);
642 }
643 if (db->ipa_db_mod->db_init_statrule(rule->no,
644 rule->name, rule->info) < 0) {
645 logmsgx(IPA_LOG_ERR, "module %s: rule %s: "
646 "db_init_statrule failed", db->mod_file,
647 rule->name);
648 return (-1);
649 }
650 }
651 } else if (debug_db_null)
652 logdbg("rule %s: uses \"null\" database", rule->name);
653
654 mem_free(rule->info, m_parser);
655 rule->info = NULL;
656
657 #ifdef WITH_LIMITS
658 if (db_init_statlimits(rule) < 0) {
659 logbt("db_init_statrule");
660 return (-1);
661 }
662 #endif
663 #ifdef WITH_THRESHOLDS
664 if (db_init_statthresholds(rule) < 0) {
665 logbt("db_init_statrule");
666 return (-1);
667 }
668 #endif
669 return (0);
670 }
671 #endif /* WITH_RULES */
672
673 /*
674 * Pre-initialize all db_mods.
675 */
676 int
pre_init_db_mods(void)677 pre_init_db_mods(void)
678 {
679 const struct db_mod *db_mod;
680
681 SLIST_FOREACH(db_mod, &db_mod_list, link)
682 if (db_mod->ipa_db_mod->db_pre_init() < 0) {
683 logmsgx(IPA_LOG_ERR, "module %s: db_pre_init failed",
684 db_mod->mod_file);
685 return (-1);
686 }
687 return (0);
688 }
689
690 /*
691 * Initialize all db_mods.
692 */
693 int
init_db_mods(void)694 init_db_mods(void)
695 {
696 const struct db_mod *db_mod;
697
698 SLIST_FOREACH(db_mod, &db_mod_list, link)
699 if (db_mod->ipa_db_mod->db_init() < 0) {
700 logmsgx(IPA_LOG_ERR, "module %s: db_init failed",
701 db_mod->mod_file);
702 return (-1);
703 }
704 return (0);
705 }
706
707 /*
708 * Deinitialize all db_mods.
709 */
710 int
deinit_db_mods(void)711 deinit_db_mods(void)
712 {
713 const struct db_mod *db_mod;
714 int rv;
715
716 rv = 0;
717 SLIST_FOREACH(db_mod, &db_mod_list, link)
718 if (db_mod->ipa_db_mod->db_deinit() < 0) {
719 logmsgx(IPA_LOG_ERR, "module %s: deinit_db_mods: "
720 "db_deinit failed", db_mod->mod_file);
721 rv = -1;
722 }
723 return (rv);
724 }
725
726 /*
727 * Deinitialize one rule in databases.
728 */
729 int
db_deinit_rule(const struct rule * rule)730 db_deinit_rule(const struct rule *rule)
731 {
732 const struct db_elem *db;
733 int rv;
734
735 rv = 0;
736 STAILQ_FOREACH(db, rule->db_list, link)
737 if (db->ipa_db_mod->db_deinit_rule != NULL &&
738 db->ipa_db_mod->db_deinit_rule(rule->no) < 0) {
739 logmsgx(IPA_LOG_ERR, "module %s: rule %s: "
740 "db_deinit_rule failed", db->mod_file, rule->name);
741 rv = -1;
742 }
743 return (rv);
744 }
745
746 /*
747 * Update statistics for one rule.
748 */
749 int
db_update_rule(const struct rule * rule,const uint64_t * cnt)750 db_update_rule(const struct rule *rule, const uint64_t *cnt)
751 {
752 const struct db_elem *db;
753 int rv;
754
755 rv = 0;
756 STAILQ_FOREACH(db, rule->db_list, link)
757 if (db->ipa_db_mod->db_update_rule(rule->no, cnt,
758 &curdate) < 0) {
759 logmsgx(IPA_LOG_ERR, "module %s: rule %s: "
760 "db_update_rule failed", db->mod_file, rule->name);
761 rv = -1;
762 }
763 return (rv);
764 }
765
766 /*
767 * Append an accounting record for one rule.
768 */
769 int
db_append_rule(struct rule * rule,const uint64_t * cnt,int flush_cnt)770 db_append_rule(struct rule *rule, const uint64_t *cnt, int flush_cnt)
771 {
772 const struct db_elem *db;
773 int rv;
774
775 rv = 0;
776 STAILQ_FOREACH(db, rule->db_list, link)
777 if (db->ipa_db_mod->db_append_rule(rule->no, cnt,
778 &curdate) < 0) {
779 logmsgx(IPA_LOG_ERR, "module %s: rule %s: "
780 "db_append_rule failed", db->mod_file, rule->name);
781 rv = -1;
782 }
783
784 if (rule->append_tevent != NULL)
785 rule->append_sec = rule->append_tevent->event_sec;
786
787 if (flush_cnt)
788 rule->cnt = 0;
789
790 return (rv);
791 }
792
793 /*
794 * Set a rule active/inactive in databases it uses.
795 */
796 int
db_set_rule_active(const struct rule * rule,int active)797 db_set_rule_active(const struct rule *rule, int active)
798 {
799 const struct db_elem *db;
800
801 STAILQ_FOREACH(db, rule->db_list, link)
802 if (db->ipa_db_mod->db_set_rule_active != NULL &&
803 db->ipa_db_mod->db_set_rule_active(rule->no,
804 active) < 0) {
805 logmsgx(IPA_LOG_ERR, "module %s: rule %s: "
806 "db_set_rule_active(%d) failed", db->mod_file,
807 rule->name, active);
808 return (-1);
809 }
810 return (0);
811 }
812
813 #ifdef WITH_AUTORULES
814 /*
815 * Initialize one dynamic rule in databases, also initialize its
816 * limits and thresholds.
817 */
818 int
db_init_dynrule(const struct autorule * autorule,struct rule * rule)819 db_init_dynrule(const struct autorule *autorule, struct rule *rule)
820 {
821 if (!STAILQ_EMPTY(rule->db_list)) {
822 const struct db_elem *db;
823
824 STAILQ_FOREACH(db, rule->db_list, link) {
825 if (db->ipa_db_mod->db_init_dynrule == NULL) {
826 logmsgx(IPA_LOG_ERR, "module %s: autorule %s, "
827 "rule %s: db_init_dynrule: module does not "
828 "support dynamic rules", db->mod_file,
829 autorule->name, rule->name);
830 return (-1);
831 }
832 if (db->ipa_db_mod->db_init_dynrule(autorule->no,
833 rule->no, rule->name, rule->info) < 0) {
834 logmsgx(IPA_LOG_ERR, "module %s: autorule %s, "
835 "rule %s: db_init_dynrule failed",
836 db->mod_file, autorule->name, rule->name);
837 return (-1);
838 }
839 }
840 } else if (debug_db_null)
841 logdbg("rule %s: uses \"null\" database", rule->name);
842
843 mem_free(rule->info, m_anon);
844 rule->info = NULL;
845
846 #ifdef WITH_LIMITS
847 if (db_init_dynlimits(autorule, rule) < 0) {
848 logbt("db_init_dynrule");
849 return (-1);
850 }
851 #endif
852 #ifdef WITH_THRESHOLDS
853 if (db_init_dynthresholds(autorule, rule) < 0) {
854 logbt("db_init_dynrule");
855 return (-1);
856 }
857 #endif
858
859 return (0);
860 }
861 #endif /* WITH_AUTORULES */
862