Expressions
Expressions can be used inside of dynamic expansions, or inside of conditions.
The following operators are supported (in order of precedence).
| Operator | Description |
|---|---|
& |
binary AND |
| |
binary OR |
<< |
left shift |
>> |
right shift |
+ |
addition |
- |
subtraction |
* |
multiplication |
/ |
division |
% |
remainder |
^ |
xor |
(…) |
sub-expression |
The following unary operators are also supported:
| Operator | Description |
|---|---|
- |
unary minus |
~ |
unary complement |
! |
unary not |
Operator precedence follows the normal rules. Division by zero means that the entire expression is invalid.
See the edit documentation for a list of attribute editing operators.
Conditions
Conditions in expressions are also supported. For example:
&NAS-Port = 5 + (&User-Name == "bob")
This expression will return 6 if the users name is bob, and 5 otherwise.
Similarly, expressions are also supported in conditions. There is no
need to use %{expr:…} in conditions, as was needed in earlier
versions of the server. You can just use math in-place.
You do not even need to use %{expr:…} in double-quoted strings.
You can just put math in-place, as with the following example:
&Filter-Id = "Adding %{NAS-Port} + 4 = %{&NAS-Port + 4}"
Data Types
The new expression parser accepts significantly more data types than
the old rlm_expr module. The rlm_expr module assumed that all
inputs were signed 64-bit integers. Any attempt to use other data
types resulted in an error.
For example, the ` operator can be applied to `string` and `octet`
data types. (And incidentally, `-` is the inverse of `!)
&Reply-Message := "foo" + "bar"
Will result in &Reply-Message == "foobar".
The suffix can then be "subtracted" off, with:
&Reply-Message -= "bar"
Will result in &Reply-Message == "foo" !.
Note that the -= operator behaves differently from earlier versions
of the server! Since the server no longer needs update sections, we
could re-purpose the operator.
Other data types will generally yield results which make sense. For example:
-
adding an integer to an
ipv4prefixtype will result in anipv4addrdata type, -
&and|will work onstringandoctetsdata types, -
Using
&withipv4addrdata types anuint32will result in anipv4prefixdata type, -
`ipv4addr`s can be subtracted, and will return a number,
-
date`s can be subtracted, and will return a `time_delta, -
operations on integers are upgraded to the next largest integer size when necessary,
-
the logical operators
&&and||return the value which caused them to succeed, e.g.&Foo := (&User-Password || "help")will return the contents of&User-Nameif it exists, otherwise it will return the stringhelp.
In most cases, the data types are derived from the attribute dictionaries. However, it is sometimes necessary to force the fields (or output) of an expression to be parsed in a particular manner.
Casts
Type casting is supported via the (type)
syntax. The old-style syntax of <type> is accepted, but is
deprecated.
&NAS-Port-Id = (uint32) "%sql("SELECT...") + 4
Errors
Mathematical operations which cause overflow, underflow, or division
by zero will return a null result. This result will propagate
through any calculations, so that an expression which relies on null
will generally also return null.
A null result can be removed via the || operator. For example:
&NAS-Port-Id = (5 - "foo") || 6
Will return 6, as the left side expression of the || operator evaluates to null.