Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
IPA.CONF(5)		      File Formats Manual		   IPA.CONF(5)

NAME
       ipa.conf	-- ipa(8) configuration	file

DESCRIPTION
       The ipa.conf file is a configuration file for ipa(8).  This file	or any
       other one specified in the -f option in the ipa(8) command line is read
       when ipa(8) starts working or receives a	SIGHUP signal.

FILE FORMAT
       The  ipa.conf  file can be quite	simple and can be complex enough.  The
       main idea is to place as	much as	possible  into	configuration  file(s)
       instead of writing external programs to do accounting related tasks.

       This manual page	contains the complete file format description and com-
       plete documentation about all features of ipa(8).

       There  is  an example almost after each paragraph.  Since IPA distribu-
       tion does not have  any	module,	 ipa_ipfw,  ipa_ip6fw,	ipa_atest  and
       ipa_db_sdb  modules  are	 used  in  examples just because they were the
       first modules designed for IPA.

   General syntax
       Any logical line	in the configuration file can be  written  in  several
       text  lines for indenting purpose.  There is not	any rule in which line
       to place	reserved words,	arguments and special symbols.	If some	format
       allows one space	character, then	as much	as  needed  space  characters,
       tab  characters and newline characters can be written there for indent-
       ing.  All elements in a configuration file are case sensitive.  A  con-
       figuration file consists	of sections, parameters	and comments.

   Comments
       There  are shell-like and C-like	comments.  If you use a	C-like comment
       in a shell-like comment,	then a C-like comment is ignored.

       Example:

	   # Shell-like	comment.
	   /* C-like comment. */
	   /*
	    * Another C-like comment.
	    */

   Sections and	parameters
       A section consists of its name, optional	arguments  and	its  body.   A
       section's body should be	placed in curly	braces:

	   section [[=]	argument] {
	       /* Parameters and sections. */
	   }

       A parameter consists of its name	and optional arguments.	 Every parame-
       ter should have the `;' character at the	end of its arguments list:

	   parameter [[=] argument];

       The  `='	character after	the section's or parameter's name is optional.
       Some parameters look like variables (it is naturally  to	 use  the  `='
       character  for them), another ones look like instructions.  In any case
       you can choose a	syntax you like	more.

       An argument can contain strings:

	   "string"

       The ``\t'', ``\n'', ``\\'' and ``\"'' sequences should be used for rep-
       resenting tab, newline, back-slash and double quote characters inside a
       string.	If it is needed	to split a string to several lines,  then  use
       one  `\'	 character  at	the  end of the	current	line (do not put extra
       space characters	after the back-slash character).  If a string is writ-
       ten in several lines without `\'	characters, then each newline  charac-
       ter is added to a string.

   Macro variables
       The definition of a macro variable has the following form:

	   ${variable} = "string";

       A macro variable	name consists of letters, digits, '_' symbols and dol-
       lar  signs.  What is a letter is	checked	with isalpha(3)	function which
       uses current locale.

       A value of any macro variable should be a string, when a	macro variable
       is expanded then	first and last double quotes of	its value are removed.

       Macro variables can be local or global.	A macro	variable is global  if
       it  is  defined outside any section, else a macro variable is local.  A
       local macro variables are local for all nested sections and for all ex-
       ternal sections.	 Local macro variables can hide	global ones.

       There are some predefined macro variables:

       ${$}	    - a	`$' character;
       ${rule}	    - the current rule name;
       ${limit}	    - the current limit	name;
       ${sublimit}  - the current sublimit name;
       ${threshold} - the current threshold name;
       ${autorule}  - the current autorule name.

       Any macro variable (including predefined	ones) except ${$} can be rede-
       fined if	needed.	 It is not recommended to redefine  or	delete	prede-
       fined macro variables in	modules.

       Macro  variable	${$}  cannot  be used for constructing macro variables
       names (see the example).

       Macro variable can be used almost anywhere in the  configuration	 file.
       When  macro  variable  is  expanded,  then its value is expanded	recur-
       sively.	Macro variables	are expanded at	the moment of their usage  and
       not  at	the  moment of their definition.  Macro	variables are expanded
       also in strings.	 Macro variables is a feature of the internal configu-
       ration file parser, so ${rule} macro variable cannot  be	 used  in  au-
       torules	and  in	rules patterns (see information	about substitutions in
       command strings).

       Example:

	   ${a}	= "${b}";      # Definition of ${a}.
	   ${b}	= "1";	       # Definition of ${b}.
	   param = ${a};       # Expands to 1.
	   ${b}	= "2";	       # Redefine ${b}.
	   param = ${a};       # Expands to 2.

	   param = "${$}{b}";  # Expands to "${b}" (sequence of	characters).

	   section {
	       ${a} = "1";     # Definition of local ${a} which	hides
			       # global	${a}.
	       ${c} = "4";     # Definition of local ${c}.
	       param = ${a};   # Expands to 1.
	       subsection {
		   ${a}	= "2"; # Redefine local	${a}.
		   ${b}	= "3"; # Redefine global ${b}.
	       }
	       param = ${a};   # Expands to 2.
	       param = ${b};   # Expands to 3.
	   }

	   # param = ${c};     <-- Error: ${c} is not defined as global.

   Including files
       Configuration information can be	kept in	several	 configuration	files.
       Files are included with the help	of the following parameters:

	   include "/path/file";
	   include_files "/directory/pattern";

       The  include  parameter includes	one file.  The include_files parameter
       includes	files which match the given shell pattern from	the  specified
       directory.

       These  parameters can be	used anywhere in the configuration file	except
       inside modules' sections, and contents of included files	 will  be  in-
       cluded  immediately.   Files can	be included from included files.  Each
       included	file should have correctly  specified  parameters  with	 argu-
       ments, comments and sections with arguments, but	it can have not	closed
       sections.

       POSIX  regular expressions can be used as patterns in include_files pa-
       rameters	as well, to enable them	set the	posix_re_pattern parameter  to
       ``yes''	before	parameters  which include files	with POSIX regular ex-
       pression	patterns (the default value is ``no''):

	   posix_re_pattern = <boolean>;

       This parameter should not be placed in any section.

       Included	files must be owned by the user	who run	ipa(8) and must	not be
       writable	for group and other users.  If files  are  included  with  the
       help of the include_files parameter, then a directory specified in this
       parameter also should have the same properties.

       Examples:

	   posix_re_pattern = yes;
	   include "/usr/local/etc/ipa.local.conf";
	   include_files "/usr/local/etc/ipa/LAN/.";

       First  parameter	includes one file, second parameter includes each file
       in the given directory (the ``.'' POSIX regular expression means	 ``any
       character'').

	   /* posix_re_pattern = no; */
	   include_files "/usr/local/etc/ipa/LAN/*";

       Here  a	shell  pattern is used.	 First string should be	uncommented if
       previously POSIX	regular	expressions were used.

   Using accounting modules
       IPA accounting modules are used for gathering statistics.   ipa(8)  and
       accounting  modules  work  together via the ipa_ac_mod API described in
       the ipa_mod(3) manual page.

       The ac_mod parameter dynamically	loads the given	accounting module:

	   ac_mod "file_name";

       This parameter should not be placed in any section.  Several accounting
       modules can be used at one time.

       The given file name should be a	shared-object  (shared	library)  file
       name if ipa(8) uses dlopen(3) interface or it can be a .la file name if
       the libtool's ltdl library interface is used.

       Example:

	   ac_mod "ipa_ipfw.so";
	   ac_mod "ipa_ip6fw.so";

       These parameters	load two accounting modules.

   Using database modules
       IPA  database  modules  are  used  for storing statistics in databases.
       ipa(8) and database modules work	together via the  ipa_db_mod  API  de-
       scribed in the ipa_mod(3) manual	page.

       The db_mod parameter loads the given database module:

	   db_mod "file_name";

       This  parameter	should not be placed in	any section.  Several database
       modules can be used at one time.

       The given file name should be a	shared-object  (shared	library)  file
       name if ipa(8) uses dlopen(3) interface or it can be a .la file name if
       the libtool's ltdl library interface is used.

       Example:

	   db_mod "ipa_db_sdb.so";

       This parameter loads one	database module.

   Configuring modules
       Documentation  for  some	 IPA module should give	all information	how to
       configure it.  Usually configuration of a IPA module is	integrated  to
       the configuration file ipa.conf(5).

       Each  module has	a configuration	prefix,	which is used for distinguish-
       ing module's sections and parameters.  If there	is  a  parameter  like
       this one:

	   prefix:parameter [[=] argument];

       then  ipa(8) will try to	find a loaded module with configuration	prefix
       ``prefix'', then	ipa(8) will give this parameter	 for  parsing  to  the
       found module.

       Sections	also can have prefixes:

	   prefix:section [[=] argument] {
	       /* Module's parameters and sections. */
	   }

       In  this	 case  parameters  and	sections inside	such section should be
       written without a prefix	and this section and all its internal sections
       and parameters will be passed to	the appropriate	module for parsing.

       Documentation for some module should describe a module itself, module's
       configuration prefix, database or accounting system name	and  all  mod-
       ule's parameters	and sections.

       Example:

	   sdb:	{
	       allow_symlinks =	yes;
	   }

	   ipfw:debug =	1;

       Given  section's	 name  can  confuse one, but everything	is correct.  A
       module can have empty section's and parameter's name.

   Units of statistics
       Arguments of some parameters and	sections can be	bytes,	time  and  un-
       signed	64-bit	 integer  numbers.   Such  data	 type  is  defined  as
       IPA_CONF_TYPE_VALUE in ipa_mod(3).  Sometimes it	is  desirable  to  use
       only one	data type for such values, because ``10'', ``10m'' and ``10M''
       are correct values and mean 10, 10 minutes and 10 Mbytes	respectively.

       The  value_units	parameter can be used for specifying desired data type
       for arguments with IPA_CONF_TYPE_VALUE data type	 and  for  controlling
       their real values:

	   value_units = <type>;

       This  parameter should not be placed in any section and it is better to
       place it	before other parameters	and sections.  It accepts the  follow-
       ing values: ``any'' (the	default	value),	``time'', ``bytes'' and	``num-
       ber''.

       Parameters  limit,  threshold, threshold_deviation and sublimit section
       accept arguments	with IPA_CONF_TYPE_VALUE data type.

   Accounting rules
       ipa(8) performs accounting based	on rules.  There are  static  and  dy-
       namic  rules.   A  static rule is described in the rule section.	 A dy-
       namic rule does not have	description in the configuration file, but  it
       is  generated  on-the-fly  from some autorule described in the autorule
       section.

       Several rules (static, dynamic) can share settings.  There are  several
       ways  to	do this.  The first way	is using the global section.  The sec-
       ond way is using	rulepat	(rules patterns) sections.  And	the third  way
       is specifying common settings for dynamic rules in autorule sections.

       If  some	rule (static, dynamic) does not	have settings for some section
       or parameter, then it inherits settings from matched  rulepat  section,
       then  it	 inherits settings from	the global section; if there are still
       some unspecified	sections or  parameters,  then	default	 settings  are
       used.   Run  ipa(8) with	-tt switches to	see real values	of all parame-
       ters.

       Following parameters can	be used	in global, rulepat, rule and  autorule
       sections:   ac_list,   db_list,	 append_time,  update_time,  worktime,
       ctl_rule_acl, debug_exec, debug_limit, debug_limit_init,	 debug_thresh-
       old, debug_threshold_init.

   Using accounting systems
       The ac_list parameter specifies a list of used accounting systems:

	   ac_list = <list>;

       <List>  is a set	of names separated by a	space character.  To get names
       of accounting systems read documentations for modules you specified  in
       ac_mod parameters.

       If  some	rule has the ac_list parameter,	then accounting	systems	listed
       in its argument will be asked for statistics for	this rule.  This para-
       meter allows to create per rule accounting systems list.

       There is	one built-in accounting	system null:  this  accounting	system
       always returns 0	as statistics.	If the ac_list parameter is not	speci-
       fied and	is not inherited, then the null	accounting system is used.

       Example:

	   ac_mod "ipa_ipfw.so";
	   ac_mod "ipa_ip6fw.so";

	   global {
	       ac_list = ipfw ip6fw;
	   }

       Here two	accounting systems are specified.

   Using databases
       The db_list parameter specifies a list of used databases:

	   db_list = <list>;

       <List>  is a set	of names separated by a	space character.  To get names
       of databases read documentations	for modules you	 specified  in	db_mod
       parameters.

       If  some	 rule  has the db_list parameter, then databases listed	in its
       argument	will be	used for storing statistics for	this rule.  This para-
       meter allows to create per rule databases list.	The  same  corresponds
       to limits and thresholds.

       There  is one built-in database null: data sent to this database	is not
       kept anywhere.  If the db_list parameter	is not specified  and  is  not
       inherited, then the null	database is used.

       Example:

	   db_mod "ipa_db_sdb.so";

	   global {
	       db_list = sdb;
	   }

       Here one	database is specified.

   Accounting per period of a week
       By default accounting is	performed for all days in a week, but account-
       ing can be performed only for some time intervals in a week.  The work-
       time  parameter specifies time intervals	when accounting	should be per-
       formed:

	   worktime = <X> h1:m1-h2:m2 [h1:m1-h2:m2];
	   worktime = <X> *;

       <X> means a week	day.  Valid values for <X> are:	`S' Sunday,  `M'  Mon-
       day,  `T'  Tuesday, `W' Wednesday, `H' Thursday,	`F' Friday, `A'	Satur-
       day.  There can be only one record for each day.	 Time intervals	cannot
       be overlapped or	be placed not in the order.

       00:00-24:00 interval or the `*' character means whole day.

       When worktime allows to perform accounting, then	the section  where  it
       is placed is called ``active'', else it is called ``inactive''.

       What  exactly  this  parameter defines for autorules, rules, limits and
       thresholds read in the appropriate paragraphs.

       Note that time intervals	given in the worktime parameter	do not guaran-
       tee that	exactly	the same time intervals	will appear in	the  database,
       because	the running copy of ipa(8) can have low	priority or the	system
       can be to busy.

       The end of one time interval can	be the start of	the next  time	inter-
       val, this feature is only useful	for rules (see below).

       Example:

       Perform accounting only at Monday, Tuesday and Wednesday:

	   worktime = M	* T * W	*;

       Perform accounting at Thursday from 8:00	till 14:30 and from 18:20 till
       21:00, at Sunday	from midnight till 10:35 (the value is written in sev-
       eral lines just for indenting):

	   worktime = H	08:00-14:30 18:20-21:00
		      S	00:00-10:35;

   Database time intervals
       The  update_time	parameter determines time interval when	statistics for
       some rule should	be updated:

	   update_time = <time>;

       If this parameter is omitted, then the default value is 1 minute.

       The append_time parameter determines time interval when a  new  statis-
       tics record for some rule should	be appended:

	   append_time = <time>;

       This  parameter does not	have a default value.  A new statistics	record
       for each	rule is	appended to the	database at the	end of each day	in any
       case.

       Usually the value of the	append_time  parameter	is  greater  than  the
       value of	the update_time	parameter.

       ipa(8) tries to combine several time events into	one to reduce resource
       usage,  this  feature  has another interesting moment.  For example, if
       update_time is 5	minutes, then ipa(8) always schedules time events  for
       this parameter at 00:00,	00:05, 00:10 and so on.

       There  are  programs  that can change UTC and local time, also the time
       zone can	change itself.	Such events  can  cause	 ``some	 time  related
       problems	 occurred''  non  fatal	errors in ipa(8).  Too small values of
       parameters update_time and append_time can cause	more such errors.  For
       example,	if you synchronize time	very often and the value  of  the  up-
       date_time  parameter  is	nearly equal to	the time interval of time syn-
       chronization, then you can receive a lot	of such	warning	messages.

       The sensitive_time parameter allows to specify how time events are sen-
       sitive to time changes:

	   sensitive_time = <time>;

       By default the value is 30  seconds.   This  parameter  should  not  be
       placed in any section.

       The  wakeup_time	 parameter  specifies maximum number of	seconds	ipa(8)
       can sleep.  This	parameter tells	ipa(8) when to wake up	and  check  if
       everything is correct with time,	time zone, etc.:

	   wakeup_time = <time>;

       The  default  value is 10 minutes.  This	parameter should not be	placed
       in any section.

       Example:

	   global {
	       update_time = 30s;
	       append_time = 1h	30m;
	   }

       The `s' character means seconds,	`m'  minutes,  `h'  hours  (spaces  in
       <time>  are optional).  If <time> is specified as a complex value, then
       hours should be placed before minutes and seconds,  minutes  should  be
       placed before seconds.

   Descriptions	of rules, limits and thresholds
       Sections	 rule,	limit  and  threshold  can have	the optional parameter
       info, which is passed to	the database and is used for describing	a sec-
       tion:

	   info	= "string";

       The value of this parameter should not contain `\n'  and	 `\t'  charac-
       ters.   Usually	this value should help to recall what this rule, limit
       or threshold is used for.

       A dynamic rule gets its description from	an accounting module that gen-
       erates it, so you cannot	specify	descriptions for dynamic rules in  the
       configuration file.

       Example:

	   rule	10.1.2.3-in {
	       info = "My traffic from ISP";
	       /* ... */
	   }

       Sometimes  rule's name is not very informative, so describing a rule is
       a good idea.

   Names of rules, limits, thresholds and autorules
       Any symbol in any name must be letter, digit or punctuation symbol from
       the ASCII character set.

       Any name	cannot contain double quote, '/' and '\' symbols.

       You should give such names that are also	valid rules  names  for	 data-
       bases you use.

       These  restriction  also	 work  for dynamic rules and for names used in
       commands	in ictl	parameters.

   Static rules
       Static rules are	called ``static'' because they exist in	the configura-
       tion file and any accounting module cannot delete them.

       The rule	section	describes settings for one static rule:

	   rule	<rule-name> {
	       /* Rule's parameters and	sections. */
	   }

       The rule	section	does not have any mandatory settings.	If  some  rule
       does  not  have any sections and	parameters, then it is called an empty
       rule.  It is obvious that empty rules are senseless, so any  rule  usu-
       ally has	some parameters	(own or	inherited).

       If  a  rule has the worktime parameter, then a new accounting record is
       appended	to the database	when a new time	interval begins.  If a rule is
       inactive, then all its limits and thresholds are	inactive as well.

       Example:

	   ac_mod "ipa_ipfw.so";
	   ac_mod "ipa_ip6fw.so";
	   db_mod "ipa_db_sdb.so";

	   rule	local.traf {
	       ac_list = ipfw ip6fw;
	       db_list = sdb;
	       info = "Traffic to my LAN";
	       sdb:db_group = staff;
	       ipfw:rules = 100	200 300;
	       ip6fw:rules = 1.10;
	   }

       Here a rule uses	two accounting systems and one database.  It also  has
       a description and several modules' specific parameters.

   Running commands
       There  are  several  sections which allow to specify a list of commands
       which should be run if some event occurred.  The	exec parameter is used
       for running commands:

	   exec	[<user>] "/path/command	[arguments]";

       The exec	parameter without <user> runs a	command	with privileges	of the
       user who	run ipa(8), that is no actions in changing user	or groups  are
       performed.

       The  exec  parameter  with <user> runs a	command	with privileges	of the
       given user.  A user can be given	only by	its name.  ipa(8) will get UID
       and GIDs	of the user just before	running	a command.  This parameter can
       be used if ipa(8) is run	by the super-user only.

       If is needed to use name	of the rule in some command string in  rulepat
       or autorule section, then use substitutions.  Two substitutions are de-
       fined: %rule% means the name of the rule, %% means the `%' character.

       These  substitutions do not work	in command strings placed in rule sec-
       tions, use macro	variable ${rule} and single `%'	 character  there  in-
       stead.

       By  default  commands should be given with absolute pathname, but it is
       possible	to specify commands with  relative  pathnames,	just  set  the
       only_abs_paths parameter	to ``no'' (the default value is	``yes''):

	   only_abs_paths = <boolean>;

       All  commands are run by	a command shell, so any	shell-specific command
       line constructions can be used:

	   <shell_path>	<shell_arg1> /path/command [arguments]

       Note that the standard input (stdin), standard output (stdout) and  the
       standard	error (stderr) are handled in the same way as in ipa(8).

       <Shell_path>  is	 determined  when  IPA	is  built  (see	 output	of the
       ``ipa -v'' command for the real pathname), but it can be	 redefined  in
       the shell_path parameter:

	   shell_path =	"/path/shell";

       <Shell_arg1>  is	equal to ``-c''	by default, but	it can be redefined in
       the shell_arg1 parameter:

	   shell_arg1 =	"<arg1>";

       If there	are not	enough resources and ipa(8) is not able, for  example,
       to  fork(2)  a child to run a commands list, then ipa(8)	will exit with
       an error	code.  But if any error	occurred in a child which runs a  com-
       mand,  then ipa(8) will ignore this error and a child simply will log a
       warning message.	 There is no a portable	way to implement a better han-
       dling of	such errors.

       Parameters only_abs_paths, shell_path  and  shell_arg1  should  not  be
       placed in any section.

       Example:

	   startup {
	       exec "/bin/echo \"ipa started\" | mail me";
	       exec nobody "/usr/local/bin/something";
	   }

	   only_abs_path = no;

	   shutdown {
	       exec "echo \"ipa	stopped\" | mail me";
	   }

	   rulepat "^client" {
	       startup {
		   exec	"command %rule%";
	       }
	   }

	   rule	1 {
	       shutdown	{
		   exec	"echo rule off >> /tmp/${rule}.log";
	       }
	   }

       In  the first section the ``mail'' command is given without an absolute
       pathname.  This is correct because only the first  command  is  checked
       for an absolute pathname, ipa(8)	does not interpret shell-specific com-
       mand line constructions.

       In the rulepat section substitution %rule% is used and in the rule sec-
       tion  macro variable ${rule} is used for	inserting the name of the rule
       to the command string.

   Running commands at startup and shutdown
       One can specify which commands should be	run when ipa(8)	 starts	 (fin-
       ishes)  its work	in startup (shutdown) sections.	 These sections	can be
       placed alone (global commands) and in autorule, rulepat,	 rule,	limit,
       sublimit	and threshold sections.

       If  these  sections are placed alone (see below usage of	these sections
       inside other sections), then they  can  contain	only  sync_exec,  ictl
       (only inside startup) and exec parameters.

       The algorithm of	running	commands in startup (shutdown) sections	is the
       following:

       1.     run global commands;

       2.     run commands from	rule sections;

       2a.    in each rule section run commands	for limits and thresholds;

       2b.    in each limit section run	commands for its sublimits.

       When  ipa(8)  rereads the configuration file (when it receives a	SIGHUP
       signal),	then commands in startup sections are ignored,	but  new  com-
       mands for shutdown sections will	be used.

       Example:

	   startup {
	       exec "command1";
	   }

	   rule	1 {
	       startup {
		   exec	"command2";
	       }
	       limit 1 {
		   /* ... */
		   startup {
		       exec "command3";
		   }
	       }
	   }

	   rule	2 {
	       startup {
		   exec	"command4";
	       }
	   }

       Here commands are run in	the following order on startup:	command1, com-
       mand2, command3 and command4.

   Running commands synchronously and asynchronously
       There  are  two	regimes	of running commands: synchronous and asynchro-
       nous.  In synchronous regime ipa(8) is waiting for the exit of  running
       commands.   In  asynchronous  regime ipa(8) having run commands,	is not
       waiting for the exit of running commands	and continues its work.

       By default commands in all startup and shutdown sections	are  run  syn-
       chronously, in all other	sections commands are run asynchronously.

       The  sync_exec  parameter allows	to specify synchronous or asynchronous
       regime for any section:

	   sync_exec = <boolean>;

       This parameter can be used in any section which	accepts	 exec  parame-
       ters.

       Example:

	   startup {
	       sync_exec = no;
	       exec "/path/something";
	   }

       In  this	 example  default synchronous regime of	the startup section is
       changed to asynchronous.

   About statistics
       In IPA statistics is 64-bit unsigned integer numbers.   Statistics  can
       be  whatever  (time,  bytes or numbers).	 If some rule uses several ac-
       counting	systems, then ipa(8) summarizes	statistics got from  each  ac-
       counting	system.	 Usually an accounting module returns positive statis-
       tics, but it can	return negative	statistics.  Any database gets statis-
       tics as 64-bit unsigned integer numbers together	with the current local
       time.

       Internally  each	 rule  has  two	 64-bit	unsigned integer counters: one
       counter for positive statistics and another one	for  negative  statis-
       tics.  In any time one of these counters	is equal to zero.  If the neg-
       ative  statistics  counter is overflowed, then ipa(8) reports about oc-
       curred problem and exits	since such overflow means wrong	configuration.
       If the positive statistics counter is overflowed, then ipa(8) asks  the
       database	 to append a new statistics record for a rule to store statis-
       tics which does not fit the size	of its internal	counter.

       Internally any limit or threshold has the same  two  counters,  but  if
       limit's or threshold's positive or negative counter is overflowed, then
       ipa(8)  reports	about  occurred	 problem and exits since such overflow
       means wrong configuration.  Also	each threshold	has  several  counters
       for each	time slice (signs of counters are kept in a bitmap).

       Usually	positive  statistics  is greater than negative statistics, but
       this is not required.  Only positive statistics is stored in the	 data-
       base  and  while	 ipa(8)	 is running negative statistics	is kept	in its
       memory, but when	ipa(8) exits and some rule (limit  or  threshold)  has
       negative	 statistics, then this negative	statistics is lost (a log mes-
       sage will be sent).  In other words, ipa(8) is able to subtract statis-
       tics from the current value of  its  positive  statistics  counter  and
       there  is not any way to	subtract statistics from old statistics	in the
       database.

   Limits: introduction
       A limit should be considered with the context of	some rule.   Sometimes
       limits  in  IPA are called triggers.  If	it is necessary	to do some ac-
       tions when statistics for some rule reaches some	value during some time
       period, then the	limit section should be	used.  This section  can  have
       several sections	and must have at least one parameter named limit:

	   limit <limit-name> {
	       limit = <limit-value>;
	       /* Limit's parameters and sections. */
	   }

       One  rule  can  have several limits.  If	a rule has at least one	limit,
       then it will no inherit any limits from the matched rulepat section.

       Any limit has 64-bit unsigned integer counter for positive  statistics.
       This  counter  is  updated synchronously	with a rule's counter.	If the
       counter becomes equal to	or greater than	the value of the limit parame-
       ter, then a limit is treated as reached and its counter will not	be up-
       dated any more.

       <Limit-value> can be: bytes, time or  unsigned  64-bit  integer	number
       (see examples below); and it can	be equal to zero.

       A  limit	 can  pass  several states: a limit is not reached, a limit is
       reached (plus optionally	running	commands), a reached limit is  expired
       (plus  optionally running commands) and pseudo state when a not reached
       limit should be restarted.  The limit section can have some  parameters
       and some	sections which determine a limit's states (described below).

       If  a  limit  is	 not reached, then its statistics is checked each time
       when its	rule is	updated	(this time interval is not more	than the value
       of the update_time parameter).

       Example:

	   rule	my-account {
	       /* Rule's parameters and	sections. */
	       limit 1 {
		   limit = 1M 500K;
		   info	= "Bytes limit";
	       }
	       limit 2 {
		   limit = 2h 30m;
		   info	= "Time	limit";
	       }
	       limit 3 {
		   limit = 1234567890;
		   info	= "Numerical limit";
	       }
	   }

       There are three limits in one rule in this example.

       When the	value of the limit parameter is	given as bytes,	then  the  `T'
       character  means	 Tbytes, `G' Gbytes, `M' Mbytes, `K' Kbytes, `B' bytes
       (spaces are optional).  If a value is specified	as  a  complex	value,
       then  Tbytes  should  be	 placed	 before	 Gbytes	 and Mbytes and	so on.
       1 Kbyte is equal	to 1024	bytes.

   Restarting a	not reached limit
       The restart parameter in	the restart section  allows  to	 specify  time
       when a not reached limit	should be restarted with zeroed	(flushed) pos-
       itive and negative counters:

	   limit <limit-name> {
	       /* Limit's parameters and sections. */
	       restart {
		   restart = <restart-time>;
		   /* Commands.	*/
	       }
	   }

       The  time when a	new limit was created or a reached limit was restarted
       again is	known as ``start time''.  The <restart-time> value is relative
       to limit's start	time (see example).

       The restart section can contain optional	commands which will be run  at
       the moment of limit restart.

       Accounting systems used by limit's rule are informed when a not reached
       limit  is  restarted.  So if you	do not specify commands	in the restart
       section,	then some actions still	can be performed  by  accounting  sys-
       tems.

       If  a limit does	not have the restart parameter,	then this limit	(if it
       is not reached) cannot be  automatically	 restarted.   But  it  can  be
       restarted  by  the ipactl(8) utility or by ictl parameters and all com-
       mands from the restart section will be run.

       A not reached limit can restart only when its rule is active.

       Example 1:

	   rule	my.traf	{
	       ac_list = ipfw;
	       ipfw:rules = 100	200;
	       limit 1 {
		   limit = 1G;
		   restart {
		       restart = 20h 30m;
		   }
	       }
	   }

       Here the	value of the restart parameter is added	to limit's start  time
       and  calculated	value  is time when a limit should be restarted.  Here
       restart time is simply a	number of seconds from limit's start time.

       The `s' character means seconds,	`m' minutes, `h' hours,	`D'  days  and
       `W' weeks.

       Example 2:

	   rule	my.traf	{
	       ac_list = ipfw;
	       ipfw:rules = 100	200;
	       limit 1 {
		   limit = 1G;
		   restart {
		       restart = +W;
		   }
	       }
	   }

       Here  the  limit	 will  be restarted at the end of a week after limit's
       start time.  A character	after the `+' sign means: `m' a	minute,	`h'  a
       hour, `D' a day,	`W' a week, `M'	a month.

       Example 3:

	   rule	my.traf	{
	       ac_list = ipfw;
	       ipfw:rules = 100	200;
	       limit 1 {
		   limit = 1G;
		   restart {
		       restart = +M 2D;
		   }
	       }
	   }

       In  this	 example  the  limit will be restarted on the beginning	of the
       third day of the	next month after limit's start time: the restart  time
       for ``+M'' (start of the	next month) is calculated and then ``2D'' (two
       days) are added to the calculated value.

       Note  that  ``2D	+M''  is not the same: here ``2D'' is added to limit's
       start time and then the restart time for	``+M'' is calculated  (and  we
       always will get first day of some next month here).

   Actions when	a limit	becomes	reached
       If  a  limit becomes reached, then commands listed in the reach section
       are run:

	   limit <limit-name> {
	       /* Limit's parameters and sections. */
	       reach {
		   /* Commands.	*/
	       }
	   }

       The reach section can be	absent or empty	and in this case  no  commands
       will be run when	a limit	becomes	reached.

       Accounting  systems  used by limit's rule are informed when a limit be-
       comes reached.  So if you do not	specify	commands in the	reach section,
       then some actions still can be performed	by accounting systems.

       Example:

	   rule	my.traf	{
	       ac_list = ipfw;
	       ipfw:rules = 100;
	       limit 1 {
		   limit = 1G;
		   restart {
		       restart = +W;
		   }
		   reach {
		       exec "/somewhere/stop_traffic";
		   }
	       }
	   }

       Here there is 1 Gbyte limit.  If	this limit is  not  reached,  then  it
       will  be	 restarted  at the end of the week.  If	this limit is reached,
       then the	given command will be run.

   Restarting a	reached	limit
       The expire parameter in the expire section allows to specify time  when
       a  reached limit	should be restarted with zeroed	(flushed) positive and
       negative	counters:

	   limit <limit-name> {
	       /* Limit's parameters and sections. */
	       expire {
		   expire = <restart-time>;
		   /* Commands.	*/
	       }
	   }

       The <restart-time> value	is relative to time when a limit  was  reached
       (see example).

       The  expire section can contain optional	commands, which	will be	run at
       the moment of limit restart.

       Accounting systems used by limit's rule are  informed  when  a  reached
       limit  is  restarted.   So if you do not	specify	commands in the	expire
       section,	then some actions still	can be performed  by  accounting  sys-
       tems.

       If  a  limit does not have the expire parameter,	then this limit	(if it
       is reached) cannot be automatically restarted.  But it can be restarted
       by the ipactl(8)	utility	and by ictl parameters and all	commands  from
       the expire section will be run.

       The  value  of  the expire parameter can	be 0s, this means that reached
       limit will be restarted immediately.

       A reached limit can expire only when its	rule is	active.

       Example:

	   rule	my.traf	{
	       ac_list = ipfw;
	       ipfw:rules = 100;
	       limit 1 {
		   limit = 1G;
		   restart {
		       restart = +W;
		   }
		   reach {
		       exec "/somewhere/stop_traffic";
		   }
		   expire {
		       expire =	+W;
		       exec "/somewhere/start_traffic";
		   }
	       }
	   }

       Here there is 1 Gbyte per week limit.  If the limit is reached, then at
       the beginning of	the next week it will be restarted.  If	this limit  is
       not  reached,  then  it	is also	restarted at the beginning of the next
       week.

   Active and inactive limits
       If a limit does not have	own worktime parameter,	then it	inherits  this
       parameter from its rule.	 Any limit can have own	worktime parameter.

       If  a rule is inactive, then all	its limits are inactive	as well.  If a
       limit is	inactive, then times defined by	the restart and	expire parame-
       ters are	not checked.

       It is possible to have active rule and inactive limit, but it is	impos-
       sible to	have inactive rule and active limit.  All  time	 intervals  in
       the limit's worktime parameter must be subsets of time intervals	in the
       rule's  worktime	 parameter.  To	check time intervals subsets in	static
       rules and autorules run ipa(8) with -tt switches.

       Example:

	   rule	my-account {
	       /* ... */
	       worktime	= A * S	*;
	       limit 1 {
		   limit = 10M;
		   worktime = A	08:00-21:00 S 08:00-21:00;
	       }
	   }

       Here the	rule is	active only at Saturday	and Sunday and	the  limit  is
       active  only from 08:00 till 21:00 at the same days.  Since 08:00-21:00
       time interval is	a subset of 00:00-24:00	time interval, then everything
       is correct with these two parameters.

   Startup and shutdown	sections for a rule
       A rule can have own startup and shutdown	sections  with	the  following
       extra subsections:

       if_any_reached	  - if any of rule's limits is reached;
       if_any_not_reached - if any of rule's limits is not reached;
       if_all_reached	  - if all rule's limits are reached;
       if_all_not_reached - if all of rule's limits are	not reached.

       These  subsections  determine  commands,	which should be	run if limits'
       states fit a subsection condition.

       Any rule	can have empty startup or shutdown section, in this case  this
       section is not inherited	from the matched rulepat section.

       Example:

	   rule	my.traf	{
	       ac_list = ipfw;
	       ipfw:rules = 100;
	       startup {
		   exec	"/somewhere/count_traffic";
		   if_any_reached {
		       /* ... */
		       exec "/bin/echo \"Some limit in \
			     rule ${rule} was reched\" | mail admin";
		   }
	       }
	       limit 1 {
		   limit = 1G;
		   restart {
		       restart = +M;
		   }
		   info	= "1G per month";
		   /* ... */
	       }
	       limit 2 {
		   limit = 500M;
		   restart {
		       restart = +W;
		   }
		   info	= "500M	per week";
		   /* ... */
	       }
	   }

       Here  there  are	two limits: 1 Gbyte per	month and 500 Mbytes per week,
       the if_any_reached section will be used if any of these two  limits  is
       reached at the moment of	the start of ipa(8).  Also rule's startup sec-
       tion  has one command, which is always run at startup.  Here we use one
       back-slash character for	splitting a command string.

   Startup and shutdown	sections for a limit
       A limit can have	own startup and	shutdown sections with	the  following
       extra subsections:

       if_reached     -	if a limit is reached;
       if_not_reached -	if a limit is not reached.

       These  subsections determine commands, which should be run if a limit's
       state fits a subsection condition.

       Accounting systems used by limit's rule are  informed  at  startup  and
       shutdown	 whether  a  limit is reached or is not	reached.  So if	you do
       not specify startup and/or shutdown commands for	a limit, then some ac-
       tions still can be performed by accounting systems.

   Databases and limits	(thresholds)
       A limit inherits	a list of databases from its rule,  but	 a  limit  can
       have own	list of	database:

	   rule	<rule-name> {
	       /* Rule's parameters and	sections. */
	       db_list = <list1>;
	       limit <limit-name> {
		   /* Limit's parameters and sections. */
		   db_list = <list2>;
	       }
	   }

       <List1>	and  <list2> can contain common	elements, <list1> is used only
       for a rule and <list2> is used only for a limit in any case.

       Why to use separate database lists for a	rule and  a  limit?   Not  all
       databases work with limits and even if some database works with limits,
       it can support not all functions	(methods) for limits.  See implementa-
       tion details in the ipa_mod(3) manual page.

       Suppose	some  limit uses several databases.  During initialization the
       first database, that is able to return a	limit's	state, will  be	 asked
       for the current limit's state.  Even if some other database has another
       limit's	state,	it will	not be asked for it and	its limit's state will
       be updated.

       Note that the order of databases	for a limit is important.

       Read in the database module's documentation whether it  can  work  with
       limits and what exactly a module	supports when it works with limits.

       Everything said above corresponds to thresholds as well.

   Using the limit (threshold) parameter from the database
       The load_limit parameter	allows to fetch	the value of the limit parame-
       ter from	the database:

	   limit <limit-name> {
	       /* Limit's parameters and sections. */
	       load_limit = <boolean>;
	   }

       If  it  is  necessary to	load the value of the limit parameter from the
       database, then set the value of the  load_limit	parameter  to  ``yes''
       (the  default value is ``no'').	If the database	does not have the cur-
       rent state of a limit (if a limit is new), then the value of the	 limit
       parameter  from	the  configuration  file  will be used,	that's why the
       limit parameter always must be specified.

       One of possible cases why one wants to set this parameter to ``yes'' is
       the usage of the	ipactl(8) utility for changing the value of the	 limit
       parameter on-the-fly.

       This  parameter	can be specified in the	global section.	 If some limit
       does not	have this parameter, then its value will be inherited from the
       global section.

       Everything said above  corresponds  to  thresholds  as  well,  but  the
       load_threshold parameter	should be used for thresholds.

   Limits initialization
       When  ipa(8)  starts, rereads the configuration file or does reinitial-
       ization when some time related problems occurred, it performs the  fol-
       lowing steps for	each limit:

       1.     The  current  limit's  state  is read from the database.	If the
	      database does not	have the limit's state,	 then  a  new  limit's
	      state  is	 registered with the value of the limit	parameter from
	      the configuration	file and with zero counter and	initialization
	      of  the  limit  is complete, else	ipa(8) does second step	(2a or
	      2b).

       2a.    If the limit is not reached with	the  current  state  from  the
	      database,	 then  if  the	value  of  the load_limit parameter is
	      ``no'', then ipa(8) updates the value  of	 the  limit  parameter
	      from  the	configuration file; if the value of the	load_limit pa-
	      rameter is ``yes'', then ipa(8) ignores the value	of  the	 limit
	      parameter	 from  the configuration file and gets this value from
	      the database.  In	any case the limit is marked as	 not  reached,
	      even  if	with new settings it becomes reached.  Then ipa(8) up-
	      dates date when the limit	should be restarted accordingly	to the
	      value of the restart parameter from the configuration file,  ig-
	      noring this date from the	database.

	      If  start	 time  of  a not reached limit is greater than current
	      time, then ipa(8)	changes	its start time to current  time.   The
	      limit's counter is not changed.

       2b.    If the limit is reached, then ipa(8) marks this limit as reached
	      and  does	 not  update  the  value of the	limit parameter	in the
	      database (that is, it does not honor the value of	the load_limit
	      parameter	at this	moment).  Then ipa(8) updates  date  when  the
	      limit will expire	accordingly to the value of the	expire parame-
	      ter  from	 the  configuration  file, ignoring this date from the
	      database.

       A reached or not	reached	limit can be restarted	during	initialization
       only if used database returned incorrect	data about its state.

       To verify the current limit's state use ipactl(8) with command status.

   Limits: state diagram
       To  help	to understand how exactly an arbitrary limit works, let's draw
       the state diagram:

			+--------------+--> Restart (Tstart)
			|	       |
			Trestart_exec  Treach_exec    Texpire_exec
       --|------>------||------>------||------>------||------------->
	 Tstart	     Trestart	      Treach	   Texpire	 time

   Sublimits
       A sublimit is a part of some limit.  The	main purpose of	a sublimit  is
       to  register  an	event when some	part of	the limit parameter's value is
       reached.	 Since a sublimit is a part of some limit  section,  then  the
       value of	a sublimit must	be given in the	same units as the value	of the
       limit parameter or in per cent:

	   limit <limit-name> {
	       limit = <limit-value>;
	       /* Limit's parameters and sections. */
	       sublimit	<sublimit-value> {
		   /* Sublimit's sections. */
	       }
	   }

       Sublimits  can  contain only reach, startup and shutdown	sections.  All
       these sections has the same format and mean the same as for limits.   A
       limit can have several sublimits.

       Accounting  systems  are	 not informed about sublimits' events, because
       sublimits are invisible for modules.  Since sublimits  states  are  not
       kept  in	the database, it is always better to use sublimits than	adding
       extra limits to some rule if possible.

       Example:

	   rule	my.traf	{
	       /* ... */
	       limit l1	{
		   limit = 1G;
		   load_limit =	yes;
		   restart {
		       restart = +M;
		   }
		   info	= "${rule}, ${limit} per month";
		   /* ... */
		   sublimit 50%	{
		       reach {
			   exec	"/bin/echo \"half of ${rule}'s \
				 limit ${limit}	reached\" | mail me";
		       }
		   }
	       }
	   }

       Here there is the sublimit, which will send an email when half  of  the
       l1  limit is reached.  Even if the value	of the limit parameter will be
       changed by the ipactl(8)	utility, sublimit's value  will	 be  adjusted,
       because it is given in per cent.

   Thresholds: introduction
       A  threshold  allows  to	monitor	rule's statistics for some time	period
       before current time and do some actions when statistics for  this  time
       period  is  less	 than, equal to	or greater than	the given value.  This
       time period also	can be called ``sliding	time window''.	A threshold is
       described in the	threshold section with the following format:

	   threshold <threshold-name> {
	       threshold = <threshold-value>;
	       threshold_time_width = <time>;
	       threshold_time_slice = <time>;
	       /* Other	threshold's parameters and sections. */
	   }

       One rule	can have several thresholds.  If  a  rule  has	at  least  one
       threshold,  then	 it  will  no  inherit any thresholds from the matched
       rulepat section.

       Any threshold has 64-bit	unsigned integer counter, which	is updated and
       which is	compared with the value	of the threshold  parameter.   If  the
       counter	becomes	 less  than, equal to or greater than the value	of the
       threshold parameter, then commands from the  optional  below_threshold,
       equal_threshold	or  above_threshold  section are run.  This counter is
       updated synchronously with a rule's counter  each  threshold_time_slice
       time interval.

       <Threshold-value>  can  be: bytes, time or unsigned 64-bit integer num-
       ber; and	it can be equal	to zero.

       It is possible to specify  a  deviation	of  <threshold-value>  in  the
       threshold_deviation  parameter.	 The  value of the threshold_deviation
       parameter must be given in the same units as the	value of the threshold
       parameter or in per cent.

       The value of the	threshold_time_width parameter determines the width of
       sliding time window.  The value of the  threshold_time_slice  parameter
       determines time intervals of sliding time window	movement.  The thresh-
       old_time_width  parameter's  value  must	 be  greater  than the thresh-
       old_time_slice parameter's value	and must be divisible on this value.

       A threshold's counter represents	a snapshot of  rule's  statistics  for
       the last	threshold_time_width seconds.  Unlike limits thresholds	do not
       have  ``start  time'',  because	their statistics is sliding in time in
       discrete	time intervals equal to	threshold_time_slice  seconds.	 These
       two  parameters can be specified	in the global section and they will be
       inherited if some threshold does	not have them.

       Accounting systems used	by  a  threshold's  rule  are  informed	 about
       threshold's events.  So accounting systems can do some actions when the
       value  of  a  threshold's  counter  is  less, equal or greater than the
       threshold parameter's value.

       To limit	number of times	commands are run and  accounting  systems  are
       informed	   from	  below_threshold   (X),   equal_threshold   (Y)   and
       above_threshold (Z) sections use	the threshold_balance parameter:

	   threshold_balance = X:Y:Z;

       This parameter can be specified in  the	global	section	 and  if  some
       threshold  does	not have it, then its value will be inherited from the
       global section.

       There are three internal	counters x, y and z which count	how many times
       commands	were  run  and	accounting  systems  were  informed  from  be-
       low_threshold,  equal_threshold	and  above_threshold sections consecu-
       tively.	These counters initially are equal to X, Y and Z respectively.
       When threshold's	counter	is below than the value	of the threshold para-
       meter and x is not equal	to zero, then it is decreased, y is set	 to  Y
       and  z  is set to Z, then commands from the below_threshold section are
       run and accounting systems are informed about threshold's  event.   The
       same happens for	y and z	counters.

       To unlimit value	of X, Y	or Z set it to `-'.  In	implementation infini-
       tive  value  really  is	equal  to maximum value	of 'unsigned int' data
       type.  The default value	of this	parameter is -:-:-.

       Example:

	   rule	lan {
	       ac_list = ipfw;
	       ipfw:rules = 100	200 -300;
	       update_time = 1m;
	       limit l1	{
		   limit = 1G;
		   info	= "Control each	1G of bandwidth	usage";
		   reach {
		       exec "/bin/echo \"1G of ${rule} reached\" | mail	me";
		   }
		   expire {
		       expire =	0s;
		   }
	       }
	       threshold t1 {
		   threshold = 500M;
		   threshold_balance = 1:-:1;
		   threshold_deviation = 50M;
		   threshold_time_width	= 24h;
		   threshold_time_slice	= 15m;
		   info	= "500M	plus-minus 50M threshold per 24h";
		   below_threshold {
		       exec "/somewhere/increase_bandwidth ${rule}";
		   }
		   above_threshold {
		       exec "/somewhere/decrease_bandwidth ${rule}";
		   }
	       }
	   }

       Here the	rule has one threshold and one limit.

       The threshold allows to dynamically  control  bandwidth	in  500	Mbytes
       plus-minus 50 Mbytes (we	increase speed by some increase_bandwidth pro-
       gram  and  decrease  speed  by  some decrease_bandwidth program)	per 24
       hours (this is one day, but not a week day, here	24 hours mean time in-
       terval).	 Time slice is 15 minutes, note	that the threshold will	not be
       checked every minute here (the value of the update_time	parameter  for
       this rule).

       Statistics  for	the  rule  and the limit will be updated every minute.
       The limit allows	to send	an email when next 1 Gbyte  of	bandwidth  has
       been used.

   Active and inactive thresholds
       Like  a limit any threshold can be active and inactive and can have own
       worktime	parameter.  Read appropriate paragraph for limits for more in-
       formation.

       What is the value of the	threshold's counter when a threshold was inac-
       tive and	becomes	active due to the worktime parameter's value?  One so-
       lution is to allow a threshold's	time window to slide during  time  in-
       terval  of  inactivity,	another	 solution is to	``move'' a threshold's
       time window over	time interval of inactivity.  In  the  first  solution
       statistics for the threshold's counter during time interval of inactiv-
       ity is 0	and the	value of the threshold's counter is decreased.	In the
       second  solution	 statistics  during time interval of inactivity	is ig-
       nored (it is skipped) and the value of the threshold's counter  is  not
       changed.

       What is the value of the	threshold's counter when ipa(8)	starts working
       and  there  is  a state of a threshold in the database?	There are also
       two solutions for this situation	as for previous	question.

       To select solutions for above  described	 situations  use  the  thresh-
       old_type	parameter, its value is	equal to ORed bits (given as hexadeci-
       mal values):

       0x1    jump  over  time interval	when ipa(8) did	not run	(was stopped),
	      this bit is checked when a threshold is initialized;

       0x2    jump over	time interval when a threshold was inactive, this  bit
	      is  checked when a threshold became active again due to settings
	      of its worktime parameter.

       The default value of this parameter is zero.  Possible values  of  this
       parameter are: 0, 1, 2 and 3 (0x1|0x2).	Normal values for this parame-
       ter are 0 or 3.	Values with only one bit set should be used with care,
       since  when  a  threshold is initialized, it is treated as active (read
       the paragraph about thresholds initialization).

       This parameter can be specified in  the	global	section	 and  if  some
       threshold  does	not have it, then its value will be inherited from the
       global section.

       Example:

	   rule	client {
	       ac_list = ipfw;
	       ipfw:rules = 100	200 300;
	       update_time = 1m;
	       threshold t {
		   threshold = 100M;
		   threshold_deviation = 10%;
		   threshold_time_width	= 5h;
		   threshold_time_slice	= 15m;
		   threshold_type = 3;
		   worktime = M	08:00-21:00 T 08:00-21:00 W 08:00-21:00
			      H	08:00-21:00 F 08:00-21:00;
		   info	= "100M	plus-minus 10% threshold per 5h	(type 3)";
		   below_threshold {
		       exec "/somewhere/increase_bandwidth ${rule}";
		   }
		   above_threshold {
		       exec "/somewhere/decrease_bandwidth ${rule}";
		   }
	       }
	   }

       Suppose that the	given rule is for one client which has access  to  In-
       ternet  each  work  day	from  08:00 to 21:00.  We allow	him 100	Mbytes
       plus-minus 10% per 5  hours  speed  (we	increase  speed	 by  some  in-
       crease_bandwidth	 program and decrease speed by some decrease_bandwidth
       program).

       Suppose that the	threshold's current counter's value  is	 90 Mbytes  at
       21:00.	When  08:00  of	the next day comes, by default the threshold's
       current counter's value becomes 0 Mbyte,	because	there is at least  one
       time interval in	5 hours	between	21:00 and 08:00	of the next day.  Here
       we  use	threshold  type	 3 and time window will	``jump'' from 21:00 to
       08:00 and the threshold's current counter's value will not be  changed,
       it will be 90 Mbytes at 08:00 of	the next day.  We also can stop	ipa(8)
       at  21:00  and run it again at 08:00 and	a threshold's time window will
       also ``jump'' from 21:00	to 08:00.

       If there	are several clients with the same settings, then at 08:00  non
       of  them	 will  be  able	to intensively start to	use own	part of	common
       bandwidth.

   Startup and shutdown	sections for a threshold
       A threshold can have own	startup	and shutdown sections, which can  con-
       tain only lists of commands.

   Thresholds initialization
       When  ipa(8)  starts, rereads the configuration file or does reinitial-
       ization when some time related problems occurred, it performs the  fol-
       lowing steps for	each threshold:

       1.     The current threshold's state is read from the database.	If the
	      database does not	have the threshold's state, then a new thresh-
	      old's  state is registered with the value	of the threshold para-
	      meter from the configuration file	and with zero counter and ini-
	      tialization of the threshold is complete,	else ipa(8) does  sec-
	      ond step.

       2.     Using values of load_threshold and threshold_type	parameters and
	      the  threshold's state is	updated.  Since	threshold's statistics
	      slices are not saved in the database,  valid  statistics	slices
	      are  initialized	approximately accordingly to the current local
	      time, threshold's	timestamps and counter value.

       When a threshold	is initialized it is assumed as	 active	 even  if  its
       worktime	parameter marks	this threshold as inactive.

   Thresholds: time diagram
       To  help	 to understand how exactly an arbitrary	threshold works, let's
       draw the	time diagram:

	    <-------------- time_width ------------->

       (t1) |---c1--|---c2--|---c3--|---c4--|---c5--| --> sliding

       (t2)	    |---c2--|---c3--|---c4--|---c5--|---c6--| --> sliding

	    <-slice->
       -----|-------|-------|-------|-------|-------|-------|-------|-->
	    t1	    t2						      time

       On this diagram there is	threshold's statistics at time t1 and at  time
       t2.   All statistics is represented as a	sum of ci, each	ci is equal to
       statistics of a rule for	one time slice t2 - t1.	 A threshold slides in
       time discretely and its statistics is a snapshot	of  rule's  statistics
       for last	time_width seconds.

   Dynamic rules
       Dynamic	rules  are  generated from autorules by	specially designed ac-
       counting	modules	on-the-fly.  Internally	static and dynamic  rules  are
       almost indistinguishable	in ipa(8) and any parameter (except only three
       parameters) and section from static rules can be	used in	dynamic	rules.

       The autorule section describes settings for one autorule:

	   autorule <autorule-name> {
	       /* Parameters and sections. */
	   }

       A  dynamic  rule	 is  looks like	a static rule.	There are only two re-
       strictions for autorules	(hence for dynamic  rules):  an	 autorule  can
       have only one accounting	system in the ac_list parameter's value	and an
       autorule	cannot have ac_gather_*	and ictl parameters.

       The  configuration  file	 can  have several autorules at	once.  Any au-
       torule usually have at least the	ac_list	parameter with one element  in
       its value.  (It is possible to implement	support	for several accounting
       systems	for  one autorule, but it is senseless.)  This one element de-
       termines	accounting system that can create and  delete  dynamic	rules.
       Every  time when	this accounting	system is asked	for new	statistics, it
       can create and/or delete	(previously created) dynamic rules.

       If you want to use some database	for dynamic rules, then	this  database
       should support dynamic rules.

       If  an  autorule	has the	worktime parameter, then this parameter	is for
       this autorule.  A dynamic rule generated	from  this  autorule  inherits
       autorule's  worktime_rule  parameter  as	its worktime parameter.	 If an
       autorule	does not have the worktime parameter, then  it	inherits  this
       parameter from the global section.

       Since  an autorule and its dynamic rules	can use	different worktime pa-
       rameters	it is possible to have inactive	autorule  and  active  dynamic
       rules and vice versa.

       A  dynamic  rule	inherits parameters and	sections from its autorule, if
       some parameters and sections are	still undefined, then they are	inher-
       ited from the matched rulepat section, then from	the global section and
       then default settings are used.

       If  an  autorule	has startup and	shutdown sections, then	these sections
       are for dynamic rules, not for an autorule itself.  If it is  necessary
       to  use the name	of some	dynamic	rule in	some command line, then	do not
       use the ${rule} macro variable, because it is expanded by the  internal
       configuration file parser, use command line substitutions instead.

       Any  autorule  can have empty startup or	shutdown section, in this case
       this section is not inherited from the matched rulepat section for  its
       dynamic rules.

       If  it  is  necessary  to use different limits (thresholds) for dynamic
       rules created  from  the	 same  autorule,  then	specify	 these	limits
       (thresholds) in different rulepat sections.

       Example:

	   ac_mod "ipa_atest.so";
	   db_mod "ipa_db_sdb.so";

	   global {
	       db_list = sdb;
	       append_time = 1h;
	   }

	   autorule a {
	       ac_list = atest;
	       update_time = 1m;
	       limit 1 {
		   limit = 100M;
		   restart {
		       restart = +W;
		   }
		   reach {
		       exec "/somewhere/stop_traffic.sh	%rule%";
		       exec "/bin/echo \"%rule%'s limit	${limit} reached\" |
			     mail admin";
		   }
		   expire {
		       expire =	+M;
		       exec "/somewhere/start_traffic.sh %rule%";
		   }
	       }
	   }

       Here  each  dynamic  rule  generated from the autorule will inherit au-
       torule's	update_time parameter and db_list and  append_time  parameters
       from  the global	section.  Each dynamic rule will have one limit, since
       the ${rule} macro variable cannot be used in dynamic rules (actually in
       autorules), then	%rule% substitution is used.  Using the	${limit} macro
       variable	in a limit in an autorule is correct, since  limit's  name  is
       know for	the configuration file parser.

   Rules patterns
       Using rules patterns is an effective method for sharing common settings
       for  rules.   The global	section	allows to specify some common settings
       for any rules, dynamic rules can	inherit	common settings	from their au-
       torules.	 Rules patterns	allow to specify common	settings  for  classes
       of static and dynamic rules.

       If some static or dynamic rule does not have some parameter or section,
       then  it	 inherits this parameter or section from the matched rule pat-
       tern.  A	rule pattern is	defined	in the rulepat section:

	   rulepat "<regexp>" {
	       /* Parameters and sections. */
	   }

       Each rule pattern is named by POSIX regular expression.	Having	parsed
       the  configuration  file,  ipa(8) finds a matched rule pattern for each
       static rule and applies unspecified settings from a rule	pattern	 to  a
       static  rule.  Similarly, having	created	a dynamic rule,	ipa(8) finds a
       matched rule pattern and	applies	unspecified settings from a rule  pat-
       tern to a dynamic rule.

       By  default when	a matched rule pattern is found	the search terminates.
       To continue search for other rule patters  set  the  check_next_rulepat
       parameter to ``yes'' (the default value is ``no''):

	   check_next_rulepat =	<boolean>;

       This parameter can be used only in the rulepat section.

       Any parameter (except ac_gather_* and ictl parameters) and any section,
       which is	allowed	to use in the rule section, can	be used	in the rulepat
       section.

       Rules  patterns	can  be	placed anywhere	in the configuration file, but
       their order  is	important,  because  theirs  regular  expressions  are
       checked in the same order as they appear	in the configuration file.

       Modules	also  can expect their parameters and sections in rulepat sec-
       tions.

       Example:

	   ac_mod "ipa_ipfw.so";
	   db_mod "ipa_db_sdb.so";

	   global {
	       ac_list = ipfw;
	       db_list = sdb;
	       update_time = 1m;
	       load_limit = yes;
	       sdb:db_group = staff;
	   }

	   rulepat "0${$}" {
	       check_next_rulepat = yes;
	       update_time = 30s;
	       threshold 1 {
		   threshold = 1G;
		   threshold_deviation = 10%;
		   threshold_time_width	= 10h;
		   threshold_time_slice	= 5m;
		   below_threshold {
		       exec "/somewhere/increase-bandwidth.sh %rule%";
		   }
		   above_threshold {
		       exec "/somewhere/decrease-bandwidth.sh %rule%";
		   }
	       }
	   }

	   rulepat "^client" {
	       worktime	= M 08:00-20:00	T 08:00-20:00 W	08:00-20:00
			  H 08:00-20:00	F 08:00-20:00 A	08:00-17:00;
	   }

       Here first rulepat section ``catches'' all rules	with zero at  the  end
       of  their  names	 (macro	 variable ${$} is expanded to single character
       `$').  Since the	value of its check_next_rulepat	is ``yes'', then  next
       rule  pattern is	checked.  Second rulepat section ``catches'' all rules
       with ``client'' substring at the	beginning of their names.

   Gathering statistics	from rules
       Usually each rule gets statistics from accounting  systems,  but	 some-
       times it	is necessary to	summarize statistics from several rules	and it
       is impossible or	too expensive give this	task to	accounting modules.

       The  ac_gather_add  and ac_gather_sub parameter allow to	get statistics
       for one rule from several rules:

	   rule	<rule-name> {
	       /* Rule's parameters and	sections. */
	       ac_gather_add = "<regexp>";
	       ac_gather_sub = "<regexp>";
	   }

       Here <regexp> is	a POSIX	 regular  expression.	If  some  rule's  name
       matches	this  regular expression, then its statistics is gathered by a
       rule in which the ac_gather_* parameters	are specified and is added  to
       (ac_gather_add)	or  subtracted from (ac_gather_sub) rule's statistics.
       It is also possible to make complex dependencies	with these  parameters
       (see the	example).

       These  parameters  can  be  used	with static rules only,	but can	gather
       statistics from static and dynamic rules.

       The ac_list is a	synchronous parameter in respect to the	rule  section:
       when  some  rule	 is updated statistics is fetched from each accounting
       system specified	in a rule.  Parameters	ac_gather_*  are  asynchronous
       parameters in respect to	the rule section: current rule gets statistics
       from  a	rule  matched ac_gather_* parameters' regular expressions when
       this matched rule is updated.

       A rule can have ac_gather_* parameters and the ac_list parameter.

       Example:

	   ac_mod "ipa_ipfw.so";

	   global {
	       ac_list = ipfw;
	   }

	   rule	client1	{
	       ipfw:rules = 100	102 104;
	       info = "Statistics for first client";
	   }

	   rule	client2	{
	       ipfw:rules = 200	202 204;
	       info = "Statistics for second client";
	       /* ac_gather_add	= "^clients${$}"; <-- WRONG! */
	   }

	   rule	clients	{
	       ac_gather_add = "^client[[:digit:]]+${$}";
	       info = "Statistics for all clients";
	   }

	   rule	server {
	       ipfw:rules = 1000 1002;
	       info = "Statistics for server";
	   }

	   rule	all_stat {
	       ac_gather_add = "^(server|clients)${$}";
	       info = "Statistics for all in my	LAN";
	   }

	   rule	all_except_client2_stat	{
	       ac_gather_add = "^all_stat${$}";
	       ac_gather_sub = "^client2${$}";
	       info = "Statistics for all in my	LAN except client2";
	   }

       Here there are six static rules:	 client1,  client2,  clients,  server,
       all_stat	and all_except_client2_stat.  The rule clients gets statistics
       from rules client1 and client2.	The rule all_stat gets statistics from
       rules  clients  and  server.  And the rule all_except_client2_stat gets
       statistics from rules clients and server	not including statistics  from
       rule client2.

       The  rule client2 has incorrectly used the ac_gather_add	parameter in a
       comment.	 If this parameter exists in this rule,	then we	will get cycle
       in rules	dependencies: client2->clients->client2...   ipa(8)  does  not
       check cycles in rules dependencies.

   Using ipactl(8) program
       The  ipactl(8) program allows to	send control commands to ipa(8)	via an
       Unix domain socket.  Before using this program it is necessary to allow
       to use it by setting the	ctl_enable parameter to	``yes''	 (the  default
       value is	``no''):

	   ctl_enable =	<boolean>;

       If  the value of	this parameter is ``yes'', then	ipa(8) creates a local
       socket and listens for commands on it.  The created socket is owned  by
       the user	who run	ipa(8).

       Access  permissions  for	 the  socket  are  defined by the value	of the
       ctl_socket_perm parameter (the default value is ``u''):

	   ctl_socket_perm = <permission>;

       <Permissions> is	a sequence of characters `u' (user), `g'  (group)  and
       `o'  (others).	These  characters determine who	is allowed to write to
       the socket.  Other users	can be allowed to write	to the socket only  if
       ipa(8) uses ACL (access control list).

       There  is  the  default	path  to  this	socket	(see the output	of the
       ``ipactl	-h''  command),	 but  you  it  can   be	  redefined   in   the
       ctl_socket_path parameter:

	   ctl_socket_path = "/path/to/socket";

       The  socket  has	timeout	equal to 10 seconds by default,	but this value
       can be changed in the ctl_timeout parameter:

	   ctl_timeout = <time>;

       There is	a limit	on maximum size	of a control query recevied by ipa(8).
       Its  default  is	 1 Kbyte.   This  value	 can   be   changed   in   the
       ctl_query_max_size parameter:

	   ctl_query_max_size =	<bytes>;

       ipa(8)  run  under FreeBSD and NetBSD is	able to	check ipactl(8)'s mes-
       sages credentials (check	this in	the output of the ``ipa	-v'' command),
       so on these systems one has to define ctl_acl_class and ctl_*_acl para-
       meters.

       The ctl_acl_class parameter defines ACL class: the name of ACL followed
       by ACL definition:

	   ctl_acl_class <class> [<ACL>];

       This parameter should not be placed in any section.

       ACL consists of elements	separated by space character, each its element
       has the following format:

	   [!]<user>|%<group>

       The `!' character means that access is denied.  The `%' character means
       that the	following name is a group name.	 <User>	and  <group>  must  be
       given  as  symbolic  names (UID and GID do not work here).  Elements in
       ACL are checked from the	left to	the  right.   Here  ``access  denied''
       means that the user is not allowed to use some control command.	When a
       control	message	arrives, ipa(8)	translates user	name or	groups name of
       each ACL	to UID or GID and compares it with a message's sender  creden-
       tials.

       The ctl_dump_acl	parameter applies ACL for the command dump:

	   ctl_dump_acl	= <class>;

       The ctl_freeze_acl parameter applies ACL	for the	command	freeze:

	   ctl_freeze_acl = <class>;

       The ctl_stat_acl	parameter applies ACL for status and memory commands:

	   ctl_stat_acl	= <class>;

       The  ctl_rule_acl  parameter  applies ACL to a rule for delete, expire,
       restart,	set and	status commands	and it applies ACL to an autorule  for
       create and status commands:

	   ctl_rule_acl	= <class>;

       If  ACL	is  not	defined	and is not inherited, then it is considered as
       empty ACL and means that	access is denied for anybody.

       Let's show how to use all these parameters in examples.

       Example 1:

	   ctl_enable =	yes;
	   ctl_socket_perm = ug;

       In this example ipa(8) does not know how	 to  get  ipactl(8)'s  control
       messages	 credentials.	User and group are allowed to send commands to
       the socket (this	is controlled by access	permissions  of	 the  socket).
       It  is impossible to allow other	users to write to the socket for secu-
       rity reasons.

       Example 2:

	   ctl_enable =	yes;
	   ctl_socket_path = "/var/tmp/ipactl.sock";
	   ctl_timeout = 10s;

       Here the	socket path and	timeout	are redefined.

       Example 3:

	   ctl_enable =	yes;
	   ctl_socket_perm = ugo;
	   ctl_acl_class = empty;
	   ctl_acl_class = root	  root;
	   ctl_acl_class = admins root !john %wheel;

	   ctl_dump_acl	= root;

	   global {
	       ctl_rule_acl = admins;
	       /* ... */
	   }

	   rulepat "^vip" {
	       ctl_rule_acl = root;
	       /* ... */
	   }

	   rulepat "^staff" {
	       ctl_rule_acl = admins;
	       /* ... */
	   }

	   rule	lan-all	{
	       ctl_rule_acl = empty;
	       /* ... */
	   }

       In this example ipa(8) knows how	to get	ipactl(8)'s  control  messages
       credentials.   Three  ACL  classes are defined: empty, root and admins.
       Others users are	allowed	to send	commands to the	socket.

   Built-in ipactl
       Any program can be run in any section which  accepts  exec  parameters.
       In  such	sections the ipactl(8) utility also can	be run in an asynchro-
       nous regime.  If	ipactl(8) is called in a synchronous regime and	if  it
       connects	 to ipa(8) process which run it	and if it has infinitive time-
       out for connection, then	it will	run forever.

       But calling ipactl(8) asynchronously from the exec  parameter  has  one
       disadvantage:  such  call is not	atomic and it requires some time.  The
       problem is even worst if	it is  necessary  to  call  ipactl(8)  several
       times from the same section.

       The  ictl parameter is a	built-in version of ipactl(8) and supports the
       following commands:

	   ictl	"-r <rule> set ...";
	   ictl	"-r <rule> -l <limit> expire|restart|set ...";
	   ictl	"-r <rule> -t <threshold> set ...";

       Formats of these	parameter's values are similar to  formats  of	corre-
       sponding	commands in ipactl(8).	This parameter can be used in any sec-
       tion  which  accepts  exec parameters and it should be specified	before
       exec parameters.	 It is possible	to use several ictl  parameters.   The
       given control command in	this parameter always is called	synchronously,
       ignoring	the value of the sync_exec parameter.  Actually	ipactl(8) even
       is not called, because corresponding functions are called directly.

       The  ictl  parameter  can be used inside	static rules and inside	global
       startup section only.  This parameter cannot be used inside  any	 shut-
       down  section.	It is possible to implement support for	this parameter
       for dynamic rules, but it is unclear if this is necessary.

       There is	one restriction	for control commands.  A control command  can-
       not  be	called	for  the  rule	(limit	or threshold) from which it is
       called.	It is possible to create loops of control commands invocations
       (e.g. a control command is called from one limit	and modifies state  of
       another	limit, that another limit calls	a control command that changes
       state of	the original limit).  Such loops are checked by	ipa(8) and are
       considered as wrong configuration.

       As it was said above the	ictl parameter can be  used  in	 startup  sec-
       tions,  but  you	 should	use it there only if you completely understand
       what you	are doing.

       Any command given in the	ictl parameter:	1) for a limit is  synchronous
       in  respect  to this limit's events; 2) for a threshold is asynchronous
       in respect to this threshold's events; 3) for a rule is asynchronous in
       respect to limits' and thresholds' events of this rule.

       If you want to check correctness	of specified names  of	rules,	limits
       and  thresholds in control commands, then run ipa(8) with -tt switches,
       because single -t switch	does not check existence of names.

       Example:

	   rule	1 {
	       /* ... */
	       limit 1 {
		   /* ... */
		   expire {
		       expire =	+W;
		       ictl "-r	1 -l 2 expire";
		       ictl "-r	2 -l 1 restart";
		       ictl "-r	2 set counter +1000";
		       /* ... */
		   }
	       }
	       limit 2 {
		   /* ... */
	       }
	   }

	   rule	2 {
	       /* ... */
	       limit 1 {
		   /* ... */
	       }
	   }

       When the	first limit from the first rule	expires, it  will  also	 ``ex-
       pire''  (possibly  reached)  second  limit from the first rule, restart
       (possibly not reached) first limit from the second rule and it will add
       1000 units of statistics	to the second rule.

   Freezing work of ipa(8)
       It is sometime necessary	to be sure that	 ipa(8)	 does  nothing	during
       some  period  of	 time.	There are two parameters which allow to	freeze
       work of ipa(8).

       First parameter sleep_after_dump	allows to specify period of time  dur-
       ing which ipa(8)	should sleep and ignore	any signals after execution of
       the dump	command	from ipactl(8).

       Second  parameter  freeze_time  allows to specify period	of time	during
       which ipa(8) should sleep and ignore any	signals	 after	receiving  the
       freeze command from ipactl(8).

       These parameters	have the following arguments:

	   freeze_time = <time>;
	   sleep_after_dump = <time>;

       Values  of  these parameter should not be relatively big, because there
       is a chance that	some time event	can be checked too late.  The  default
       value of	each parameter is equal	to zero.

       These parameters	should not be placed in	any section.

       Example:

	   freeze_time = 30s;
	   sleep_after_dump = 5s;

       Here we say ipa(8) to sleep 5 seconds after the dump command, and sleep
       30 seconds after	the freeze command.  The scenario is the following: we
       send the	dump command (for example, if we want to fetch current statis-
       tics  later),  and  we send the freeze command to freeze	work of	ipa(8)
       and change something in the system.  Here we  assume  that  30  seconds
       will be enough to make all necessary changes in the system.

   Order of active rules
       ipa(8)  checks  rules starting from the head of the active rules	queue.
       If all rules are	independent, then one should not worry about their or-
       der; but	if, for	example, rule r1 should	be  checked  before  rule  r2,
       then read following several paragraphs.

       If  there  is not any ac_gather_* parameters and	there is not any work-
       time parameters,	then the order of active rules is the same as the  or-
       der of rules in the configuration file.

       If there	is at least one	ac_gather_* parameter, then the	order of rules
       is  changed to follow dependencies specified in ac_gather_* parameters,
       but if some rules do not	match regular expressions given	in ac_gather_*
       parameters, then	their relative order is	the same as their relative or-
       der in the configuration	file.

       If there	is not any ac_gather_* parameters and  there  are  rules  with
       worktime	parameters, then the order of these rules can be changed.

       Dynamic	rules  always are added	to the head of the active rules	queue,
       because dynamic rules cannot have ac_gather_* parameters, but some sta-
       tic rule	can get	statistics from	dynamic	rules and  dynamic  rules  can
       have worktime parameters.

       To keep the order of active rules the same as the order of rules	in the
       configuration  file  set	 the keep_rules_order parameter	to ``yes' (the
       default value is	``no''):

	   keep_rules_order = <boolean>;

       Be careful with the order of rules in the  configuration	 file  if  you
       have  at	least one ac_gather_* parameter	and the	keep_rules_order para-
       meter is	set to ``yes'':	place rules which give statistics below	 rules
       which get statistics.

       Limits  and  thresholds	in  one	rule are checked in the	same order, as
       they are	written	in the configuration and this order  is	 not  changed.
       All limits are checked before thresholds	in one rule.

       Note that some modules are sensitive to the order of active rules.

       This parameter should not be placed in any section.

       Example:

	   keep_rules_order = yes;

       Now ipa(8) will not change the order of active rules.

   Debugging
       Sometime	 it  is	necessary to find out why something goes wrong.	 There
       are some	parameters which can be	used for debugging:

       debug_ac_null  -	report when null accounting system is used (alone, 1);
       debug_db_null  -	report when null database is used (alone, 1);
       debug_time     -	debug various time related events (alone, 2);
       debug_worktime -	debug worktime parameters (alone, 1);
       debug_exec     -	debug exec parameters (rule, 1);
       debug_autorule -	debug autorules	(alone,	1);
       debug_limit    -	debug limit related events (rule, 1);
       debug_limit_init	- report about limit initialization (rule, 1);
       debug_threshold	- debug	threshold related events (rule,	1);
       debug_threshold_init - report about threshold initialization (rule, 1).

       Each debugging parameter	accepts	a debug	level as an argument,  maximum
       debug level for each debug parameter is specified as a number in	paren-
       thesis.	 If there is a word ``alone'' in parenthesis, then a parameter
       should not be placed in any section.  If	there is a  word  ``rule''  in
       parenthesis,  then  a  parameter	can be placed in global, rule, rulepat
       and autorule sections.

       By default debugging is off for everything.

       Example:

	   debug_worktime = 1;

	   global {
	       debug_limit_init	= 1;
	   }

       In this example detail information will be sent to the log  file	 about
       worktime's  time	 intervals  and	 about	limits	initialization for all
       rules.

FILES
       ipa.conf

       (run ipa(8) with	the -h switch and  check  default  configuration  file
       pathname)

SEE ALSO
       ipa(8), ipactl(8), ipastat(8), ipastat.conf(5), ipa_mod(3)

AUTHOR
       Andrey Simonenko	<simon@comsys.ntu-kpi.kiev.ua>

BUGS
       If you find any,	please send email me.

				 March 3, 2010			   IPA.CONF(5)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=ipa.conf&sektion=5&manpath=FreeBSD+Ports+14.3.quarterly>

home | help