Expressions
Expressions can be used inside of dynamic expansions, or inside of conditions, or on the right side of assignment editing.
%{1 + 2}
(&NAS-Port == 1 + 2)
&NAS-Port = 1 + 2
Operators in an Expression
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 in Assignments
Conditions in assignments 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}"
The old `%{expr:…}
syntax will return an error in v4. That functiuonality is no longer supported.
Data Types
The new expression parser accepts significantly more data types than the old expresisons. The expression in the previous versions assumed that all inputs were signed 64-bit integers. Any attempt to use other data types resulted in an error.
In new expressions, 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"
!.
Other data types will generally yield results which make sense. For example:
-
adding an integer to an
ipv4prefix
type will result in anipv4addr
data type, -
&
and|
will work onstring
andoctets
data types, -
Using
&
withipv4addr
data types anuint32
will result in anipv4prefix
data type, -
ipv4addr
types can be subtracted, and will return a number which is the number of IPs between the two values, -
two
date
values can be subtracted, and will return atime_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-Name
if 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 as a particular type. This is where casting is used.
Casts
Type casting is supported via the (type)
syntax. The old syntax of <type>
is not accepted.
&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
.