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