SmartRoute
Rule based connects
Draft 4 - Aug 19, 1994
by Tony Vencill

Rule based connects allow an admin to specify under what conditions
a connect should not be allowed.  If no rules are specified for a
given C and/or N line it will be allowed under any condition.

A rule may consist of any legal combination of the following functions
and operators.

Functions
---------
connected(targetmask)     - true if a server other than that processing
                            the rule is connected that matches the
                            target mask
directcon(targetmask)     - true if a server other than that processing
                            the rule is directly connected that matches
                            the target mask
via(viamask, targetmask)  - true if a server other than that processing
                            the rule matches the target mask and is
                            connected via a directly connected server
                            that matches the via mask
directop()                - true if an oper is directly connected

Unary operators
---------------
!    eg: !argument        - true if the argument is false

Binary operartors
-----------------
&&   eg: arg1&&arg2       - true if arg1 and arg2 are both true
||   eg: arg1||arg2       - true if arg1, arg2, or both are true

Parenthesis () are allowed for grouping arguments, but if no parenthesis
are included, && will take precedence over ||, ! will take precedence
over both && and ||, and the function will be evaluated from left to
right.  White space in a rule is ignored.  Invalid characters in a rule
will lead to the rule being ignored.

Examples
--------

A simple example of a connect rule might be:

connected(*eu.under*)

This might be used in a US undernet server for a Europe CN pair to
insure that a second Europe link is not allowed if one US-EU link
already exists.  Note that on the undernet, US server names are
city.state.us.undernet.org and Europe server names are
city.country.eu.undernet.org.

A more interesting example might be:

connected(*eu.under*) && 
  ( !direct(*eu.under*) || via(manhat*, *eu.under*) )

Imagine the Boston undernet server uses this rule on its Europe CN
pairs.  This says that if a Europe server is already connected, a
Boston-Europe connect will not be allowed.  It also says that if a
Europe server does already exist and Boston is not directly connected
to one or more Europe servers or Manhattan is, the Boston-Europe
connect will not be allowed.  This has the effect of allowing multiple
US-EU links but attempting to limit these links to one server (ie:
Boston will not initiate its first Europe link if another server is
already linking Europe).  This rule will also prefer to let Manhattan
handle the US-EU link by disallowing Boston-Europe links if a Europe
server is already linked to Manhattan.

A example of the remaining function, directop(), is:

connected(*eu.under*) || directop()

If this line is used on Boston for the Paderborn CN pair, it will allow
connects to Paderborn only if another Europe server is not already
connected and there is not an oper on Boston.  If this rule is
overrideable (ie: is applied only to autoconnects as described below),
then it will disallow Boston autoconnects to Paderborn while a Boston
oper is online, but allow oper-initiated connects to Paderborn under any
circumstance.  This directop() function could be used to invoke less
prefered routes only when an oper is not present to handle routing, or
conversly to allow use of less preferable routes only when an oper is
present to monitor their performance.

ircd.conf entries
-----------------

A rule is listed in the ircd.conf file using a D or d line (which can
be thought of as a "disallow" line).  D lines will apply to all oper
and server originated connects, while d lines will apply only to
autoconnects (ie: they are overrideable by opers).  The formats are:

D:targetmask::rule
d:targetmask::rule

Remember that newlines are not allowed in conf lines.  Two examples
(from above) are:

D:*eu.under*::connected(*eu.under*)
d:*eu.under*::connected(*eu.under*) || directop()

Connects originating from other servers will be checked against and
matching D lines, while matching d lines will be ignored as it will not
be clear whether or not the connection attempt is oper initiated.

Checking and viewing rules
--------------------------

The chkconf program that comes with the servers has been modified to
also check your connect rules.  If running in debug mode, parsing errors
will show up at debug level 8.  To view rules online, "/stats d" can be
used to see all rules and "/stats D" can be used to view those rules
which affect oper initiated connects and accepts.

Processing and storage
----------------------

The rules are parsed when the conf file is read and transformed into a
more efficiently computed form, then all applicable rules are
evaluated each time a connect command is given or an autoconnect is
due.  If more than one applicable rule is given, only one need
evaluate to true for the connect to be allowed (ie: the rules are ored
together).  Note that conditions that exist when the connect is
initiated might differ from conditions when the link is established.
