oracular (5) unlang.5.gz

Provided by: freeradius-common_3.2.5+dfsg-3ubuntu0.1_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 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 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 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 maintained 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 comparing 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  ATTRIBUTE
              REFERENCES,  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  parentheses  in the regular expression will define
              variables containing the matching text, as described below in the ATTRIBUTE REFERENCES 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
       ATTRIBUTE REFERENCES 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.

              ^=     Add the attribute to the head 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 prepend all values to the head 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 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  failures  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>

                                                16 February 2021                                       unlang(5)