----
The following example will take an input string `"192.168.0.1"`, split
-it on the `'.'` character, and then assign it to the `Tmp-Integer-0`
-attribute. The result will be four copies of the `Tmp-Integer-0`
-attribute, which each carry one octet of the IP address.
+it on the `'.'` character, and then assign it to another attribute.
+The result will be four copies of the `Tmp-Integer-0` attribute, which
+each carry one octet of the IP address.
.Example Creating multiple Attributes
----
.Example of casting to raw 'octets'
[source,unlang]
----
-"User-Name is %{Tmp-Octets-0}"
-"User-Name is %{(string) Tmp-Octets-0}"
+"Value is %{Class}"
+"Value is %{(string) Class}"
----
-if the `Tmp-Octets-0` attribute has value `0x666f6f` (`foo`)
+if the `Class` attribute has value `0x666f6f` (`foo`)
-In the first expansion, the resulting output is `User-Name is
+In the first expansion, the resulting output is `Value is
0x666f6f`. In the second expansion, the resulting output is
-`User-name is foo`.
+`Value is foo`.
Note that placing raw `octets` data into a string may allow for binary
data to be inserted into what should be a printable string. Any uses
====
[source,unlang]
----
-if (User-Name =~ /^@%{Tmp-String-0}$/) {
+string regex
+
+regex = %sql("SELECT realm ....")
+
+if (User-Name =~ /^@%{regex}$/) {
...
}
----
====
+Note that the string will be deemed to be "unsafe", so characters
+which are special for a regular expression will be escaped. If the
+string is taken from a trusted source, it can be marked as safe via
+the `%regex.safe()` function.
+
To ensure optimal performance you should limit the number of patterns
containing xref:xlat/index.adoc[dynamic expansions], and if using PCRE, combine
multiple expressions operating on the same subject into a single expression
using the PCRE alternation '|' operator.
-.Using multiple dynamic expansions and the PCRE alternation operator
-====
-[source,unlang]
-----
-if (User-Name =~ /^@(%{Tmp-String-0}|%{Tmp-String-1})$/) {
- ...
-}
-----
-====
-
-
// Licenced under CC-by-NC 4.0.
// Copyright (C) 2021 Network RADIUS SAS.
// Copyright (C) 2019 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
current interpreter, and may be changed in the future.
.Example of Looping over children of a structural type.
+
+In this examply, we assume that an attribute `TLV-Thing` has a child
+called `Foo`.
+
[source,unlang]
----
-foreach thing (Tmp-TLV-0[*]) {
- out += thing.c
+foreach thing (TLV-Thing[*]) {
+ out += thing.Foo
out += " "
}
----
-This example can read the child attribute `c`, but cannot modify it.
+This example can read the child attribute `Foo`, but cannot modify it.
// Copyright (C) 2024 Network RADIUS SAS. Licenced under CC-by-NC 4.0.
----
In v3 the default dictionaries included a series of `Tmp-*`
-attributes. These are no longer necessary, and should not be used.
+attributes. These attributes are no longer necessary, and should not
+be used. Local variables should be used instead.
.Local variables exist on only if they have been created
[source,unlang]
[source,unlang]
----
-control.Tmp-String-0 := "Caipirinha"
-reply.Reply-Message := "The base64 of %{control.Tmp-String-0} is %base64.encode(%{control.Tmp-String-0})"
+string test
+
+test := "Caipirinha"
+reply.Reply-Message := "The base64 of %{test} is %base64.encode(test)"
----
.Output
[source,unlang]
----
-control.Tmp-String-0 := "Q2FpcGlyaW5oYQ=="
-reply.Reply-Message := "The base64.decode of %{control.Tmp-String-0} is %base64.decode(%{control.Tmp-String-0})"
+string test
+
+test := "Q2FpcGlyaW5oYQ=="
+reply.Reply-Message := "The base64.decode of %{test} is %base64.decode(test)"
----
.Output
[source,unlang]
----
-control.Tmp-String-0 := "10"
-reply.Reply-Message := "The %{control.Tmp-String-0} in binary is %bin(%{control.Tmp-String-0})"
+string test
+
+test := "10"
+reply.Reply-Message := "The %{test} in binary is %bin(test)"
----
.Output
[source,unlang]
----
-control.Tmp-String-0 := "12345"
-reply.Reply-Message := "The value of %{control.Tmp-String-0} in hex is %hex(%{control.Tmp-String-0})"
+string test
+
+test := "12345"
+reply.Reply-Message := "The value of %{test} in hex is %hex(test)"
----
.Output
[source,unlang]
----
-control.Tmp-String-0 := "http://example.org/"
+string test
+
+test := "http://example.org/"
reply += {
- Reply-Message = "The urlquote of %{control.Tmp-String-0} is %url.quote(%{control.Tmp-String-0})"
+ Reply-Message = "The urlquote of %{test} is %url.quote(test)"
}
----
[source,unlang]
----
-control.Tmp-String-0 := "http%%3A%%2F%%2Fexample.org%%2F" # Attention for the double %.
+string test
+
+test := "http%%3A%%2F%%2Fexample.org%%2F" # Attention for the double %.
reply += {
- Reply-Message = "The urlunquote of %{control.Tmp-String-0} is %url.unquote(%{control.Tmp-String-0})"
+ Reply-Message = "The urlunquote of %{test} is %url.unquote(test)"
}
----
= Dictionary Lookups
-The following functions perform lookups based on dictionary names and numbers.
-
-The functions are defined in the xref:raddb/mods-available/dict.adoc[dict] module. It must be listed in
-the `mods-enabled/` directory in order for the expansions to work.
-
-== %str.concat(<ref:[idx]>, <delim>)
-
-Used to join two or more attributes, separated by an optional delimiter.
-
-.Return: _string_
-
-In most cases, `%str.concat(...)` is only useful inside of a dynamically
-expanded string. If you need to concatenate strings together in a policy, just use `+`.
-
-.Example
-
-[source,unlang]
-----
-control += {
- Tmp-String-0 = "aaa"
- Tmp-String-0 = "bb"
- Tmp-String-0 = "c"
-}
-
-reply += {
- Reply-Message = "%str.concat(%{control.Tmp-String-0[*]}, ', ')"
- Reply-Message = "%str.concat(%{control.Tmp-String-0[*]}, ',')"
-}
-----
-
-.Output
-
-```
-aaa, bb, c
-aaa,bb,c
-```
-
-.Using "+"
-[source,unlang]
-----
-string foo
-
-foo += { "a", "c", "c", "d" } # abcd
-
-foo += control.Tmp-String-0[*]
-----
-
-== %str.split(<ref>, <delim>)
-
-Split an string into multiple new strings based on a delimiter.
-
-This expansion is the opposite of `%str.concat( ... )`.
-
-.Return: _the number exploded list of strings_.
-
-.Example
-
-[source,unlang]
-----
-control.Tmp-String-0 := "bob.toba@domain.com"
-
-control.Tmp-String-1 := "%str.split(control.Tmp-String-0, '@')"
-
-reply.Reply-Message := "Welcome %{control.Tmp-String-1[0]}"
-----
-
-.Output
-
-```
-Welcome bob.toba
-```
-
-== %str.lpad(<string>, <val>, <char>)
-
-Left-pad a string.
-
-.Return: _string_
-
-.Example
-
-[source,unlang]
-----
-control.Tmp-String-0 := "123"
-
-reply.Reply-Message := "Maximum should be %str.lpad(%{control.Tmp-String-0}, 11, '0')"
-----
-
-.Output
-
-```
-Maximum should be 00000000123
-```
-
-== %str.rpad(<string>, <val>, <char>)
-
-Right-pad a string.
-
-.Return: _string_
-
-.Example
-
-[source,unlang]
-----
-control.Tmp-String-0 := "123"
-
-reply.Reply-Message := "Maximum should be %str.rpad(%{control.Tmp-String-0}, 11, '0')"
-----
-
-.Output
-
-```
-Maximum should be 12300000000
-```
-
-== %str.lower( ... )
-
-Dynamically expands the string and returns the lowercase version of
-it. This definition is only available in version 2.1.10 and later.
-
-.Return: _string_
-
-.Example
-
-[source,unlang]
-----
-control.Tmp-String-0 := "CAIPIRINHA"
-reply.Reply-Message := "tolower of %{control.Tmp-String-0} is %str.lower(%{control.Tmp-String-0})"
-----
-
-.Output
-
-```
-tolower of CAIPIRINHA is caipirinha
-```
-
-== %str.upper( ... )
-
-Dynamically expands the string and returns the uppercase version of
-it. This definition is only available in version 2.1.10 and later.
-
-.Return: _string_
-
-.Example
-
-[source,unlang]
-----
-control.Tmp-String-0 := "caipirinha"
-reply.Reply-Message := "toupper of %{control.Tmp-String-0} is " + %str.upper(%{control.Tmp-String-0})
-----
-
-.Output
-
-```
-toupper of caipirinha is CAIPIRINHA
-```
-
+The dictionary functions are defined in the
+xref:raddb/mods-available/dict.adoc[dict] module. It must be listed
+in the `mods-enabled/` directory in order for the expansions to work.
// Copyright (C) 2023 Network RADIUS SAS. Licenced under CC-by-NC 4.0.
// This documentation was developed by Network RADIUS SAS.
[source,unlang]
----
-control.Tmp-String-0 := "mykey"
-control.Tmp-String-1 := "Caipirinha"
-reply.control.Tmp-Octets-0 := %hmac.md5(control.Tmp-String-0, control.Tmp-String-1)
+string test1
+string test2
+octets output
+
+test1 := "mykey"
+test2 := "Caipirinha"
+output := %hmac.md5(test1, test2)
reply += {
- Reply-Message = "The HMAC-MD5 of %{control.Tmp-String-1} in octets is %{control.Tmp-Octets-0}"
- Reply-Message = "The HMAC-MD5 of %{control.Tmp-String-1} in hex is %hex(control.Tmp-Octets-0)"
+ Reply-Message = "The HMAC-MD5 of %{test1}%{test2} in octets is %{output}"
+ Reply-Message = "The HMAC-MD5 of %{test1}%{test2} in hex is %hex(output)"
}
----
[source,unlang]
----
-control.Tmp-String-0 := "mykey"
-control.Tmp-String-1 := "Caipirinha"
-control.Tmp-Octets-0 := %hmac.sha1(control.Tmp-String-0, control.Tmp-String-1)
+string test1
+string test2
+octets output
+
+test1 := "mykey"
+test2 := "Caipirinha"
+output := %hmac.sha1(test1, test2)
reply += {
- Reply-Message = "The HMAC-SHA1 of %{control.Tmp-String-1} in octets is %{control.Tmp-Octets-0}"
- Reply-Message = "The HMAC-SHA1 of %{control.Tmp-String-1} in hex is %hex(control.Tmp-Octets-0}"
+ Reply-Message = "The HMAC-SHA1 of %{test1}%{test2} in octets is %{output}"
+ Reply-Message = "The HMAC-SHA1 of %{test1}%{test2} in hex is %hex(output)"
}
----
====
[source,unlang]
----
-Tmp-String-0 := "Caipirinha"
+string test := "Caipirinha"
Framed-IP-Address := 192.0.2.1
reply += {
- Reply-Message = "The length of %{control.Tmp-String-0} is %length(control.Tmp-String-0)"
+ Reply-Message = "The length of %{test} is %length(test)"
Reply-Message = "The length of %{control.Framed-IP-Address} is %length(control.Framed-IP-Address)"
}
----
[source,unlang]
----
control.Tmp-String-0 := { "This is a string", "This is another one" }
+
reply.Reply-Message := "Serialize output: %pairs.print(control.[*])"
----
[source,unlang]
----
-control += {
- Tmp-String-0 = "aaa"
- Tmp-String-0 = "bb"
- Tmp-String-0 = "c"
-}
+control.Tmp-String-0 := { "aaa", "bb", "c" }
reply += {
- Reply-Message = "%str.concat(%{control.Tmp-String-0[*]}, ', ')"
- Reply-Message = "%str.concat(%{control.Tmp-String-0[*]}, ',')"
+ Reply-Message = %str.concat(%{control.Tmp-String-0[*]}, ', ')
+ Reply-Message = %str.concat(%{control.Tmp-String-0[*]}, ',')
}
----
aaa,bb,c
```
-.Using "+"
-[source,unlang]
-----
-string foo
-
-foo += { "a", "c", "c", "d" } # abcd
-
-foo += control.Tmp-String-0[*]
-----
-
// Copyright (C) 2025 Network RADIUS SAS. Licenced under CC-by-NC 4.0.
// This documentation was developed by Network RADIUS SAS.
[source,unlang]
----
-control.Tmp-String-0 := "CAIPIRINHA"
-reply.Reply-Message := "lowercase of %{control.Tmp-String-0} is %str.lower(control.Tmp-String-0)"
+User-Name := "BOB"
+
+reply.Reply-Message := "lowercase of %{User-Name} is %str.lower(User-Name)"
----
.Output
```
-lowercase of CAIPIRINHA is caipirinha
+lowercase of BOB is bob
```
// Copyright (C) 2025 Network RADIUS SAS. Licenced under CC-by-NC 4.0.
[source,unlang]
----
-control.Tmp-String-0 := "123"
+string test
-reply.Reply-Message := "Maximum should be %str.lpad(%{control.Tmp-String-0}, 11, '0')"
+test := "123"
+
+reply.Reply-Message := "Maximum should be %str.lpad(test, 11, '0')"
----
.Output
[source,unlang]
----
-control.Tmp-String-0 := "123"
+string test
-reply.Reply-Message := "Maximum should be %str.rpad(%{control.Tmp-String-0}, 11, '0')"
+test := "123"
+
+reply.Reply-Message := "Maximum should be %str.rpad(test, 11, '0')"
----
.Output
[source,unlang]
----
-control.Tmp-String-0 := "bob.toba@domain.com"
+User-Name := "bob.toba@domain.com"
-control.Tmp-String-1 := %str.split(control.Tmp-String-0, '@')
+control.Tmp-String-1 := %str.split(User-Name, '@')
reply.Reply-Message := "Welcome %{control.Tmp-String-1[0]}"
----
[source,unlang]
----
-control.Tmp-String-0 := "caipirinha"
-reply.Reply-Message := "uppercase of %{control.Tmp-String-0} is " + %str.upper(control.Tmp-String-0)
+User-Name := "bob"
+reply.Reply-Message := "uppercase of %{User-Name} is " + %str.upper(User-Name)
----
.Output
```
-uppercase of caipirinha is CAIPIRINHA
+uppercase of bob is BOB
```
// Copyright (C) 2025 Network RADIUS SAS. Licenced under CC-by-NC 4.0.