/*-
 * Copyright (c) 2003-2004 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.
 *
 *   @(#)$Id: ipa_mod.h,v 1.4 2011/01/23 18:42:34 simon Exp $
 */

#ifndef IPA_MOD_H
#define IPA_MOD_H

#include <sys/types.h>

#include <regex.h>
#include <stdarg.h>
#include <time.h>

#ifdef __cplusplus
extern "C" {
#endif

#define IPA_MEMFUNC_API_VERSION	1	/* Version of ipa_memfunc API. */

#define IPA_MEMFUNC_FLAG_PTHREAD  0x01	/* Sync access to memory object. */
#define IPA_MEMFUNC_FLAG_OPTIMIZE 0x02	/* Optimize memory allocations. */

typedef struct ipa_mem_type_struct ipa_mem_type;
typedef struct ipa_marray_struct ipa_marray;
typedef struct ipa_mzone_struct ipa_mzone;

/*
 * Exported memory manipulation functions for module.
 */
typedef struct {
	unsigned int	api_ver;
	int		(*memfunc_init)(void);
	void		(*memfunc_deinit)(int);
	ipa_mem_type	*m_parser;
	ipa_mem_type	*(*mem_type_new)(const char *, const char *,
			    unsigned int);
	void		*(*mem_malloc)(size_t, ipa_mem_type *);
	void		*(*mem_calloc)(size_t, size_t, ipa_mem_type *);
	void		*(*mem_realloc)(void *, size_t, ipa_mem_type *);
	char		*(*mem_strdup)(const char *, ipa_mem_type *);
	int		(*mem_vasprintf)(ipa_mem_type *, char **,
			    const char *, va_list);
	void		(*mem_free)(void *, ipa_mem_type *);
	ipa_marray	*(*marray_init)(const char *, const char *,
			    unsigned int, void **, size_t, unsigned int,
			    unsigned int);
	void		(*marray_deinit)(ipa_marray *);
	int		(*marray_alloc)(ipa_marray *, unsigned int *, int);
	void		(*marray_free)(ipa_marray *, unsigned int);
	void		(*marray_minimize)(ipa_marray *);
	int		(*marray_check_index)(ipa_marray *, unsigned int);
	unsigned int	(*marray_nused)(ipa_marray *);
	ipa_mzone	*(*mzone_init)(const char *, const char *,
			    unsigned int, size_t, unsigned int, unsigned int);
	void		(*mzone_deinit)(ipa_mzone *);
	void		*(*mzone_alloc)(ipa_mzone *);
	void		(*mzone_free)(ipa_mzone *, void *);
	unsigned int	(*mzone_nused)(ipa_mzone *);
} ipa_memfunc;

/*
 * Versions of ipa_mod(3) APIs.
 */
#define IPA_AC_MOD_API_VERSION	2	/* Version of ipa_ac_mod API. */
#define IPA_DB_MOD_API_VERSION	2	/* Version of ipa_db_mod API. */
#define IPA_ST_MOD_API_VERSION	2	/* Version of ipa_st_mod API. */

/*
 * Modules flags.
 */
#define IPA_MOD_FLAG_PTHREAD_SAFE 0x1

/*
 * Log priority constants.
 */
enum {
	IPA_LOG_INFO =		   0,
	IPA_LOG_WARNING,	/* 1 */
	IPA_LOG_ERR		/* 2 */
};

/*
 * Type of parameter's argument.
 */
#define IPA_CONF_TYPE_INT32	 0	/* int32_t	*/
#define IPA_CONF_TYPE_UINT32	 1	/* uint32_t	*/
#define IPA_CONF_TYPE_INT64	 2	/* int64_t	*/
#define IPA_CONF_TYPE_UINT64	 3	/* uint64_t	*/
#define IPA_CONF_TYPE_STRING	 4	/* "string"	*/
#define IPA_CONF_TYPE_BYTES	 5	/* bytes	*/
#define IPA_CONF_TYPE_TIME	 6	/* time		*/
#define IPA_CONF_TYPE_VALUE	 7	/* value	*/
#define IPA_CONF_TYPE_PER_CENT	 8	/* per cent	*/
#define IPA_CONF_TYPE_BOOLEAN	 9	/* int		*/
#define IPA_CONF_TYPE_MISC	10	/* anything	*/

/*
 * IDs of section visible for modules.
 */
#define IPA_CONF_SECT_ROOT			 1
#define IPA_CONF_SECT_GLOBAL			 2
#define IPA_CONF_SECT_RULE			 3
#define IPA_CONF_SECT_LIMIT			 4
#define IPA_CONF_SECT_THRESHOLD			 5
#define IPA_CONF_SECT_AUTORULE			 6
#define IPA_CONF_SECT_RULEPAT			 7
#define IPA_CONF_SECT_RESTART			 8
#define IPA_CONF_SECT_REACH			 9
#define IPA_CONF_SECT_EXPIRE			10
#define IPA_CONF_SECT_STARTUP			11
#define IPA_CONF_SECT_SHUTDOWN			12
#define IPA_CONF_SECT_IF_REACHED		13
#define IPA_CONF_SECT_IF_NOT_REACHED		14
#define IPA_CONF_SECT_IF_ALL_REACHED		15
#define IPA_CONF_SECT_IF_ANY_REACHED		16
#define IPA_CONF_SECT_IF_ALL_NOT_REACHED	17
#define IPA_CONF_SECT_IF_ANY_NOT_REACHED	18
#define IPA_CONF_SECT_BELOW_THRESHOLD		19
#define IPA_CONF_SECT_EQUAL_THRESHOLD		20
#define IPA_CONF_SECT_ABOVE_THRESHOLD		21

/*
 * The offset for custom sections numbers.
 */
#define IPA_CONF_SECT_CUSTOM_OFFSET 0x80000000

/*
 * A structure for describing a parameter.
 */
typedef struct {
	const char	*param_name;
	int		arg_nargs;
	const char	*arg_pattern;
	regex_t		*arg_regexp;
	unsigned int	arg_type;
	const unsigned int *param_where;
	int		(*arg_parse)(void *);
} ipa_conf_param;

/*
 * A structure for describing a section.
 */
typedef struct {
	const char	*sect_name;
	unsigned int	sect_id;
	int		arg_nargs;
	const char	*arg_pattern;
	regex_t		*arg_regexp;
	unsigned int	arg_type;
	const unsigned int *sect_where;
	int		(*arg_parse)(void *);
} ipa_conf_sect;

/*
 * Configuration events constants.
 */
#define IPA_CONF_EVENT_GLOBAL_BEGIN			 0
#define IPA_CONF_EVENT_GLOBAL_END			 1
#define IPA_CONF_EVENT_RULE_BEGIN			 2
#define IPA_CONF_EVENT_RULE_END				 3
#define IPA_CONF_EVENT_LIMIT_BEGIN			 4
#define IPA_CONF_EVENT_LIMIT_END			 5
#define IPA_CONF_EVENT_THRESHOLD_BEGIN			 6
#define IPA_CONF_EVENT_THRESHOLD_END			 7
#define IPA_CONF_EVENT_AUTORULE_BEGIN			 8
#define IPA_CONF_EVENT_AUTORULE_END			 9
#define IPA_CONF_EVENT_RULEPAT_BEGIN			10
#define IPA_CONF_EVENT_RULEPAT_END			11
#define IPA_CONF_EVENT_CUSTOM_SECT_BEGIN		12
#define IPA_CONF_EVENT_CUSTOM_SECT_END			13
#define IPA_CONF_EVENT_STARTUP_BEGIN			14
#define IPA_CONF_EVENT_STARTUP_END			15
#define IPA_CONF_EVENT_SHUTDOWN_BEGIN			16
#define IPA_CONF_EVENT_SHUTDOWN_END			17
#define IPA_CONF_EVENT_RESTART_BEGIN			18
#define IPA_CONF_EVENT_RESTART_END			19
#define IPA_CONF_EVENT_REACH_BEGIN			20
#define IPA_CONF_EVENT_REACH_END			21
#define IPA_CONF_EVENT_EXPIRE_BEGIN			22
#define IPA_CONF_EVENT_EXPIRE_END			23
#define IPA_CONF_EVENT_IF_REACHED_BEGIN			24
#define IPA_CONF_EVENT_IF_REACHED_END			25
#define IPA_CONF_EVENT_IF_NOT_REACHED_BEGIN		26
#define IPA_CONF_EVENT_IF_NOT_REACHED_END		27
#define IPA_CONF_EVENT_IF_ALL_REACHED_BEGIN		28
#define IPA_CONF_EVENT_IF_ALL_REACHED_END		29
#define IPA_CONF_EVENT_IF_ANY_REACHED_BEGIN		30
#define IPA_CONF_EVENT_IF_ANY_REACHED_END		31
#define IPA_CONF_EVENT_IF_ANY_NOT_REACHED_BEGIN		32
#define IPA_CONF_EVENT_IF_ANY_NOT_REACHED_END		33
#define IPA_CONF_EVENT_IF_ALL_NOT_REACHED_BEGIN		34
#define IPA_CONF_EVENT_IF_ALL_NOT_REACHED_END		35
#define IPA_CONF_EVENT_BELOW_THRESHOLD_BEGIN		36
#define IPA_CONF_EVENT_BELOW_THRESHOLD_END		37
#define IPA_CONF_EVENT_EQUAL_THRESHOLD_BEGIN		38
#define IPA_CONF_EVENT_EQUAL_THRESHOLD_END		39
#define IPA_CONF_EVENT_ABOVE_THRESHOLD_BEGIN		40
#define IPA_CONF_EVENT_ABOVE_THRESHOLD_END		41

/*
 * Exported support functions for a module.
 */
typedef struct {
	void	(*print_string)(const char *);
	void	(*print_bytes)(const uint64_t *);
	void	(*print_time)(const uint64_t *);
	void	(*print_value)(const uint64_t *, unsigned int);
	void	(*print_boolean)(int);
	void	(*print_space)(void);
	void	(*print_param_name)(const char *, const char *);
	void	(*print_param_args)(const char *, va_list);
	void	(*print_param_end)(void);
	void	(*print_sect_name)(const char *, const char *);
	void	(*print_sect_args)(const char *, va_list);
	void	(*print_sect_begin)(void);
	void	(*print_sect_end)(void);
	void	(*open_log)(void);
	void	(*close_log)(void);
	void	(*logmsg)(const char *, int, int, const char *, va_list);
	void	(*logconferr)(const char *, int, const char *, va_list);
	int	(*local_sym_add)(char *, char *, int);
	int	(*local_sym_del)(const char *);
	int	(*global_sym_add)(char *, char *, int);
	int	(*global_sym_del)(const char *);
} ipa_suppfunc;

/*
 * Limit's events constants.
 */
#define IPA_LIMIT_EVENT_START			 0
#define IPA_LIMIT_EVENT_RESTART			 1
#define IPA_LIMIT_EVENT_RESTART_EXEC		 2
#define IPA_LIMIT_EVENT_REACH			 3
#define IPA_LIMIT_EVENT_REACH_EXEC		 4
#define IPA_LIMIT_EVENT_EXPIRE			 5
#define IPA_LIMIT_EVENT_EXPIRE_EXEC		 6
#define IPA_LIMIT_EVENT_UPDATED			 7
#define IPA_LIMIT_EVENT_STARTUP_IF_REACHED	 8
#define IPA_LIMIT_EVENT_STARTUP_IF_NOT_REACHED	 9
#define IPA_LIMIT_EVENT_SHUTDOWN_IF_REACHED	10
#define IPA_LIMIT_EVENT_SHUTDOWN_IF_NOT_REACHED 11

/*
 * Events bits for limit state.
 */
#define IPA_LIMIT_EVENT_START_SET	 (1 << IPA_LIMIT_EVENT_START)
#define IPA_LIMIT_EVENT_RESTART_SET	 (1 << IPA_LIMIT_EVENT_RESTART)
#define IPA_LIMIT_EVENT_RESTART_EXEC_SET (1 << IPA_LIMIT_EVENT_RESTART_EXEC)
#define IPA_LIMIT_EVENT_REACH_SET	 (1 << IPA_LIMIT_EVENT_REACH)
#define IPA_LIMIT_EVENT_REACH_EXEC_SET	 (1 << IPA_LIMIT_EVENT_REACH_EXEC)
#define IPA_LIMIT_EVENT_EXPIRE_SET	 (1 << IPA_LIMIT_EVENT_EXPIRE)
#define IPA_LIMIT_EVENT_EXPIRE_EXEC_SET	 (1 << IPA_LIMIT_EVENT_EXPIRE_EXEC)
#define IPA_LIMIT_EVENT_UPDATED_SET	 (1 << IPA_LIMIT_EVENT_UPDATED)

/* Number of limit's events. */
#define IPA_LIMIT_EVENT_NUM	8

/*
 * ipa_tm is almost the same as struct tm{}, but: only
 * tm_{year,mon,mday,hour,min,sec} fields are used and
 * tm_year and tm_mon are equal to real year and month values.
 */
typedef struct tm ipa_tm;

/*
 * Threshold's events constants.
 */
#define IPA_THRESHOLD_EVENT_BELOW	0
#define IPA_THRESHOLD_EVENT_EQUAL	1
#define IPA_THRESHOLD_EVENT_ABOVE	2

/*
 * Accounting module API.
 */
struct ipa_ac_mod {
	unsigned int	api_ver;
	unsigned int	mod_flags;
	const char	*ac_name;
	const ipa_suppfunc *suppfunc;
	const ipa_memfunc *memfunc;
	const char	*conf_prefix;
	ipa_conf_sect	*conf_sect_tbl;
	ipa_conf_param	*conf_param_tbl;
	int		(*conf_init)(void);
	int		(*conf_deinit)(void);
	int		(*conf_event)(unsigned int, unsigned int, const void *);
	int		(*conf_mimic_real)(void);
	int		(*conf_inherit)(unsigned int, unsigned int,
			    const char *);
	void		(*conf_show)(unsigned int, unsigned int);
	int		(*ac_pre_init)(void);
	int		(*ac_init_autorule)(unsigned int, const char *);
	int		(*ac_init_dynrule)(unsigned int, unsigned int,
			    const char *);
	int		(*ac_init_statrule)(unsigned int, const char *);
	int		(*ac_init)(void);
	int		(*ac_deinit_rule)(unsigned int);
	int		(*ac_deinit_autorule)(unsigned int);
	int		(*ac_deinit)(void);
	int		(*ac_get_stat)(const ipa_tm *);
	int		(*ac_get_rule_stat)(unsigned int, int, unsigned int,
			    int *, uint64_t *);
	int		(*ac_set_autorule_active)(unsigned int, int);
	int		(*ac_set_rule_active)(unsigned int, int);
	int		(*ac_set_limit_active)(unsigned int, unsigned int, int);
	int		(*ac_set_threshold_active)(unsigned int, unsigned int,
			    int);
	int		(*ac_limit_event)(unsigned int, unsigned int,
			    unsigned int);
	int		(*ac_threshold_event)(unsigned int, unsigned int,
			    unsigned int);
	int		(*ac_create_rule)(const char *, unsigned int,
			    const char *, const char *);
	int		(*ac_delete_rule)(const char *, unsigned int);
};

#define IPA_AC_MOD_ENTRY(x)	x ## _ac_mod

/*
 * Limit's state.
 */
struct ipa_limit_state {
	uint64_t	lim;
	uint64_t	cnt;
	unsigned int	event_date_set;
	ipa_tm		event_date[IPA_LIMIT_EVENT_NUM];
};

/*
 * Threshold's state.
 */
struct ipa_threshold_state {
	uint64_t	thr;
	uint64_t	cnt;
	ipa_tm		tm_from;
	ipa_tm		tm_updated;
};

/*
 * Database module API.
 */
struct ipa_db_mod {
	unsigned int	api_ver;
	unsigned int	mod_flags;
	const char	*db_name;
	const ipa_suppfunc *suppfunc;
	const ipa_memfunc *memfunc;
	const char	*conf_prefix;
	ipa_conf_sect	*conf_sect_tbl;
	ipa_conf_param	*conf_param_tbl;
	int		(*conf_init)(void);
	int		(*conf_deinit)(void);
	int		(*conf_event)(unsigned int, unsigned int, const void *);
	int		(*conf_mimic_real)(void);
	int		(*conf_inherit)(unsigned int, unsigned int,
			    const char *);
	void		(*conf_show)(unsigned int, unsigned int);
	int		(*db_pre_init)(void);
	int		(*db_init_dynrule)(unsigned int, unsigned int,
			    const char *, const char *);
	int		(*db_init_statrule)(unsigned int, const char *,
			    const char *);
	int		(*db_init_dynlimit)(unsigned int, unsigned int,
			    const char *, const char *, unsigned int,
			    const char *, const char *);
	int		(*db_init_statlimit)(unsigned int, const char *,
			    const char *, unsigned int, const char *,
			    const char *);
	int		(*db_init_dynthreshold)(unsigned int, unsigned int,
			    const char *, const char *, unsigned int,
			    const char *, const char *);
	int		(*db_init_statthreshold)(unsigned int, const char *,
			    const char *, unsigned int, const char *,
			    const char *);
	int		(*db_init)(void);
	int		(*db_get_limit_state)(unsigned int, unsigned int,
			    struct ipa_limit_state *);
	int		(*db_set_limit_state)(unsigned int, unsigned int,
			    const struct ipa_limit_state *, int);
	int		(*db_get_threshold_state)(unsigned int, unsigned int,
			    struct ipa_threshold_state *);
	int		(*db_set_threshold_state)(unsigned int, unsigned int,
			    const struct ipa_threshold_state *);
	int		(*db_deinit_threshold)(unsigned int, unsigned int);
	int		(*db_deinit_limit)(unsigned int, unsigned int);
	int		(*db_deinit_rule)(unsigned int);
	int		(*db_deinit)(void);
	int		(*db_append_rule)(unsigned int, const uint64_t *,
			    const ipa_tm *);
	int		(*db_update_rule)(unsigned int, const uint64_t *,
			    const ipa_tm *);
	int		(*db_update_limit)(unsigned int, unsigned int,
			    const uint64_t *, const ipa_tm *);
	int		(*db_limit_event)(unsigned int, unsigned int,
			    unsigned int, const ipa_tm *, const ipa_tm *);
	int		(*db_update_threshold)(unsigned int, unsigned int,
			    const uint64_t *, const ipa_tm *, const ipa_tm *);
	int		(*db_set_rule_active)(unsigned int, int);
	int		(*db_set_limit_active)(unsigned int, unsigned int, int);
	int		(*db_set_threshold_active)(unsigned int, unsigned int,
			    int);
};

#define IPA_DB_MOD_ENTRY(x)	x ## _db_mod

/*
 * Statistics of one record from database.
 */
struct ipa_rule_stat {
	uint64_t	cnt;
	unsigned int	year;
	unsigned char	mon;
	unsigned char	mday;
	unsigned char	h1, m1, s1;
	unsigned char	h2, m2, s2;
};

/*
 * Description of one rule/limit/threshold.
 */
struct ipa_entity_desc {
	char		*name;
	char		*info;
};

/*
 * Statistics module API.
 */
struct ipa_st_mod {
	unsigned int	api_ver;
	unsigned int	mod_flags;
	const char	*st_name;
	const ipa_suppfunc *suppfunc;
	const ipa_memfunc *memfunc;
	const char	*conf_prefix;
	ipa_conf_sect	*conf_sect_tbl;
	ipa_conf_param	*conf_param_tbl;
	int		(*conf_init)(void);
	int		(*conf_deinit)(void);
	int		(*conf_event)(unsigned int, unsigned int, const void *);
	int		(*conf_mimic_real)(void);
	int		(*conf_inherit)(unsigned int, unsigned int,
			    const char *);
	void		(*conf_show)(unsigned int, unsigned int);
	int		(*st_pre_init)(void);
	int		(*st_init_rule)(unsigned int, const char *);
	int		(*st_init_limit)(unsigned int, const char *,
			    unsigned int, const char *);
	int		(*st_init_threshold)(unsigned int, const char *,
			    unsigned int, const char *);
	int		(*st_init)(void);
	int		(*st_deinit_threshold)(unsigned int, unsigned int);
	int		(*st_deinit_limit)(unsigned int, unsigned int);
	int		(*st_deinit_rule)(unsigned int);
	int		(*st_deinit)(void);
	int		(*st_get_rule_info)(unsigned int, ipa_mem_type *,
			    char **);
	int		(*st_get_limit_info)(unsigned int, unsigned int,
			    ipa_mem_type *, char **);
	int		(*st_get_threshold_info)(unsigned int, unsigned int,
			    ipa_mem_type *, char **);
	int		(*st_get_rules_list)(const char *, const regex_t *,
			    ipa_mem_type *, unsigned int*,
			    struct ipa_entity_desc **);
	int		(*st_get_limits_list)(unsigned int, const char *,
			    const regex_t *, ipa_mem_type *, unsigned int*,
			    struct ipa_entity_desc **);
	int		(*st_get_thresholds_list)(unsigned int, const char *,
			    const regex_t *, ipa_mem_type *, unsigned int *,
			    struct ipa_entity_desc **);
	int		(*st_get_rule_stat)(unsigned int, const ipa_tm *,
			    const ipa_tm *, int, ipa_mem_type *, unsigned int *,
			    struct ipa_rule_stat **);
	int		(*st_get_limit_stat)(unsigned int, unsigned int,
			    const ipa_tm *, const ipa_tm *, ipa_mem_type *,
			    unsigned int *, struct ipa_limit_state **);
	int		(*st_get_threshold_stat)(unsigned int, unsigned int,
			    struct ipa_threshold_state *);
};

#define IPA_ST_MOD_ENTRY(x)	x ## _st_mod

#ifdef __cplusplus
}
#endif

#endif /* !IPA_MOD_H */
