}
----
-== Update Statements
+== Editing Attribures and lists.
-xref:unlang/update.adoc[update] statements are used to edit attributes and
-lists of attributes.
+xref:unlang/edit.adoc[attribute editing] statements are used to edit
+attributes and lists of attributes. The old-style
+xref:unlang/update.adoc[update] sections are deprecated, and no longer
+supported.
Most request packets will result in reply packets that contain
-additional information for the requestor. The `update` section allows
+additional information for the requestor. Attribute editing allows
policies to add attributes to requests, replies, or to other places.
.Example
[source,unlang]
----
-update reply {
- &Session-Timeout := 3600
- &Framed-IP-Address := 192.0.2.4
-}
+&reply.Session-Timeout := 3600
+&reply.Framed-IP-Address := 192.0.2.4
----
== Dynamic Expansions
.Example
[source,unlang]
----
-update reply {
- &Framed-IP-Address := "%{sql:SELECT static_ip from table WHERE user = '%{User-Name}'}"
-}
+&reply.Framed-IP-Address := "%{sql:SELECT static_ip from table WHERE user = '%{User-Name}'}"
----
== Data Types
.Example
[source,unlang]
----
-update reply {
- &Framed-IP-Address := 192.0.2.4
- &Session-Timeout := 5
- &Reply-Message := "hello"
+&reply += {
+ &Framed-IP-Address = 192.0.2.4
+ &Session-Timeout = 5
+ &Reply-Message = "hello"
}
----
server is running.
In contrast, `unlang` performs run-time processing of requests.
-Conditional statements such as xref:unlang/if.adoc[if] are evaluated for every
-packet that is received. Attribute editing statements such as
-xref:unlang/update.adoc[update] can be used to edit attribute contents or lists
-of attributes.
+Conditional statements such as xref:unlang/if.adoc[if] are evaluated
+for every packet that is received. Attribute
+xref:unlang/edit.adoc[editing] statements such as can be used to edit
+attribute contents or lists of attributes.
.Example
[source,unlang]
# attribute has value "bob"
if (&User-Name == "bob") {
- # keyword "update"
-
# followed by instructions to add the Reply-Message
# attribute to the "reply" list, with contents
# "Hello, bob"
- update reply {
- Reply-Message := "Hello, bob"
- }
+ &reply.Reply-Message := "Hello, bob"
}
----
= The update Statement
-.Syntax
-[source,unlang]
-----
-update [ <list> ] {
- <server-attribute> <op> <value>
- ...
-}
-----
+The `update` statement is deprecated. It may work, but it will be
+removed in a future release. The `update` statement does not support
+the data types of `group` and `struct`.
+
+All new configuration should use the new xref:unlang/edit.adoc[edit]
+syntax. It is more flexible and more powerful than `update` sections.
-The `update` statement adds attributes to, or edits the attributes in,
-the named _<list>_.
+This page exists only document how the old-style `update` sections can
+be converted to the new syntax.
-The `update` statement consists of the following syntax elements:
+The most important conceptual change is that the
+xref:unlang/edit.adoc[edit] syntax separates list assignments from
+value assignments. Where the `update` sections always modified a list
+by adding or deleting attributes, the new syntax allows for list
+updates _or_ updates to an attributes value. Be careful not to get
+the two uses mixed up, otherwise the result will not be what you
+expect.
-_<list>_: The attribute list which will be updated. The list is
-usually `request`, `reply`, or `control`.
-+
-If the _<list>_ qualifier is omitted, then each entry inside of the
-`update` section *must* be prefixed with a list name. For example,
-`&request.User-Name ...`
+The second conceptual change is that attribute creation is separate
+from applying attributes to a list. For example, the `+=` operator
+used to both create an attribute, and then append that attribute to a
+list. The new edit syntax separates attribute creation from list
+modification.
-_<server-attribute>_:: The server attribute which is assigned the
-_<value>_.
+== Conversions
-_<op>_:: The operator such as `=`, `:=`, etc.
+There are a larger number of operators using for both the old `update`
+section and the xref:unlang/edit.adoc[edit] syntax. We explain in
+detail how the configuration can be converted from one form to another.
-_<value>_:: The value which is assigned to the attribute. If the field
-is a double-quoted string, it undergoes xref:xlat/index.adoc[string
-expansion], and the resulting value is assigned to the attribute.
+=== Appending to a list: +=
-The update process is atomic, in that either all of the attributes are
-modified, or none of them are modified. If the `update` fails for any
-reason, then all of the results are discarded, and the `update` does
-not affect any server attributes.
+The following example creates four attributes, and appends them to the
+`request` list.
-.Example
[source,unlang]
----
-update reply {
- &Reply-Message := "Hello!"
- &Framed-IP-Address := 192.0.2.4
+update request {
+ &User-Name += "foo"
+ &Filter-Id += "bar"
+ &NAS-IP-Address += 127.0.0.1
+ &NAS-Port += 5
}
----
-== Lists
+This example should be converted to the following syntax:
-The _<list>_ field sets the attribute list that will be updated. If
-the _<list>_ qualifier is omitted, then each entry inside of the
-`update` section *must* be prefixed with a list name. For example,
-`&request.User-Name ...`
+[source,unlang]
+----
+&request += {
+ &User-Name = "foo"
+ &Filter-Id = "bar"
+ &NAS-IP-Address = 127.0.0.1
+ &NAS-Por = 5
+}
+----
-Please see the xref:unlang/list.adoc[list] page for valid list names.
+This configuration can be interpreted as "edit the `&request` list,
+but appending (`+=`) another list to it. The list being appended
+contains four attributes".
-== Server Attributes
+Note that the operators on the right-hand side list are all `=`. The
+`=` operator is used here because we are simply _creating_ the
+right-hand side list, not _modifying_ it.
-The _<server-attribute>_ field is an attribute name, such as
-`&Reply-Message`. The attribute name may also be prefixed with a
-_<list>_ qualifier, which overrides the _<list>_ given at the start
-of the `update` section.
+=== Over-writing attributes in a list: :=
-NOTE: In version 3, the leading `&` was optional. In version 4, the
-leading `&` is required.
+The following example over-writes the values for two attributes in the
+`request` list.
-== Editing Operators
+[source,unlang]
+----
+update request {
+ &User-Name := "foo"
+ &Filter-Id := "bar"
+}
+----
+
+The simplest conversion here is to keep the `:=` operator, and to just
+assign the attributes in place, with a list qualifier.
+
+[source,unlang]
+----
+&request.User-Name := "foo"
+&request.Filter-Id := "bar"
+----
-The `<op>` field is used to define how the attribute is processed.
-Different operators allow attributes to be added, deleted, or
-replaced, as defined below.
+=== Conditionally Over-writing attributes in a list: =
-.Editing Operators
-[options="header"]
-[cols="10%,90%"]
-|=====
-| Operator | Description
-| = | 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.
-| ^= | Add the attribute to the head of the list, even if attributes
-of the same name are already present in the list.
-| -= | Remove all attributes from the list that match _<value>_.
-| !* | Delete all occurances of the attribute, no matter what the value.
-|=====
+The following example conditionally over-writes the values for two attributes in the
+`request` list.
-.Example
[source,unlang]
----
-update reply {
- &Session-timeout := 86400
+update request {
+ &User-Name = "foo"
+ &Filter-Id = "bar"
}
----
-.Example
+The simplest conversion here is to keep the `=` operator, and to just
+assign the attributes in place, with a list qualifier.
+
[source,unlang]
----
-update reply {
- &Reply-Message += "Rejected: Also, realm does not end with ac.uk"
-}
+&request.User-Name = "foo"
+&request.Filter-Id = "bar"
----
-== Values
+=== Removing Attributes from a list: !*
-The _<value>_ field is the value which is assigned to the
-_<server-attribute>_. The interpretation of the _<value>_ field
-depends on the data type of the contents. For example, if the string
-`"192.0.2.1"` is assigned to an attribute of the `string` data type,
-then the result is an ASCII string containing that value. However, if
-the same string is assigned to an attribute of the `ipaddr` data type,
-then the result is a 32-bit IPv4 address, with binary value `0xc0000201`.
+The following example removes all `&User-Name` attributes from the `request` list.
-.Example
[source,unlang]
----
-update reply {
- &Session-Timeout <= 3600
+update request {
+ &User-Name !* ANY
}
----
+The conversion is to use the `-=` operator:
+
+[source,unlang]
+----
+&request -= &User-Name
+----
+
+== More Complex Conversions
+
+It is extremely difficult to document every possible conversion when
+using a mix of operators in an `update` section. The above examples
+should be sufficient for most common cases.
+
+Our recommendation is that if an `update` section contains multiple
+different operators, it should be split into multiple assignments.
+That is, do not try to convert the entire `update` section as-is.
+Instead, separate the `update` section into multiple `update`
+sections, one for each operator. Then, convert each `update` section
+individually.
+
+Another option is to write down in plain English what operations you
+wish to perform. Then, look at the new documentation to see how those
+operations match to the new syntax.
+
+In most cases, the operations are little more than "add attributes to
+list", or "delete attributes from list". Those operations are simple
+to perform in the new syntax.
+
+== Issues with the Old Operators
+
+The operators in the `update` sections were really _list_ operators,
+and not _value_ operators. For example, `+=` was "add attribute to
+list", and not "add value to attribute". This mixup was the source of
+a significant amount of confusion when people first tried to use
+FreeRADIUS.
+
+In addition, using `+=` to manipulate lists meant that it was
+impossible to use that operator for adding values. The follow-on
+effect was that math had to be done using the `%{expr:...}` expansion,
+which was confusing and difficult to document. Changing the syntax
+allowed the separation of list assignments from value modifications,
+which meant that xref:unlang/expression.adoc[expressions] became
+became simpler.
+
+
// Copyright (C) 2021 Network RADIUS SAS. Licenced under CC-by-NC 4.0.
// Development of this documentation was sponsored by Network RADIUS SAS.