New build path variable
[freeradius.git] / doc / configurable_failover.rst
index 2598e89..89c6876 100644 (file)
@@ -1,37 +1,41 @@
-       Configurable Module Fail Over
-       -----------------------------
+Configurable Module Fail Over
+=============================
 
 Before configurable module failover, we had this kind of entry in
-"radiusd.conf":
-
-#---
-authorize {
-  preprocess
-  files
-}
-#---
-
-  This entry instructed the "authorize" section to first process the
-request through the "preprocess" module, and if that returned success,
-to process it through "files" module.  If that sequence returned
-success, then the "authorize" stage itself would then return success.
+``radiusd.conf``:
+
+::
+
+  #---
+  authorize {
+    preprocess
+    files
+  }
+  #---
+
+This entry instructed the ``authorize`` section to first process the
+request through the ``preprocess`` module, and if that returned success,
+to process it through ``files`` module.  If that sequence returned
+success, then the ``authorize`` stage itself would then return success.
 Processing was strictly linear and if one module failed, the whole
 section would fail immediately.
 
-  Configurable failover provides more flexibility. It takes advantage
+Configurable failover provides more flexibility. It takes advantage
 of the tree structure of radiusd.conf to support a configuration
-language that allows you to "group" modules that should work together
+language that allows you to ``group`` modules that should work together
 in ways other than simple lists.  You can control the flow of any
-stage (e.g. "authorize") to fit your needs, without touching C code,
+stage (e.g. ``authorize``) to fit your needs, without touching C code,
 just by altering radiusd.conf.
 
-  This configurable fail-over has a convenient short-hand, too.
+This configurable fail-over has a convenient short-hand, too.
 Administrators commonly want to say things like "try SQL1, if it's
 down, try SQL2, otherwise drop the request."
 
-  For example:
+For example:
+
+::
 
-#---
+  #---
   modules {
     sql sql1 {
       # configuration to connect to SQL database one
@@ -51,37 +55,39 @@ down, try SQL2, otherwise drop the request."
         sql1                   # try module sql1
         sql2                   # if that's down, try module sql2
        handled                 # otherwise drop the request as
-                               # it's been "handled" by the "always"
+                               # it's been ``handled`` by the ``always``
                                # module (see doc/rlm_always)
       }
   }
-#---
+  #---
 
-  The "redundant" section is a configuration directive which tells the
+The ``redundant`` section is a configuration directive which tells the
 server to process the second module if the first one fails.  Any
-number of modules can be listed in a "redundant" section.  The server
-will process each in turn, until one of the modules succeeds.  It willthen stop processing the "redundant" list.
+number of modules can be listed in a ``redundant`` section.  The server
+will process each in turn, until one of the modules succeeds.  It will then stop processing the ``redundant`` list.
 
-1. Rewriting results for single modules
-   ------------------------------------
+Rewriting results for single modules
+------------------------------------
 
-  Normally, when a module fails, the entire section ("authorize",
-"accounting", etc.) stops being processed.  In some cases, we may want
-to permit "soft failures".  That is, we may want to tell the server
+Normally, when a module fails, the entire section (``authorize``,
+``accounting``, etc.) stops being processed.  In some cases, we may want
+to permit  "soft failures".  That is, we may want to tell the server
 that it is "ok" for a module to fail, and that the failure should not
 be treated as a fatal error.
 
-  In this case, the module is treated as a "section", rather than just
-as a single line in "radiusd.conf".  The configuration entries for
-that section are taken from the "configurable fail-over" code, and not
+In this case, the module is treated as a "section", rather than just
+as a single lne in ``radiusd.conf``.  The configuration entries for
+that section are taken from the ``configurable fail-over`` code, and not
 from the configuration information for that module.
 
-  For example, the "detail" module normally returns "fail" if it is
-unable to write its information to the "detail" file.  As a test, we
+For example, the ``detail`` module normally returns ``fail`` if it is
+unable to write its information to the ``detail`` file.  As a test, we
 can configure the server so that it continues processing the request,
-even if the "detail" module fails.  The following example shows how:
+even if the ``detail`` module fails.  The following example shows how:
 
-#--
+::
+
+  #--
   #  Handle accounting packets
   accounting {
       detail {
@@ -93,122 +99,137 @@ even if the "detail" module fails.  The following example shows how:
        handled
       }
   }
-#--
-
-  The "fail = 1" entry tells the server to remember the "fail" code,
-with priority "1".  The normal configuration is "fail = return", which
-means "if the detail module fails, stop processing the accounting
-section".
-
-2. Fail-over configuration entries
-   -------------------------------
-
-  Modules normally return on of the following codes as their result:
-
-       Code            Meaning
-       ----            ------
-       notfound        the user was not found
-       noop            the module did nothing
-       ok              the module succeeded
-       updated         the module updated information in the request
-       fail            the module failed
-       reject          the module rejected the user
-       userlock        the user was locked out
-       invalid         the user's configuration entry was invalid
-       handled         the module has done everything to handle the request
+  #--
+
+The ``fail = 1`` entry tells the server to remember the ``fail`` code,
+with priority ``1``.  The normal configuration is ``fail = return``, which
+means ``if the detail module fails, stop processing the accounting
+section``.
+
+Fail-over configuration entries
+-------------------------------
+
+Modules normally return on of the following codes as their result:
+
++-----------+-----------------------------------------------------+
+|Code      | Meaning                                             |
++===========+=====================================================+
+|notfound   | the user was not found                              |
++-----------+-----------------------------------------------------+
+|noop      | the module did nothing                              |
++-----------+-----------------------------------------------------+
+|ok        | the module succeeded                                |
++-----------+-----------------------------------------------------+
+|updated    | the module updated information in the request       |
++-----------+-----------------------------------------------------+
+|fail       | the module failed                                   |
++-----------+-----------------------------------------------------+
+|reject     | the module rejected the user                        |
++-----------+-----------------------------------------------------+
+|userlock   | the user was locked out                             |
++-----------+-----------------------------------------------------+
+|invalid    | the user's configuration entry was invalid          |
++-----------+-----------------------------------------------------+
+|handled    | the module has done everything to handle the request|
++-----------+-----------------------------------------------------+
        
-  In a configurable fail-over section, each of these codes may be
+In a configurable fail-over section, each of these codes may be
 listed, with a value.  If the code is not listed, or a configurable
 fail-over section is not defined, then values that make sense for the
-requested "group" (group, redundant, load-balance, etc) are used.
+requested ``group`` (group, redundant, load-balance, etc) are used.
 
-  The special code "default" can be used to set all return codes to
+The special code ``default`` can be used to set all return codes to
 the specified value.  This value will be used with a lower priority
 than ones that are explicitly set.
 
-  The values for each code may be one of two things:
+The values for each code may be one of two things:
 
-       Value           Meaning
-       -----           -------
-       <number>        Priority for this return code.
-       return          stop processing this configurable fail-over list.
-       reject          Stop processing this configurable fail-over list.
-                       and immediately return a reject.
++---------+---------------------------------------------------------------+
+|Value   | Meaning                                                       |
++=========+===============================================================+
+|<number> | Priority for this return code.                                |
++---------+---------------------------------------------------------------+
+|return          | Stop processing this configurable fail-over list.             |
++---------+---------------------------------------------------------------+
+|reject          | Stop processing this configurable fail-over list and          |
+|         | immediately return a reject.                                  |
++---------+---------------------------------------------------------------+
 
-  The <number> used for a value may be any decimal number between 1
+The ``<number>`` used for a value may be any decimal number between 1
 and 99999.  The number is used when processing a list of modules, to
 determine which code is returned from the list.  For example, if
-"module1" returns "fail" with priority "1", and a later "module2"
-returns "ok" with priority "3", the return code from the list of
-modules will be "ok", because it has higher priority than "fail".
+``module1`` returns ``fail`` with priority ``1``, and a later ``module2``
+returns ``ok`` with priority ``3``, the return code from the list of
+modules will be ``ok``, because it has higher priority than ``fail``.
 
-  This configurability allows the administrator to permit some modules
+This configurability allows the administrator to permit some modules
 to fail, so long as a later module succeeds.
 
 
-3. More Complex Configurations
-   ---------------------------
+More Complex Configurations
+---------------------------
 
-  The "authorize" section is normally a list of module names.  We can
-create sub-lists by using the section name "group".  The "redundant"
-section above is just a short-hand for "group", with a set of default
-return codes, which are different than the normal "stop processing the
-list on failure".
+The ``authorize`` section is normally a list of module names.  We can
+create sub-lists by using the section name ``group``.  The ``redundant``
+section above is just a short-hand for ``group``, with a set of default
+return codes, which are different than the normal ``stop processing the
+list on failure``.
 
-  For example, we can configure two detail modules, and allow either
+For example, we can configure two detail modules, and allow either
 to fail, so long as one of them succeeds.
 
-#--
+::
+
+  #--
   #  Handle accounting packets
   accounting {
       group {
         detail1 {
-          fail = 1             # remember "fail" with priority 1
-         ok = return           # if we succeed, don't do "detail2"
+          fail = 1             # remember ``fail`` with priority 1
+         ok = return           # if we succeed, don't do ``detail2``
         }
        detail2 {
-         fail = 1              # remember "fail" with priority 1
-         ok = return           # if we succeed, return "ok"
-                               # if "detail1" returned "fail"
+         fail = 1              # remember ``fail`` with priority 1
+         ok = return           # if we succeed, return ``ok``
+                               # if ``detail1`` returned ``fail``
        }
-      }                        # returns "fail" only if BOTH modules returned "fail"
+      }                        # returns ``fail`` only if BOTH modules returned ``fail``
       redundant {
         sql1
         sql2
        handled
       }
   }
+  #--
 
-#--
+This configuration says:
 
-  This configuration says:
+       - log to ``detail1``, and stop processing the ``group`` list if ``detail1`` returned OK.
 
-       log to "detail1", and stop processing the "group" list if
-       "detail1" returned OK.
+       - If ``detail1`` returned ``fail``, then continue, but remember the ``fail`` code, with priority 1.
 
-       If "detail1" returned "fail", then continue, but remember the
-       "fail" code, with priority 1.
+       - If ``detail2`` fails, then remember ``fail`` with priority 1.
 
-       If "detail2" fails, then remember "fail" with priority 1.
+       - If ``detail2`` returned ``ok``, return ``ok`` from the ``group``.
 
-       If "detail2" returned "ok", return "ok" from the "group".
-
-  The return code from the "group" is the return code which was either
-forced to return (e.g. "ok" for "detail1"), or the highest priority
+The return code from the ``group`` is the return code which was either
+forced to return (e.g. ``ok`` for ``detail1``), or the highest priority
 return code found by processing the list.
 
-  This process can be extended to any number of modules listed in a
-"group" section.
+This process can be extended to any number of modules listed in a
+``group`` section.
 
 
-4. Virtual Modules
-   ---------------
+Virtual Modules
+---------------
 
-  Some configurations may require using the same list of modules, in
+Some configurations may require using the same list of modules, in
 the same order, in multiple sections.  For those systems, the
-configuration can be simplified through the use of "virtual" modules.
+configuration can be simplified through the use of ``virtual`` modules.
 These modules are configured as named sub-sections of the
-"instantiate" section, as follows:
+``instantiate`` section, as follows:
+
+::
 
        instantiate {
                ...
@@ -219,25 +240,25 @@ These modules are configured as named sub-sections of the
                }
        }
 
-  The name "sql1_or_2" can then be used in any other section, such as
-"authorize" or "accounting".  The result will be *exactly* as if that
-section was placed at the location of the "sql1_or_2" reference.
+The name ``sql1_or_2`` can then be used in any other section, such as
+``authorize`` or ``accounting``.  The result will be *exactly* as if that
+section was placed at the location of the ``sql1_or_2`` reference.
 
-  These virtual modules are full-fledged objects in and of themselves.
+These virtual modules are full-fledged objects in and of themselves.
 One virtual module can refer to another virtual module, and they can
-contain "if" conditions, or any other configuration permitted in a
+contain ``if`` conditions, or any other configuration permitted in a
 section.
 
 
-5. Redundancy and Load-Balancing
-   -----------------------------
+Redundancy and Load-Balancing
+-----------------------------
 
-  See "man unlang" or doc/load-balance.txt for information on simple
+See ``man unlang`` or ``doc/load-balance`` for information on simple
 redundancy (fail-over) and load balancing.
 
 
-6. The Gory Details
-   ----------------
+The Gory Details
+-----------------
 
 The fundamental object is called a MODCALLABLE, because it is something that
 can be passed a specific radius request and returns one of the RLM_MODULE_*
@@ -246,51 +267,53 @@ radiusd.conf are functions. There are two kinds of MODCALLABLEs: GROUPs and
 SINGLEs.
 
 A SINGLE is a reference to a module instance that was set up in the modules{}
-section of radiusd.conf, like "preprocess" or "sql1". When a SINGLE is
+section of radiusd.conf, like ``preprocess`` or ``sql1``. When a SINGLE is
 called, the corresponding function in the rlm is invoked, and whichever
 RLM_MODULE_* it returns becomes the RESULT of the SINGLE.
 
 A GROUP is a section of radiusd.conf that includes some MODCALLABLEs.
-Examples of GROUPs above include "authorize{...}", which implements the C
-function module_authorize, and "redundant{...}", which contains two SINGLEs
+Examples of GROUPs above include ``authorize{...}``, which implements the C
+function module_authorize, and ``redundant{...}``, which contains two SINGLEs
 that refer to a couple of redundant databases. Note that a GROUP can contain
-other GROUPs - "Auth-Type SQL{...}" is also a GROUP, which implements the C
+other GROUPs - ``Auth-Type SQL{...}`` is also a GROUP, which implements the C
 function module_authenticate when Auth-Type is set to SQL.
 
 Now here's the fun part - what happens when a GROUP is called? It simply runs
 through all of its children in order, and calls each one, whether it is
 another GROUP or a SINGLE. It then looks at the RESULT of that child, and
-takes some ACTION, which is basically either "return that RESULT immediately"
-or "Keep going". In the first example, any "bad" RESULT from the preprocess
-module causes an immediate return, and any "good" RESULT causes the
+takes some ACTION, which is basically either ``return that RESULT immediately``
+or ``Keep going``. In the first example, any ``bad`` RESULT from the preprocess
+module causes an immediate return, and any ``good`` RESULT causes the
 authorize{...} GROUP to proceed to the files module.
 
 We can see the exact rules by writing them out the long way:
 
-authorize {
-  preprocess {
-    notfound = 1
-    noop     = 2
-    ok       = 3
-    updated  = 4
-    fail     = return
-    reject   = return
-    userlock = return
-    invalid  = return
-    handled  = return
-  }
-  files {
-    notfound = 1
-    noop     = 2
-    ok       = 3
-    updated  = 4
-    fail     = return
-    reject   = return
-    userlock = return
-    invalid  = return
-    handled  = return
+::
+
+  authorize {
+    preprocess {
+      notfound = 1
+      noop     = 2
+      ok       = 3
+      updated  = 4
+      fail     = return
+      reject   = return
+      userlock = return
+      invalid  = return
+      handled  = return
+    }
+    files {
+      notfound = 1
+      noop     = 2
+      ok       = 3
+      updated  = 4
+      fail     = return
+      reject   = return
+      userlock = return
+      invalid  = return
+      handled  = return
+    }
   }
-}
 
 This is the same as the first example, with the behavior explicitly
 spelled out. Each SINGLE becomes its own section, containing a list of
@@ -299,22 +322,23 @@ preprocess is called, and if it returns for example RLM_MODULE_REJECT,
 then the reject=return rule is applied, and the authorize{...} GROUP
 itself immediately returns RLM_MODULE_REJECT.
 
-If preprocess returns RLM_MODULE_NOOP, the corresponding ACTION is "2". An
+If preprocess returns RLM_MODULE_NOOP, the corresponding ACTION is ``2``. An
 integer ACTION serves two purposes - first, it tells the parent GROUP to go
 on to the next module. Second, it is a hint as to how desirable this RESULT
 is as a candidate for the GROUP's own RESULT. So files is called... suppose
 it returns RLM_MODULE_NOTFOUND. The ACTION for notfound inside the files{...}
-block is "1". We have now reached the end of the authorize{...} GROUP and we
+block is ``1``. We have now reached the end of the authorize{...} GROUP and we
 look at the RESULTs we accumulated along the way - there is a noop with
 preference level 2, and a notfound with preference level 1, so the
 authorize{...} GROUP as a whole returns RLM_MODULE_NOOP, which makes sense
 because to say the user was not found at all would be a lie, since preprocess
 apparently found him, or else it would have returned RLM_MODULE_NOTFOUND too.
 
-We could use the "default" code to simplify the above example a
+We could use the ``default`` code to simplify the above example a
 little.  The following two configurations are identical:
 
-...
+::
+
   files {
     notfound = 1
     noop     = 2
@@ -322,12 +346,13 @@ little.  The following two configurations are identical:
     updated  = 4
     default  = return
   }
-...
 
-When putting the "default" first, later definitions over-ride it's
+
+When putting the ``default`` first, later definitions over-ride it's
 return code:
 
-...
+::
+
   files {
     default  = return
     notfound = 1
@@ -335,8 +360,6 @@ return code:
     ok       = 3
     updated  = 4
   }
-...
-
 
 [Take a deep breath - the worst is over]
 
@@ -348,6 +371,8 @@ defaults will be right for the most common configurations.
 So where does redundant{...} fit in with all that? Well, redundant{...} is
 simply a group that changes the default ACTIONs to something like
 
+::
+
   fail = 1
   everythingelse = return
 
@@ -356,14 +381,19 @@ fail, then return whatever it returned. And at the end, if they all failed,
 the redundant GROUP as a whole returns RLM_MODULE_FAIL, just as you'd want it
 to (I hope).
 
-There are two other kinds of grouping: group{...} which does not have any
-specialized default ACTIONs, and append{...}, which should be used when you
+There are two other kinds of grouping: ``group{...}`` which does not have any
+specialized default ACTIONs, and ``append{...}``, which should be used when you
 have separate but similarly structured databases that are guaranteed not to
 overlap.
 
 That's all that really needs to be said. But now a few random notes:
 
-1. GROUPs may have RESULT=ACTION specifiers too! It would look like this:
+GROUPs may have RESULT=ACTION
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+It would look like this:
+
+::
 
   authorize {
     preprocess
@@ -375,10 +405,16 @@ That's all that really needs to be said. But now a few random notes:
     files
   }
 
-which would prevent rlm_files from being called if neither of the SQL
+which would prevent ``files`` from being called if neither of the SQL
 instances could find the user.
 
-2. redundant{...} and append{...} are just shortcuts. You could write
+redundant{...} and append{...} are just shortcuts
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You could write:
+
+::
+
     group {
       sql1 {
         fail     = 1
@@ -408,23 +444,31 @@ instances could find the user.
       sql1
       sql2
     }
-  but the latter is just a whole lot easier to read.
 
-3. "authenticate{...}" itself is not a GROUP, even though it contains a list
-of Auth-Type GROUPs, because its semantics are totally different - it uses
-Auth-Type to decide which of its members to call, and their order is
-irrelevant.
+but the latter is just a whole lot easier to read.
+
+``authenticate{...}`` is not a GROUP
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+even though it contains a list of ``Auth-Type`` GROUPs, because its
+semantics are totally different - it uses ``Auth-Type`` to decide which of
+its members to call, and their order is irrelevant.
 
-4. The default rules are context-sensitive - for authorize, the defaults are
+The default rules are context-sensitive
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+For ``authorize``, the defaults are
 what you saw above - notfound, noop, ok, and updated are considered
-success, and anything else has an ACTION of "return". For authenticate, the
+success, and anything else has an ACTION of ``return``. For authenticate, the
 default is to return on success *or* reject, and only try the second and
 following items if the first one fails. You can read all the default ACTIONs
 in modcall.c (int defaultactions[][][]), or just trust me. They do the right
 thing.
 
-5. There are some rules that can't be implemented in this language - things
-like "notfound = 1-reject", "noop = 2-ok", "ok = 3-ok", etc. But I don't feel
+There are some rules that can't be implemented in this language
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+things like ``notfound = 1-reject``, ``noop = 2-ok``, ``ok = 3-ok``, etc. But I don't feel
 justified adding that complexity in the first draft.
 There are already enough things here that may never see real-world usage.
 Like append{...}