Provided by: freeradius-common_3.0.16+dfsg-1ubuntu3.2_all bug

NAME

       unlang - FreeRADIUS Processing un-language

DESCRIPTION

       FreeRADIUS  supports  a simple processing language in its configuration files.  We call it
       an "un-language" because the intention is NOT to create yet another programming  language.
       If  you  need something more complicated than what is described here, we suggest using the
       Perl or Python modules rlm_perl, or rlm_python.

       The goal of the language is to allow simple policies to be written  with  minimal  effort.
       Those policies are then applied when a request is being processed.  Requests are processed
       through virtual servers (including the default one), in the sections  titled  "authorize",
       "authenticate",  "post-auth",  "preacct",  "accounting",  "pre-proxy",  "post-proxy",  and
       "session".

       These policies cannot be used in any other part of the configuration files, such as module
       or client configuration.

KEYWORDS

       The keywords for the language are a combination of pre-defined keywords, and references to
       loadable module names.  We document only the pre-defined keywords here.

       Subject to a few limitations described below, any keyword can appear in any context.   The
       language  consists  of  a  series of entries, each one one line.  Each entry begins with a
       keyword.  Entries are organized into lists.  Processing of the language is line  by  line,
       from the start of the list to the end.  Actions are executed per-keyword.

       module-name[.section-name]
              A  reference  to  the  named  module.  When processing reaches this point, the pre-
              compiled module is called.  The module may succeed  or  fail,  and  will  return  a
              status  to  "unlang"  if  so.   This  status can be tested in a condition.  See the
              "Simple Conditions" text in the CONDITIONS section, and MODULE RETURN CODES, below.
              If  a  section-name  is provided, it will cause the module to execute as if it were
              listed in the named section.

                   chap  # call the CHAP module
                   sql   # call the SQL module
                   ...

       if
              Checks for a particular condition.  If true,  the  block  after  the  condition  is
              processed.    Otherwise,   the  block  is  ignored.   See  CONDITIONS,  below,  for
              documentation on the format of the conditions.

                   if (condition) {
                        ...
                   }

       else
              Define a block to be executed only if the previous "if" condition returned false.

                   else {
                        ...
                   }

       elsif
              Define a block to be executed only if the previous "if" condition  returned  false,
              and if the specified condition evaluates to true.

                   elsif (condition) {
                        ...
                   }

       foreach
              Loops  over  values  of an attribute, running the block for each value.  The return
              value of the block is the return value of the last statement  executed.   The  loop
              can  be exited early by using the "break" keyword.  Unlike other languages, "break"
              here means "exit the loop at the next iteration", not "exit  the  loop  now".   The
              result is that any statements after the "break" keyword will still be executed.  We
              recommend using "break" only when it is the last statement in a "foreach" block.

              Inside of the "foreach" block, the attribute which is  being  looped  over  can  be
              referenced  as  "Foreach-Variable-#".  Where "#" is the depth of the loop, starting
              at "0".  e.g. "Foreach-Variable-0".  The loops can be nested up to eight (8)  deep,
              though this is not recommended.

                   foreach &Attribute-Reference {
                        ...
                   }

       switch
              A  "switch"  statement  takes  one  argument,  and  contains  a  series  of  "case"
              statements.  When a "switch"  statement  is  encountered,  the  argument  from  the
              "switch" is evaluated in turn against the argument from each "case" statement.  The
              first "case" statement which matches is executed.  All other "case" statements  are
              ignored.  A default "case" statement can be defined, by omitting its argument.

              If  the argument is a double quoted string (e.g. "%{exec:1 + 2}", it is expanded as
              described in the DATA TYPES section, below.  The match is  then  performed  on  the
              string  returned  from  the  expansion.   If the argument is an attribute reference
              (e.g. &User-Name), then the match is performed on  the  value  of  that  attribute.
              Otherwise,  the  argument is taken to be a literal string, and and matching is done
              via simple comparison.

              No statement other than "case" can appear in a "switch" block.

                   switch <argument> {
                        ...
                   }

       case
              Provides a place-holder which matches the argument of a parent "switch" statement.

              A "case" statement cannot appear outside of a "switch" block.

              If the argument is a double quoted string (e.g. "%{exec:1 + 2}", it is expanded  as
              described  in  the  DATA  TYPES section, below.  The match is then performed on the
              string returned from the expansion.  If the  argument  is  an  attribute  reference
              (e.g.  &User-Name),  then  the  match  is performed on the value of that attribute.
              Otherwise, the argument is taken to be a literal string, and and matching  is  done
              via simple comparison.

                   case <argument> {
                        ...
                   }  A  default  entry  can be defined by omitting the argument, as given below.
              This entry will be used if no other "case" entry matches.  Only one  default  entry
              can exist in a "switch" section.

                   case {
                        ...
                   }

       update
              Update  a  particular  attribute list, based on the attributes given in the current
              block.

                   update <list> {
                        &Attribute-Reference = value
                        ...
                   } The <list> can be one of "request", "reply", "proxy-request", "proxy-reply",
              "coa",  "disconnect",  "session-state",  or "control".  As of Version 3, the <list>
              can be omitted, in which case "request" is assumed.

              The "control" list is the list of attributes maintainted internally by  the  server
              that controls how the server processes the request.  Any attribute that does not go
              in a packet on the network will generally be placed in the "control" list.

              For EAP methods with tunneled authentication sessions (i.e. PEAP and EAP-TTLS), the
              inner  tunnel  session  can  also  reference  "outer.request",  "outer.reply",  and
              "outer.control".  Those references allow you to address the relevant  list  in  the
              outer tunnel session.

              The  "coa"  and  "disconnect" sections can only be used when the server receives an
              Access-Request or Accounting-Request.  Use "request" and "reply" instead  of  "coa"
              when the server receives a CoA-Request or Disconnect-Request packet.

              Adding  one  or  more attributes to either of the "coa" or "disconnect" list causes
              server to originate a CoA-Request or Disconnect-Request  packet.   That  packet  is
              sent when the current Access-Request or Accounting-Request has been finished, and a
              reply sent to the  NAS.   See  raddb/sites-available/originate-coa  for  additional
              information.

              The  "session-state"  list  is  primarily  used  for  EAP.  Attributes put into the
              "session-state" list are saved for the  next  packet  in  the  session.   They  are
              automatically retrieved when the next packet is received.

              The  only contents permitted in an "update" section are attributes and values.  The
              contents of the "update" section are  described  in  the  ATTRIBUTE  REFERENCE  and
              ATTRIBUTE ASSIGNMENT sections below.

       redundant
              This  section  contains  a simple list of modules.  The first module is called when
              the section is being processed.  If the first module  succeeds  in  its  operation,
              then the server stops processing the section, and returns to the parent section.

              If,  however,  the  module  fails,  then  the  next module in the list is tried, as
              described above.  The processing continues until one module succeeds, or until  the
              list has been exhausted.

              Redundant  sections can contain only a list of modules, and cannot contain keywords
              that perform conditional operations (if, else, etc) or update an attribute list.

                   redundant {
                        sql1 # try this
                        sql2 # try this only if sql1 fails.
                        ...
                   }

       load-balance
              This section contains a simple list of modules.  When the section is  entered,  one
              module  is chosen at random to process the request.  All of the modules in the list
              should be the same type (e.g. ldap or sql).  All of the modules in the list  should
              behave  identically,  otherwise  the  load-balance  section  will  return different
              results for the same request.

              Load-balance sections can contain only  a  list  of  modules,  and  cannot  contain
              keywords that perform conditional operations (if, else, etc) or update an attribute
              list.

                   load-balance {
                        ldap1     # 50% of requests go here
                        ldap2     # 50% of requests go here
                   } In general, we recommend using "redundant-load-balance"  instead  of  "load-
              balance".

       redundant-load-balance
              This  section  contains a simple list of modules.  When the section is entered, one
              module is chosen at random to process the request.  If that module  succeeds,  then
              the  server  stops processing the section.  If, however, the module fails, then one
              of the remaining modules is chosen at random to process the request.  This  process
              repeats until one module succeeds, or until the list has been exhausted.

              All  of the modules in the list should be the same type (e.g. ldap or sql).  All of
              the modules in the list  should  behave  identically,  otherwise  the  load-balance
              section will return different results for the same request.

              Load-balance  sections  can  contain  only  a  list  of modules, and cannot contain
              keywords that perform conditional operations (if, else, etc) or update an attribute
              list.  Please  see  raddb/radiusd.conf "instantiate" section for more configuration
              examples.

                   redundant-load-balance {
                        ldap1     # 50%, unless ldap2 is down, then 100%
                        ldap2     # 50%, unless ldap1 is down, then 100%
                   }

       return
              Returns from the current top-level section,  e.g.  "authorize"  or  "authenticate".
              This keyword is mainly used to avoid layers of nested "if" and "else" statements.

                   authorize {
                        if (...) {
                             ...
                             return
                        }
                        ...  # this is never reached when the "if"
                        ...  # statement is executed
                   }

ATTRIBUTE REFERENCES

       Attributes   may   be   referenced   via   the   following   syntax:       &Attribute-Name
            &Attribute-Name:TAG            &Attribute-Name[NUM]            &<list>:Attribute-Name
            &<list>:Attribute-Name:TAG[NUM] Where <list> is one of "request", "reply", "control",
       "proxy-request",  "proxy-reply",  or  "outer.request",   "outer.reply",   "outer.control",
       "outer.proxy-request",  or  "outer.proxy-reply". just as with the "update" section, above.
       The "<list>:" prefix is optional, and if omitted, is assumed to  refer  to  the  "request"
       list.

       The  TAG  portion  is  a  decimal  integer between 1 and 31.  Please see RFC 2868 for more
       information about tags.  Tags can only be used for attributes  which  are  marked  in  the
       dictionary as "has_tag".

       The  NUM  portion  is  used when there are multiple attributes of the same name in a list.
       The "Attribute-Name" reference will return the first attribute.   Using  an  array  offset
       allows the policy to refer to the second and subsequent attributes.

       If  '*'  is used in the NUM portion, it evaluates to all instances of the attribute in the
       request.

       If 'n' is used in the NUM portion, it evaluates to the last instance of the  attribute  in
       the request.

       When  an attribute name is encountered, the given list is examined for an attribute of the
       given name.  Some examples are:      User-Name
            request:User-Name # same as above
            reply:User-Name
            Tunnel-Password:1
            Cisco-AVPAir[2]
            outer.request:User-Name # from inside of a TTLS/PEAP tunnel Note that unlike C, there
       is  no  way  to  define new attributes at run-time.  They MUST be declared in a dictionary
       file, and loaded when the server starts.

       All attributes  are  defined  in  the  dictionaries  that  accompany  the  server.   These
       definitions  define  only the name and type, and do not define the value of the attribute.
       When the server receives a packet, it uses the packet contents to look up entries  in  the
       dictionary,  and  instantiates  attributes  with a name taken from the dictionaries, and a
       value taken from the packet contents.  This process means that if an  attribute  does  not
       exist, it is usually because it was not contained in a packet that the server received.

       Once  the  attribute  is  instantiated, it is added to a list.  It can then be referenced,
       updated, replaced, etc.

CONDITIONS

       The conditions are similar to C conditions in syntax, though quoted strings are supported,
       as with the Unix shell.

       Simple conditions
                   (foo)  Evaluates to true if 'foo' is a non-empty string (single quotes, double
              quotes, or back-quoted).  Also evaluates to true if 'foo'  is  a  non-zero  number.
              Note  that the language is poorly typed, so the string "0000" can be interpreted as
              a numerical zero.  This issue can be avoided by  comparings  strings  to  an  empty
              string, rather than by evaluating the string by itself.

              If  the word 'foo' is not a quoted string, then it can be taken as a reference to a
              named attribute.   See  "Referencing  attribute  lists",  below,  for  examples  of
              attribute  references.   The  condition  evaluates  to  true if the named attribute
              exists.

              Otherwise, if the word 'foo' is not a  quoted  string,  and  is  not  an  attribute
              reference,  then  it  is  interpreted  as a reference to a module return code.  The
              condition evaluates to true if the most recent module return code matches the  name
              given here.  Valid module return codes are given in MODULE RETURN CODES, below.

       Negation
                   (!foo) Evaluates to true if 'foo' evaluates to false, and vice-versa.

       Short-circuit operators
                   (foo || bar)
                   (foo  &&  bar)  "&&" and "||" are short-circuit operators.  "&&" evaluates the
              first condition, and evaluates the second condition if and only if  the  result  of
              the  first  condition is true.  "||" is similar, but executes the second command if
              and only if the result of the first condition is false.

       Comparisons
                   (foo == bar) Compares 'foo' to 'bar', and evaluates to true if the  comparison
              holds true.  Valid comparison operators are "==", "!=", "<", "<=", ">", ">=", "=~",
              and "!~", all with their usual meanings.  The operators ":=" and "=" are assignment
              operators, and are not allowed for comparisons.

              The  operators  "<",  "<=",  ">", and ">=" are also allowed for checking that an IP
              address is contained within a network.  For example:      if  (<ipaddr>192.0.2.1  <
              192.0.2.0/24)  {  This  comparison  succeeds,  because  the  address  192.0.2.1  is
              contained within the network 192.0.2.0/24.

       Attribute Comparisons
              When doing attribute comparisons, the  data  type  of  the  attribute  is  used  to
              determine  the  data  type  of  the  right-hand side argument.       (&User-Name ==
              "foo") Compares the value of the User-Name  attribute  to  the  string  'foo',  and
              evaluates to true if the comparison holds true.

              Similarly,      (&Framed-IP-Address == 192.0.2.1) Compares the value of the Framed-
              IP-Address attribute to the IP address 192.0.2.1.  This IP address does not need to
              be quoted.

       Inter-Attribute Comparisons
                   (&User-Name  ==  &Filter-Id)  Compares the value of the User-Name attribute to
              the contents of the Filter-Id attribute, and evaluates to true  if  the  comparison
              holds  true.   Unlike  the previous example, this comparison is done in a type-safe
              way.  For example, comparing the IP addresses 1.2.3.4 and 127.0.0.1 as strings will
              return different results than comparing them as IP addresses.

              The  "&"  character  in  the  condition  means  that the comparison "refers" to the
              Filter-Id attribute.  If left  off,  it  means  that  the  User-Name  attribute  is
              compared to the literal string "Filter-Id".

              Where  the  left-hand side is an attribute, the "&" can be omitted.  However, it is
              allowed for backwards compatibility.  e.g. The comparison "(&User-Name ==  &Filter-
              Id)" is equivalent to the example above.

              We recommend using attribute references instead of printing attributes to a string,
              e.g. (User-Name == "%{Filter-Id}").  Attribute references will be faster  and  more
              efficient.

              The  conditions  will check only the first occurrence of an attribute.  If there is
              more than one instance of an attribute, the following syntax should be used:

                   (&Attribute-Name[*] == "foo") Using the "[*]" syntax means that it checks  all
              of  the  instances of the named attribute.  If one attribute matches, the condition
              succeeds.  If none match, the condition fails.

       Casts       (<type>foo == bar) The left-hand-side of  a  condition  can  be  "cast"  to  a
              specific data type.  The data type must be one which is valid for the dictionaries.
              e.g. "integer", "ipaddr", etc.

              The  comparison  is  performed  in  a  type-safe  way,  as  with   "Inter-Attribute
              Comparisons",  above.   Both  sides  of  the  condition  are  parsed into temporary
              attributes, and the attributes compared via type-specific methods.   The  temporary
              attributes have no other effect, and are not saved anywhere.

              Casting  allows  conditions  to  perform  type-specific  comparisons.   In previous
              versions of the server,  the  data  would  have  to  be  manually  placed  into  an
              intermediate  attribute  (or  attributes),  and  then the attribute (or attributes)
              compared.  The use of a cast allows for simpler policies.

              Casts are allowed only on the left-hand side argument of a condition.

       Conditions may be nested to any depth, subject  only  to  line  length  limitations  (8192
       bytes).

DATA TYPES

       There  are  only  a  few  data  types supported in the language.  Reference to attributes,
       numbers, and strings.  Any data type can appear in stand-alone condition,  in  which  case
       they are evaluated as described in "Simple conditions", above.  They can also appear (with
       some exceptions noted below) on the left-hand or on the right-hand side of a comparison.

       numbers
              Numbers are composed of decimal digits.  Floating point, hex, and octal numbers are
              not supported.  The maximum value for a number is machine-dependent, but is usually
              32-bits, including one bit for a sign value.

       word
              Text that is not enclosed in quotes is interpreted differently depending  on  where
              it  occurs in a condition.  On the left hand side of a condition, it is interpreted
              as a reference to an attribute.  On the right hand side, it  is  interpreted  as  a
              simple string, in the same manner as a single-quoted string.

              Using  attribute  references  permits limited type-specific comparisons, as seen in
              the examples below.

                   if (&User-Name == "bob") {
                        ...
                   if (&Framed-IP-Address > 127.0.0.1) {
                        ...
                   if (&Service-Type == Login-User) {

       "strings"
              Double-quoted strings are expanded by inserting the value of  any  attributes  (see
              VARIABLES,  below)  before  being  evaluated.   If  the  result  is  a number it is
              evaluated in a numerical context.

              String length is limited by line-length, usually about 8000 characters.   A  double
              quote  character can be used in a string via the normal back-slash escaping method.
              ("like \"this\" !")

       'strings'
              Single-quoted strings are evaluated as-is.  Their values are not expanded  as  with
              double-quoted strings above, and they are not interpreted as attribute references.

       `strings`
              Back-quoted  strings  are  evaluated  by  expanding  the contents of the string, as
              described above for double-quoted strings.  The resulting command given  inside  of
              the  string  in  a  sub-shell, and taking the output as a string.  This behavior is
              much the same as that of Unix shells.

              Note that for security  reasons,  the  input  string  is  split  into  command  and
              arguments before string expansion is done.

              For  performance reasons, we suggest that the use of back-quoted strings be kept to
              a minimum.  Executing external programs is relatively expensive,  and  executing  a
              large number of programs for every request can quickly use all of the CPU time in a
              server.  If you believe that you need to execute many programs, we suggest  finding
              alternative  ways to achieve the same result.  In some cases, using a real language
              may be sufficient.

       /regex/im
              These strings are valid only on the right-hand side of a comparison, and then  only
              when  the  comparison  operator  is "=~" or "!~".  They are regular expressions, as
              implemented by the local regular expression library on the system.  This is usually
              Posix regular expressions.

              The  trailing  'i'  is  optional,  and  indicates that the regular expression match
              should be done in a case-insensitive fashion.

              The trailing 'm' is also optional, and indicates that carrot  '^'  and  dollar  '$'
              anchors  should  match  on new lines as well as at the start and end of the subject
              string.

              If the comparison operator is "=~", then parenthesis in the regular expression will
              define  variables containing the matching text, as described below in the VARIABLES
              section.

EXPANSIONS

       Attributes are  expanded  using  the  ATTRIBUTE  REFERENCE  syntax  described  above,  and
       surrounding the reference with "%{...}"

            %{Attribute-Reference}

       The  result  will  be  a  string  which  contains  the  value  of  the attribute which was
       referenced, as a printable string.  If the attribute does not exist, the result will be an
       empty string.

       Results of regular expression matches
              If  a  regular  expression  match  has  previously been performed, then the special
              variable %{0} will contain a copy of the matched portion of the input string.   The
              variables  %{1} through %{32} will contain the substring matches, starting from the
              left-most capture group, onwards.  If there are more than 32  capture  groups,  the
              additional  results  will  not be accessible.  If the server is built with libpcre,
              the results of named  capture  groups  are  available  using  the  "%{regex:capture
              group}"  expansion.   They  will  also  be accessible using the variables described
              above.  Every time a regular expression is evaluated, whether it  matches  or  not,
              the capture group values will be cleared.

       Obtaining results from databases
              It  is  useful to query a database for some information, and to use the result in a
              condition.  The following syntax will call a module, pass it the given string,  and
              replace the string expansion with the resulting string returned from the module.

                   %{module: string ...}

              The  syntax of the string is module-specific.  Please read the module documentation
              for additional details.

       Conditional Syntax
              Conditional syntax similar to that used in Unix shells may also be used.

              %{%{Foo}:-bar}
                     If %{Foo} has a value, returns that value.
                     Otherwise, returns literal string "bar".

              %{%{Foo}:-%{Bar}}
                     If %{Foo} has a value, returns that value.
                     Otherwise, returns the expansion of %{Bar}.

                     These conditional expansions can be nested to almost any depth, such as with
                     %{%{One}:-%{%{Two}:-%{Three}}}

       String lengths and arrays
              Similar to a Unix shell, there are ways to reference string lengths, and the second
              or more instance  of  an  attribute  in  a  list.   If  you  need  more  than  this
              functionality, we suggest using a real language.

              %{strlen:string}
                     The  number of characters in "string".  If "string" does not exist, then the
                     length also does not exist, instead of being zero.

                     The "string" is expanded before the length is taken.

              %{integer:Attribute-Name}
                     The integer value of the Attribute-Name, instead of the enumerated name.

                     e.g. If a request contains "Service-Type =  Login-User",  the  expansion  of
                     %{integer:Service-Type} will yield "1".

              %{hex:Attribute-Name}
                     The hex value of the Attribute-Name, as a series of hex digits.

                     e.g. If a request contains "Framed-IP-Address = 127.0.0.1", the expansion of
                     %{hex:Framed-IP-Address} will yield "0x7f000001".

              %{Attribute-Name[#]}
                     The number of instances of Attribute-Name.

                     e.g. If a request contains "User-Name  =  bob",  the  expansion  of  %{User-
                     Name[#]} will yield "1".

              %{Attribute-Name[*]}
                     All  values  of  Attribute-Name,  concatenated  together  with  ','  as  the
                     separator.

              %{List-Name:[#]}
                     The number of attributes in the named list.

              %{List-Name:[*]}
                     All values of attributes in the named-list, concatenated together  with  ','
                     as  the  separator.  Use  the %{pairs:} xlat to get a list of attributes and
                     values.

                     e.g. If a response contains "Reply-Message = 'Hello', Reply-Message =  'bob'
                     the expansion of "%{reply:Reply-Message[*]} will yield "Hello\nbob"

ATTRIBUTE ASSIGNMENTS

       The  attribute lists described above may be edited by listing one or more attributes in an
       "update" section.  Once the attributes have  been  defined,  they  may  be  referenced  as
       described above in the VARIABLES section.

       The  following syntax defines attributes in an "update" section.  Each attribute and value
       has to be all on one line in the configuration file.  There is no need for commas or semi-
       colons after the value.

            Attribute-Reference = value

       Attribute Reference
              The  Attribute-Reference  must  be a reference (see above), using a name previously
              defined in a dictionary.  If an undefined name is used, the server will  return  an
              error, and will not start.

       Operators
              The operator used to assign the value of the attribute may be one of the following,
              with the given meaning.

              =      Add the attribute to the list, if and only if an attribute of the same  name
                     is not already present in that list.

              :=     Add the attribute to the list.  If any attribute of the same name is already
                     present in that list, its value is replaced with the value  of  the  current
                     attribute.

              +=     Add  the  attribute  to the tail of the list, even if attributes of the same
                     name are already present in the list.  When  the  right  hand  side  of  the
                     expression  resolves to multiple values, it means add all values to the tail
                     of the list.

       Enforcement and Filtering Operators
              The following operators may also be used in addition  to  the  ones  listed  above.
              Their function is to perform enforcement or filtering on attributes in a list.

              -=     Remove  all  matching attributes from the list.  Both the attribute name and
                     value have to match in order for the attribute to be removed from the list.

              ==     Keep all matching attributes.  Both the attribute name  and  value  have  to
                     match in order for the attribute to remain in the list.

                     Note  that  this  operator  is  very  different than the '=' operator listed
                     above!

              !=     Keep all attributes with matching name, and value not  equal  to  the  given
                     one.

              <      Keep  all  attributes  having  values  less  than the value given here.  Any
                     larger value is replaced by the value given here.  If no  attribute  exists,
                     it is added with the value given here, as with "+=".

              <=     Keep  all  attributes  having values less than, or equal to, the value given
                     here.  Any larger value  is  replaced  by  the  value  given  here.   If  no
                     attribute exists, it is added with the value given here, as with "+=".

              >      Keep  all  attributes  having values greater than the value given here.  Any
                     smaller value is replaced by the value given here.  If no attribute  exists,
                     it is added with the value given here, as with "+=".

              >=     Keep all attributes having values greater than, or equal to, the value given
                     here.  Any smaller value is  replaced  by  the  value  given  here.   If  no
                     attribute exists, it is added with the value given here, as with "+=".

              !*     Delete all occurrences of the named attribute, no matter what the value.

              =~     Keep  all attributes having values which match the given regular expression.
                     If no attribute matches, nothing else is done.

              !~     Keep all attributes having values which fail  to  match  the  given  regular
                     expression.  If no attribute matches, nothing else is done.

       Values
              The value can be an attribute reference, or an attribute-specific string.

              When  the value is an an attribute reference, it must take the form of "&Attribute-
              Name".  The leading "&" signifies that the value is a reference.   The  "Attribute-
              Name"  is  an  attribute name, such as "User-Name" or "request:User-Name".  When an
              attribute reference is used, both attributes must have the  same  data  type.   For
              example,  "User-Name := &NAS-Port" is invalid, because "User-Name" is a string, and
              "NAS-Port" is an integer.

              We recommend using the form "Attribute-1 = &Attribute-2" for  updates,  instead  of
              "Attribute-1  =  "%{Attribute-2}".  The first version will copy the attribute data,
              no matter what its form.  The second  version  will  print  the  Attribute-2  to  a
              string, and then parse it to create the value for Attribute-1.  This second version
              is slower and more fragile than the first one.

              When the value is an attribute-specific string, it can be  a  string,  integer,  IP
              address,  etc.   The  value  may  be  expanded as described above in the DATA TYPES
              section, above.  For example, specifying "Framed-IP-Address = 127.0.0.1" will cause
              the  "Framed-IP-Address"  attribute  to  be  set  to  the  IP  address "127.0.0.1".
              However, using "Framed-IP-Address := module to be run with  a  string  "127.0.0.1".
              The  output  of  the "echo" module will then be parsed as an IP address, and placed
              into the Framed-IP-Address attribute.

              This flexibility means that you can assign an IP address by specifying it directly,
              or  by  having the address returned from a database query, or by having the address
              returned as the output of a program that is executed.

              When string values are finally assigned to an attribute, they can  have  a  maximum
              length  of 253 characters.  This limit is due in part to both protocol and internal
              server requirements.  That is, the strings in the language  can  be  nearly  8k  in
              length,  say for a long SQL query.  However, the output of that SQL query should be
              no more than 253 characters in length.

OTHER KEYWORDS

       Other keywords in the language are taken from the names of modules loaded by  the  server.
       These keywords are dependent on both the modules, and the local configuration.

       Some use keywords that are defined in the default configuration file are:

       fail   Cause the request to be treated as if a database failure had occurred.

       noop   Do  nothing.   This  also  serves  as  an  instruction to the configurable failover
              tracking that nothing was done in the current section.

       ok     Instructs the server that the request was processed properly.  This keyword can  be
              used  to over-ride earlier failures, if the local administrator determines that the
              faiures are not catastrophic.

       reject Causes the request to be immediately rejected

MODULE RETURN CODES

       When a module is called, it returns one of the  following  codes  to  "unlang",  with  the
       following meaning.

            notfound        information was not found
            noop            the module did nothing
            ok              the module succeeded
            updated         the module updated the request
            fail            the module failed
            reject          the module rejected the request
            userlock        the user was locked out
            invalid         the configuration was invalid
            handled         the module has handled the request itself

       These  return codes can be tested for in a condition, as described above in the CONDITIONS
       section.

       See also the  file  doc/configurable_failover  for  additional  methods  of  trapping  and
       modifying module return codes.

FILES

       /etc/freeradius/3.0/radiusd.conf

SEE ALSO

       radiusd.conf(5), dictionary(5)

AUTHOR

       Alan DeKok <aland@deployingradius.com>

                                         06 December 2017                               unlang(5)