]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
document and clean up "enum=" and "clone="
authorAlan T. DeKok <aland@freeradius.org>
Mon, 20 Feb 2023 20:40:48 +0000 (15:40 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 20 Feb 2023 20:46:24 +0000 (15:46 -0500)
"enum" is for copying values.

"clone" is for copying TLV and STRUCT types

doc/antora/modules/reference/pages/dictionary/alias.adoc
doc/antora/modules/reference/pages/dictionary/attribute.adoc
doc/antora/modules/reference/pages/dictionary/enum.adoc [new file with mode: 0644]
share/dictionary/dns/dictionary.freeradius.internal
src/lib/util/dict_fixup.c
src/lib/util/dict_tokenize.c

index 646a943e332a6eca97c58aeac3fff7dd9be93fb8..656e61f84b7b541a8e17bf609d0e3b056f6921f7 100644 (file)
@@ -18,7 +18,8 @@ overlap with the name of any other attribute.
 <reference>:: An OID by name `Vendor.Cisco.AVPair`, or by number `26.9.1`.
 +
 The full name or number must be given.
-.Examples
+
+.Example
 ----
 ALIAS Cisco-AVPair 26.9.1
 ----
@@ -26,7 +27,7 @@ ALIAS Cisco-AVPair 26.9.1
 == Purpose of the ALIAS keyword
 
 The purpose of the `ALIAS` keyword is to allow for easier transition
-from ealier versions of FreeRADIUS to version 4.  We recognize that
+from earlier versions of FreeRADIUS to version 4.  We recognize that
 the old attribute names are used in many places such as databases.  It
 can be difficult to change many thousands of existing entries in a
 "live" system.
@@ -41,9 +42,10 @@ file.
 == v3 Compatible names
 
 All of the attributes have been renamed from v3.  This change was
-necessary in order to support new funtionality in v4.  The
-unfortunate side effect of this change is that all of the names in
-SQL, LDAP, and the "files" module are incompatible with v4.
+necessary in order to support new funtionality in v4.  The unfortunate
+side effect of this change is that all of the names which are
+currently in SQL, LDAP, and the "files" module for use with v3, are
+incompatible with v4.
 
 We recognize that is is difficult to change every entry in a
 database, especially when there's no clear mapping between the
@@ -51,10 +53,11 @@ database, especially when there's no clear mapping between the
 the "new" names need to be grouped and arranged in ways that the
 old ones were not.
 
-The "old" names were all in flat lists, so thatUser-Name` appeared
+The "old" names were all in flat lists, so that `User-Name` appeared
 next to `Cisco-AVPAir`.  This organization was simple enough to work
-for 20 years, but its time has come.  The new names are
-hierarchical, so that the organization is nested by definition.
+for 20 years, but its time has come.  The new names are hierarchical,
+and are contained in "parent" attributes.  This arrangment does not
+ysyakky change the length of most attribute names.
 
 For v4, the `Cisco-AVPair` attribute is called `AVPair`, and it lives
 inside of the `Cisco` namespace, which in turn lives inside of the
index fbd97aac2b0c55e253352dea68565b8d9267d551..9b08fde7a7da84bbe000975a70f8052a29718b23 100644 (file)
@@ -51,12 +51,12 @@ Common flags and meanings
 |=====
 | Name         | Description
 | `array`      | For fixed-size types, declare that the contents of the packet can have an array of this value.
-| `clone=...`  | For `tlv` types, clone (or copy) child definitions from another `tlv` type
+| `enum=...`   | For "leaf" types, copy xref:dictionary/value.adoc[VALUE]s from an `xref:dictionary/enum.adoc[ENUM].
+| `clone=...`  | For `tlv` or 'struct' types, clone (or copy) child definitions from another attribute of the same type
 | `internal`   | This attribute is internal to the server, and will never be sent "on the wire"
-| `ref=...`    | For `group` types, specify which attributes are allowed to be in this `group`
+| `ref=...`    | For `group` types, reference another attribute by name as being allowed in the `group`.
 |=====
 
-
 .Examples
 ----
 ATTRIBUTE Foo 1 string[3]
@@ -64,6 +64,34 @@ ATTRIBUTE Bar 2 octets
 ATTRIBUTE baz 3 ipv4addr
 ----
 
+
+== Clone
+
+In some cases, structured attributes have different parents, but
+identical children. The `clone=...` flag allows an attribute to copy
+or "clone" the children of another attribute.
+
+The `clone` flag can only be used for the data type `tlv`.
+
+.Clone Examples
+----
+ATTRIBUTE Foo 1 tlv
+ATTRIBUTE Bar 1.1 ipaddr
+ATTRIBUTE Baz 2 tlv clone=Foo
+----
+
+== References
+
+In some cases, attributes can "group" other attributes without adding
+a new hierarchy.  The `ref=...` flag allows an attribute to reference
+another attribute.
+
+If `ref` is not given for an attribute of type `group` then the
+reference is assumed to be to the "root" of the current protocol
+dictionary.
+
+The `ref` flag can only be used for the data type `group`.
+
 == Fixed Size Data types
 
 The following data types can be marked up as having fixed size, by
diff --git a/doc/antora/modules/reference/pages/dictionary/enum.adoc b/doc/antora/modules/reference/pages/dictionary/enum.adoc
new file mode 100644 (file)
index 0000000..6357614
--- /dev/null
@@ -0,0 +1,50 @@
+= The ENUM keyword
+
+.Syntax
+----
+ENUM <name> <type>
+----
+
+.Description
+The `ENUM` keyword defines name for set of xref:dictionary/value.adoc[VALUE]s.
+
+<name>:: The name of the enum.
++
+These names are in the same namespace as
+xref:dictionary/attribute.adoc[ATTRIBUTE]s, and must follow the same
+rules
+
+<type>:: A xref:type/index.adoc[data type]
++
+The list of allowed data types are the same as for xref:dictionary/value.adoc[VALUE].
+
+Once an `ENUM` is defined, it can have
+xref:dictionary/value.adoc[VALUE]s associated with it, just like with
+xref:dictionary/attribute.adoc[ATTRIBUTE]s.
+
+The main purpose of `ENUM` is to define commonly used values in one
+place, and then refer to those values from multiple places.  This
+reuse simplifies the dictionaries, and helps to avoid errors.
+
+In the following example, `Ethernet-Type` is defined as an `ENUM` and
+given xref:dictionary/value.adoc[VALUE]s.  We then define two
+xref:dictionary/attribute.adoc[ATTRIBUTE]s, and copy those
+xref:dictionary/value.adoc[VALUE]s from the `ENUM` to the
+xref:dictionary/attribute.adoc[ATTRIBUTE].
+
+After these definitions, when the server will allow `Some-Protocol` to
+be assigned the value `IPv4`, which will get encoded into a packet as
+the 16-bit field `0x0800.
+
+.Example
+----
+ENUM Ethernet-Type uint16
+VALUE Ethernet-Type IPv4 0x0800
+VALUE Ethernet-Type IPv6 0x86DD
+
+ATTRIBUTE Some-Protocol 2112 uint16 enum=Ethernet-Type
+ATTRIBUTE Other-Thing  6809 uint16 enum=Ethernet-Type
+----
+
+// Copyright (C) 2023 Network RADIUS SAS.  Licenced under CC-by-NC 4.0.
+// Development of this documentation was sponsored by Network RADIUS SAS.
index 7743b99d27623f32541f117362e030b5d34e7ecf..6c02b503c7709cfaeead2a2de048e1c240b5b605 100644 (file)
@@ -4,7 +4,7 @@
 # Version $Id$
 FLAGS  internal
 
-ATTRIBUTE      Packet-Type                             1000    uint32 clone=packet.opcode
+ATTRIBUTE      Packet-Type                             1000    uint32 enum=packet.opcode
 
 VALUE  Packet-Type                     query.response          16
 VALUE  Packet-Type                     iquery.response         17
index 72570425b3e55ed665e5b8df8142dbf374cbab7a..aaeaef6e08ce38d8892565b3938fb94d467298bf 100644 (file)
@@ -475,7 +475,7 @@ static inline CC_HINT(always_inline) int dict_fixup_clone_apply(UNUSED dict_fixu
                int copied;
 
                /*
-                *      Structural types cannot be the source or destination of clones.
+                *      Only TLV and STRUCT types can be the source or destination of clones.
                 *
                 *      Leaf types can be cloned, even if they're
                 *      different types.  But only if they don't have
index ad1e64e4fb0d9b61baa0bfa21ae9ccc6be8e2570..b1695567199adb84d10ba948071651a146519d69 100644 (file)
@@ -499,6 +499,11 @@ static int dict_process_flag_field(dict_tokenize_ctx_t *ctx, char *name, fr_type
                                return -1;
                        }
 
+                       if ((type != FR_TYPE_TLV) && (type != FR_TYPE_STRUCT)) {
+                               fr_strerror_const("'clone=...' references can only be used for 'tlv' and 'struct' types");
+                               return -1;
+                       }
+
                        /*
                         *      Allow cloning of any types, so long as
                         *      the types are the same.  We do the checks later.
@@ -521,12 +526,8 @@ static int dict_process_flag_field(dict_tokenize_ctx_t *ctx, char *name, fr_type
                                return -1;
                        }
 
-                       switch (type) {
-                       case FR_TYPE_LEAF:
-                               break;
-
-                       default:
-                               fr_strerror_const("ENUM references be used for structural types");
+                       if (!fr_type_is_leaf(type)) {
+                               fr_strerror_const("'enum=...' references cannot be used for structural types");
                                return -1;
                        }
 
@@ -558,6 +559,11 @@ static int dict_process_flag_field(dict_tokenize_ctx_t *ctx, char *name, fr_type
                                        fr_strerror_const("Invalid reference in 'enum=...', target has no VALUEs");
                                        return -1;
                                }
+
+                               if (fr_dict_attr_is_key_field(da)) {
+                                       fr_strerror_const("Invalid reference in 'enum=...', target is a 'key' field");
+                                       return -1;
+                               }
                        }
 
                } else if (ctx->dict->subtype_table) {
@@ -1136,6 +1142,11 @@ static int dict_read_process_enum(dict_tokenize_ctx_t *ctx, char **argv, int arg
        }
 
        flags = *base_flags;
+       flags.name_only = true;         /* values for ENUM are irrelevant */
+       flags.internal = true;          /* ENUMs will never get encoded into a protocol */
+#if 0
+       flags.is_enum = true;           /* it's an enum, and can't be assigned to a #fr_pair_t */
+#endif
 
        if (dict_process_type_field(ctx, argv[1], &type, &flags) < 0) return -1;
 
@@ -1177,7 +1188,7 @@ static int dict_read_process_enum(dict_tokenize_ctx_t *ctx, char **argv, int arg
        if (!dict_attr_fields_valid(ctx->dict, parent, argv[0], &attr, type, &flags)) return -1;
 
        /*
-        *      Add in an attribute
+        *      Add the ENUM as if it was an ATTRIBUTE.
         */
        if (fr_dict_attr_add(ctx->dict, parent, argv[0], attr, type, &flags) < 0) return -1;