Unlang Policy Language
The server supports a simple processing language called "Unlang",
which is short for "un-language". The original intention of using an
"un-language" was to avoid creating yet another programming language.
Instead, the unlang
syntax allows for simple if / then / else
checks, and attribute editing. It does not support recursion,
subroutines, or more complex flow controls.
Where more complicated functionality is required, we recommend using
the lua
, perl
or python
modules. Those modules allow the insertion of
full-featured scripts at any point in the packet processing.
The documentation is this directory is reference
documentation. That is, it describes the syntax of unlang keywords,
using minimal examples. The reference documentation does not,
however, describe when to use the keywords, or how to create
policies. Please see the howto directory for
more in-depth "how to" guides.
|
The documentation is organized so that each item is on its own page.
The page beings with a description of the item, followed by some text
explaining what the item does. The page concludes with one or more
examples of using the item in unlang
policies.
The unlang
processing can be split into some high-level concepts.
Keywords
Keywords, which are the basic statements of the language, e.g., load-balance, if, else, etc.
load-balance {
sql1
sql2
sql3
}
Interpreter
The Interpreter processes an input "request" packet, by running policies which contain Keywords. The result of the interpretation is usually an output "reply" packet.
While the interpreter allows some fairly complex policies to be made, it is not a general purpose programming language. The purpose of the language is to receive packets, process their contents, and send replies. A secondary goal is to do that as quickly as possible.
Conditional Expressions
Conditional expressions, which are used to check if conditions evaluate to true or false. Conditional expressions can be used to control the flow of processing.
if ((&User-Name == "bob") && (&Calling-Station-Id == "00:01:03:04:05")) {
...
}
Editing Attributes and lists.
Attribute editing statements are used to edit attributes and lists of attributes. The old-style update sections are deprecated, and no longer supported.
Local variables can be defined, so that the
local dictionary
file no longer needs to be modified.
Most request packets will result in reply packets that contain additional information for the requester. Attribute editing allows policies to add attributes to requests, replies, or to other places.
&reply.Session-Timeout := 3600
&reply.Framed-IP-Address := 192.0.2.4
Dynamic Expansions
Dynamic expansion Using %{…}
to perform dynamic
expansions. (also known as xlat)
Dynamic expansions are usually performed in order to get additional information which is not immediately available to the policy. This information can be taken from almost any source, including other attributes, databases, and scripts.
&reply.Framed-IP-Address := %sql("SELECT static_ip from table WHERE user = '%{User-Name}'")
Data Types
Each attribute used by the server has an associated
data type. The unlang
interpreter enforces
restrictions on assignments, so that only valid data types can be
assigned to an attribute. Invalid assignments result in an
error.
&reply += {
&Framed-IP-Address = 192.0.2.4
&Session-Timeout = 5
&Reply-Message = "hello"
}
Design Goals of Unlang
The goal of unlang
is to allow simple policies to be written with
minimal effort. Conditional checks can be performed by the policies,
which can then update the request or response attributes based on the
results of those checks. unlang
can only be used in a processing
section, it cannot be used anywhere else, including in configuration
sections for a client or a module. The reason for this limitation is
that the language is intended to perform specific actions on requests
and responses. The client and module sections contain definitions for
a client or module; they do not define how a request is processed.
unlang
uses a syntax similar to the configuration files. The
policies can contain comments, whitespace, sections, etc.
Where unlang
differs from the basic configuration file format is in
its complexity and operation. The normal configuration files are
declarative and they are static. That is, they declare variables
and values for those variables. Those values do not change when the
server is running.
In contrast, unlang
performs run-time processing of requests.
Conditional statements such as if are evaluated
for every packet that is received. Attribute
editing statements such as can be used to edit
attribute contents or lists of attributes.
# First, the keyword 'if'
# followed by condition which checks that the User-Name
# attribute has value "bob"
if (&User-Name == "bob") {
# followed by instructions to add the Reply-Message
# attribute to the "reply" list, with contents
# "Hello, bob"
&reply.Reply-Message := "Hello, bob"
}