]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
remove STRUCT dictionary keyword
authorAlan T. DeKok <aland@freeradius.org>
Mon, 24 Nov 2025 01:19:19 +0000 (20:19 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 24 Nov 2025 01:19:19 +0000 (20:19 -0500)
it is no longer necessary

doc/antora/modules/reference/nav.adoc
doc/antora/modules/reference/pages/dictionary/index.adoc
doc/antora/modules/reference/pages/dictionary/member.adoc
doc/antora/modules/reference/pages/dictionary/struct.adoc [deleted file]
doc/antora/modules/reference/pages/type/all_types.adoc
src/lib/util/dict_tokenize.c

index e0a1a9619237e23ada3ee9c00d1641aa1d2db2fa..acef07d9c5afa22481a446145b2911b5c626c83a 100644 (file)
 *** xref:dictionary/member.adoc[MEMBER]
 *** xref:dictionary/protocol.adoc[PROTOCOL]
 *** xref:dictionary/reference.adoc[References]
-*** xref:dictionary/struct.adoc[STRUCT]
 *** xref:dictionary/value.adoc[VALUE]
 *** xref:dictionary/vendor.adoc[VENDOR]
 *** xref:dictionary/begin-protocol.adoc[BEGIN-PROTOCOL]
index 7479ecac63e720da24419d3bbf9287712d18673d..b9c38bc13365b854a3a21436d6d92f9e1b3176a7 100644 (file)
@@ -106,8 +106,7 @@ xref:dictionary/alias.adoc[ALIAS] keyword can help.  See
 Names occur in many places, such as in
 xref:dictionary/attribute.adoc[ATTRIBUTE] definitions,
 xref:dictionary/define.adoc[DEFINE],
-xref:dictionary/member.adoc[MEMBER],
-xref:dictionary/struct.adoc[STRUCT], etc.  We generally refer to all
+xref:dictionary/member.adoc[MEMBER], etc.  We generally refer to all
 of these entities as being 'attributes', no matter how the name was
 defined.
 
@@ -153,7 +152,6 @@ xref:dictionary/attribute.adoc[ATTRIBUTE] and xref:dictionary/value.adoc[VALUE].
 | xref:dictionary/include.adoc[$INCLUDE]     | Include another dictionary file
 | xref:dictionary/member.adoc[MEMBER]        | Define a member of a `STRUCT`
 | xref:dictionary/protocol.adoc[PROTOCOL]    | Define a protocol like `RADIUS` or `DHCPv4`
-| xref:dictionary/struct.adoc[STRUCT]        | Define a structure which can contain ``MEMBER``s
 | xref:dictionary/value.adoc[VALUE]          | Define a name for a particular value of an `ATTRIBUTE`
 | xref:dictionary/vendor.adoc[VENDOR]        | Define a name and number for a vendor
 |=====
index 49cde0db249784b9215ea723d6cf253a7234fbc1..ddadeec83cbc8823648578b1e98f875be6c97a5f 100644 (file)
@@ -7,14 +7,13 @@ MEMBER <name> <type> [<flags>]
 
 .Description
 
-The `MEMBER` keyword defines a name and data type mapping for members
-of a parent xref:dictionary/struct.adoc[STRUCT] definition.  The definitions
-preceding a `MEMBER` must be either another `MEMBER`, or be a `STRUCT`.
+The `MEMBER` keyword defines a name and data type mapping for fields
+of a `struct` data type.
 
 <name>:: The name of the attribute.  The name can contain alphanumeric
 characters, `-`, and `_`.  The name should be short and descriptive.
 +
-The name of this `MEMBER` is defined only within the context of its parent `STRUCT`.
+The name of this `MEMBER` is defined only within the context of its parent `struct`.
 
 <type>:: A xref:type/index.adoc[data type], or the special type `bit`.
 +
@@ -43,15 +42,15 @@ 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.
 | `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
-| `key`        | This member is a "key" type.  The struct can have different xref:dictionary/struct.adoc[STRUCT] children depending on the value of the key.
+| `clone=...`  | For `tlv` types, clone (or copy) child definitions from another attribute of the same type
+| `key`        | This member is a "key" type.  The structure can have different children of type `union`, depending on the value of the key.
 |=====
 
 See the the xref:dictionary/reference.adoc[reference] page for the syntax of references in the dictionary.
 
 .Examples
 ----
-STRUCT Foo
+ATTRIBUTE Foo 1 struct
 MEMBER Bar  bit[3]
 MEMBER Baz  bit[5]
 MEMBER Name string
@@ -72,6 +71,5 @@ Fixed Size types and meanings
 | `string[n]`  | Declare that this attribute uses `n` bytes of `string` data
 |=====
 
-
-// Copyright (C) 2023 Network RADIUS SAS.  Licenced under CC-by-NC 4.0.
+// Copyright (C) 2025 Network RADIUS SAS.  Licenced under CC-by-NC 4.0.
 // This documentation was developed by Network RADIUS SAS.
diff --git a/doc/antora/modules/reference/pages/dictionary/struct.adoc b/doc/antora/modules/reference/pages/dictionary/struct.adoc
deleted file mode 100644 (file)
index cee5de4..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-= The STRUCT keyword
-
-.Syntax
-----
-STRUCT <name> <field> <value> [<flags>]
-----
-
-.Description
-The `STRUCT` keyword defines a child structure of a previous `struct`,
-which is keyed by a particular xref:dictionary/member.adoc[MEMBER].
-
-Many protocols are defined as a _header_ which contains information
-about the protocol, and a _data_ portion which contains data carried
-by that _header_.  The _header_ usually includes a _type_ field, which
-defines how the _data_ portion is interpreted.  The `STRUCT` keyword
-allows the server to automatically decode these protocols, and all of
-their contents.
-
-<name>:: The name of the attribute.  The name can contain alphanumeric
-characters, `-`, and `_`.  The name should be short and descriptive.
-+
-As the names are hierarchical, the name is scoped to its parent.  So
-the name `Counter` can mean different things, depending on its
-context.
-
-<field>:: The name of a previous xref:dictionary/member.adoc[MEMBER]
-which has been marked up with the word `key` in the `flags` field. 
-+
-In most cases, the _<field>_ reference is simply the name of a field
-in the attribute of type `struct` which was defined immediately before
-this definition.
-+
-The _<field>_ reference can also be an OID-style name, as in
-`Client-Id.Type`.  The name is always looked up in the current dictionary.
-References cannot be to fields in other dictionaries.
-
-<value>:: When the _<field>_ has this value, the data is interpreted
-as this `struct`.  Numbers can be specified as decimal (`19`), or as
-hex (`0xffee`).
-
-<flags>:: Can only be `length=uint8` or `length=uint16`.  When
-encoding or decoding the structure, it is prefixed by a `uint8` or `uint16` field
-containing the length of the structure.
-
-Common flags and meanings
-[options="header"]
-[cols="30%,70%"]
-|=====
-| Name             | Description
-| `length=uint8`   | When encoding or decoding the structure, it is prefixed by a `uint8` field containing the length of the structure.
-| `length=uint16`  | When encoding or decoding the structure, it is prefixed by a `uint16` field containing the length of the structure.
-| `offset=<number>` | When encoding or decoding the structure, add `number` to the value in the `length` field.
-|=====
-
-
-The following example shows how one structure can include another one.  In this example, the `Information` structure has two fields: `Type` and `Other`.  It has two possible sub-structures which can appear after the `Other` field.  Which sub-structure to be decoded is defined by the `key` field: `Type`.
-
-.Example of a Key field
-----
-ATTRIBUTE Information 1 struct
-MEMBER Type uint8 key
-MEMBER Other uint32
-
-STRUCT Foo Type 1
-MEMBER Bar uint16
-MEMBER Baz uint16
-
-STRUCT Blag Type 2
-MEMBER Whoops uint32
-MEMBER Stuff uint8
-----
-
-== Caveats
-
-Variable-sized fields such as `tlv`, `struct`, `string`, or `octets` can only be placed at the end of the `struct`.
-
-// Copyright (C) 2023 Network RADIUS SAS.  Licenced under CC-by-NC 4.0.
-// This documentation was developed by Network RADIUS SAS.
index 4587de9d53e9496f44baf16bad0bb5966a9ff446..a3e338a9ca91666f466a895f34dc63a3138eee5a 100644 (file)
@@ -59,6 +59,7 @@ statements.
 | group                | generic grouping
 | struct       | structure which contains fixed-width fields
 | tlv          | type-length-value which contains other attributes
+| union         | Selects a child based on the value of a `key` field.
 | vendor       | Encapsulation of a vendor within data type `vsa`
 | vsa          | Encapsulation of vendor-specific attributes
 |=====
@@ -68,14 +69,6 @@ data type can contain child attributes.  The different structural
 types have different behaviors about what kind of children they can
 contain, and how the data type is sent in a packet over the network.
 
-struct:: A `struct` contains fixed-sized data types, in a pre-defined order.
-+
-The `struct` can only contain a fixed and pre-defined list of child
-attributes.  These attributes are the fields, or members, of the structure.
-+
-The `struct` always encodes all of its children.  If a child is
-missing, then the relevant field is filled with zeros.
-
 group: A `group` contains an arbitrary collection of children, in any order.
 +
 A `group` is really a reference to some other attribute elsewhere in
@@ -90,6 +83,14 @@ information.
 The `group` only encodes the child attributes which have been created
 and stored within the `group`.  The order of children does not matter.
 
+struct:: A `struct` contains fixed-sized data types, in a pre-defined order.
++
+The `struct` can only contain a fixed and pre-defined list of child
+attributes.  These attributes are the fields, or members, of the structure.
++
+The `struct` always encodes all of its children.  If a child is
+missing, then the relevant field is filled with zeros.
+
 tlv:: A `tlv` defines a hierarchy of children, which can only be contained in the `tlv`.
 +
 The `tlv` can only contain child attributes which have been defined as
@@ -98,6 +99,16 @@ children of the `tlv.`
 The `tlv` only encodes the child attributes which have been created
 and stored within the `tlv`.  The order of children does not matter.
 
+union: A `union` contains one out of set of children.
++
+The `union` can contains any child attributes, so long as they are
+within the same protocol namespace.  See the
+dictionary/attribute.adoc[ATTRIBUTE] documentation for more
+information.
++
+The `union` only encodes one child attribute which has been defined
+within the `union`.
+
 vendor:: A `vendor` is a group which has a limited subset of children:
 attributes which have been defined by that vendor.
 +
@@ -121,5 +132,5 @@ matter.
 A `vsa` data type can only be a contain children of the `vendor` data type.
 
 
-// Copyright (C) 2021 Network RADIUS SAS.  Licenced under CC-by-NC 4.0.
+// Copyright (C) 2025 Network RADIUS SAS.  Licenced under CC-by-NC 4.0.
 // This documentation was developed by Network RADIUS SAS
index 5fe714cfb6f093b2cd485a0718acddbe5e04dcef..4aee1d5e921d33ca9b08a5977a5c421e3005ca78 100644 (file)
@@ -2599,219 +2599,6 @@ static int dict_read_process_member(dict_tokenize_ctx_t *dctx, char **argv, int
        return dict_set_value_attr(dctx, da);
 }
 
-/** Process a STRUCT name attr value
- *
- * Define struct 'name' when key 'attr' has 'value'.
- *
- *  Which MUST be a sub-structure of another struct
- */
-static int dict_read_process_struct(dict_tokenize_ctx_t *dctx, char **argv, int argc,
-                                   UNUSED fr_dict_attr_flags_t *base_flags)
-{
-       fr_value_box_t                  box = FR_VALUE_BOX_INITIALISER_NULL(box);
-       int                             i;
-       fr_dict_attr_t const            *parent = NULL;
-       fr_dict_attr_t const            *key = NULL;
-       unsigned int                    attr;
-       char const                      *name = argv[0];
-       char const                      *value;
-       char                            *flags = NULL;
-       fr_dict_attr_t                  *da;
-
-       fr_assert(dctx->stack_depth > 0);
-
-       /*
-        *      Old-stle: unwind the stack until we find a parent which has a child named for key_attr.
-        */
-       parent = CURRENT_FRAME(dctx)->da;
-       if (parent->type != FR_TYPE_UNION) {
-               char const *key_attr;
-
-               if ((argc < 3) || (argc > 4)) {
-                       fr_strerror_const("Invalid STRUCT syntax");
-                       return -1;
-               }
-
-               key_attr = argv[1];
-               value = argv[2];
-               if (argc == 4) flags = argv[3];
-
-               parent = NULL;
-               for (i = dctx->stack_depth; i > 0; i--) {
-                       key = dict_attr_by_name(NULL, dctx->stack[i].da, key_attr);
-                       if (key) {
-                               parent = key;
-                               dctx->stack_depth = i;
-                               break;
-                       }
-               }
-
-               /*
-                *      No parent was found, maybe the reference is a fully qualified name from the root.
-                */
-               if (!parent) {
-                       parent = fr_dict_attr_by_oid(NULL, CURRENT_FRAME(dctx)->da->dict->root, key_attr);
-
-                       if (!parent) {
-                               fr_strerror_printf("Invalid STRUCT definition, unknown key attribute %s",
-                                                  key_attr);
-                               return -1;
-                       }
-
-                       /*
-                        *      @todo - remove after migration_union_key is deleted
-                        */
-                       if (!fr_dict_attr_is_key_field(parent)) {
-                               fr_strerror_printf("Attribute '%s' is not a 'key' attribute", key_attr);
-                               return -1;
-                       }
-
-                       key = parent;
-               }
-
-       } else {
-               fr_dict_attr_ext_ref_t *ext;
-
-               /*
-                *      STRUCT inside of a UNION doesn't need to specify the name of the key.
-                *
-                *      STRUCT name value [flags]
-                */
-               if ((argc < 2) || (argc > 3)) {
-                       fr_strerror_const("Invalid STRUCT syntax");
-                       return -1;
-               }
-
-               value = argv[1];
-               if (argc == 3) flags = argv[2];
-
-               /*
-                *      The parent is a union.  Get and verify the key ref.
-                */
-               ext = fr_dict_attr_ext(parent, FR_DICT_ATTR_EXT_KEY);
-               fr_assert(ext != NULL);
-
-               /*
-                *      Double-check names against the reference.
-                */
-               key = ext->ref;
-               fr_assert(key);
-               fr_assert(fr_dict_attr_is_key_field(key));
-       }
-
-       /*
-        *      Rely on dict_attr_flags_valid() to ensure that
-        *      da->type is an unsigned integer, AND that da->parent->type == struct
-        */
-       if (!fr_cond_assert(parent->parent->type == FR_TYPE_STRUCT)) return -1;
-
-       /*
-        *      Parse the value, which should be a small integer.
-        */
-       if (fr_value_box_from_str(NULL, &box, key->type, NULL, value, strlen(value), NULL) < 0) {
-               fr_strerror_printf_push("Invalid value for STRUCT \"%s\"", value);
-               return -1;
-       }
-
-       /*
-        *      Allocate the attribute here, and then fill in the fields
-        *      as we start parsing the various elements of the definition.
-        */
-       da = dict_attr_alloc_null(dctx->dict->pool, dctx->dict->proto);
-       if (unlikely(da == NULL)) return -1;
-       dict_attr_location_set(dctx, da);
-       da->dict = dctx->dict;
-
-       if (unlikely(dict_attr_type_init(&da, FR_TYPE_STRUCT) < 0)) {
-       error:
-               talloc_free(da);
-               return -1;
-       }
-
-       /*
-        *      Structs can be prefixed with 16-bit lengths, but not
-        *      with any other type of length.
-        */
-       if (flags) {
-               if (dict_process_flag_field(dctx, flags, &da) < 0) goto error;
-       }
-
-       /*
-        *      Create a unique number for the child attribute, based on the value of the key.
-        */
-       switch (key->type) {
-       case FR_TYPE_UINT8:
-               attr = box.vb_uint8;
-               break;
-
-       case FR_TYPE_UINT16:
-               attr = box.vb_uint16;
-               break;
-
-       case FR_TYPE_UINT32:
-               attr = box.vb_uint32;
-               break;
-
-       default:
-               fr_assert(0);   /* should have been checked earlier when the key attribute was defined */
-               return -1;
-       }
-
-       if (unlikely(dict_attr_num_init(da, attr) < 0)) goto error;
-       if (unlikely(dict_attr_parent_init(&da, parent) < 0)) goto error;
-       if (unlikely(dict_attr_finalise(&da, name) < 0)) goto error;
-
-       /*
-        *      Check to see if this is a duplicate attribute
-        *      and whether we should ignore it or error out...
-        */
-       switch (dict_attr_allow_dup(da)) {
-       case 1:
-               break;
-
-       case 0:
-               talloc_free(da);
-               return 0;
-
-       default:
-               goto error;
-       }
-
-       /*
-        *      Add the STRUCT to the global namespace, and as a child of "parent".
-        */
-       switch (dict_attr_add_or_fixup(&dctx->fixup, &da)) {
-       default:
-               goto error;
-
-       /* FIXME: Should dict_attr_enum_add_name also be called in the fixup code? */
-       case 0:
-               da = dict_attr_by_name(NULL, parent, name);
-               if (!da) return -1;
-
-               /*
-                *      A STRUCT definition is an implicit BEGIN-STRUCT.
-                */
-               dctx->relative_attr = NULL;
-               if (dict_dctx_push(dctx, da, NEST_NONE) < 0) return -1;
-
-               /*
-                *      Add the VALUE to the key attribute, and ensure that
-                *      the VALUE also contains a pointer to the child struct.
-                */
-               if (dict_attr_enum_add_name(fr_dict_attr_unconst(key), name, &box, false, true, da) < 0) {
-                       fr_value_box_clear(&box);
-                       return -1;
-               }
-               fr_value_box_clear(&box);
-               break;
-
-       case 1:
-               break;
-       }
-
-       return 0;
-}
 
 /** Process a value alias
  *
@@ -3314,7 +3101,6 @@ static int _dict_from_file(dict_tokenize_ctx_t *dctx,
                { L("FLAGS"),                   { .parse = dict_read_process_flags } },
                { L("MEMBER"),                  { .parse = dict_read_process_member } },
                { L("PROTOCOL"),                { .parse = dict_read_process_protocol, .begin = dict_begin_protocol }},
-               { L("STRUCT"),                  { .parse = dict_read_process_struct } },
                { L("VALUE"),                   { .parse = dict_read_process_value } },
                { L("VENDOR"),                  { .parse = dict_read_process_vendor } },
        };