From: Alan T. DeKok Date: Mon, 24 Nov 2025 01:19:19 +0000 (-0500) Subject: remove STRUCT dictionary keyword X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c4fa62cba8cdd5152bee3c1f6618964ab2cf71ad;p=thirdparty%2Ffreeradius-server.git remove STRUCT dictionary keyword it is no longer necessary --- diff --git a/doc/antora/modules/reference/nav.adoc b/doc/antora/modules/reference/nav.adoc index e0a1a961923..acef07d9c5a 100644 --- a/doc/antora/modules/reference/nav.adoc +++ b/doc/antora/modules/reference/nav.adoc @@ -131,7 +131,6 @@ *** 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] diff --git a/doc/antora/modules/reference/pages/dictionary/index.adoc b/doc/antora/modules/reference/pages/dictionary/index.adoc index 7479ecac63e..b9c38bc1336 100644 --- a/doc/antora/modules/reference/pages/dictionary/index.adoc +++ b/doc/antora/modules/reference/pages/dictionary/index.adoc @@ -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 |===== diff --git a/doc/antora/modules/reference/pages/dictionary/member.adoc b/doc/antora/modules/reference/pages/dictionary/member.adoc index 49cde0db249..ddadeec83cb 100644 --- a/doc/antora/modules/reference/pages/dictionary/member.adoc +++ b/doc/antora/modules/reference/pages/dictionary/member.adoc @@ -7,14 +7,13 @@ MEMBER [] .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. :: 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`. :: 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 index cee5de471eb..00000000000 --- a/doc/antora/modules/reference/pages/dictionary/struct.adoc +++ /dev/null @@ -1,78 +0,0 @@ -= The STRUCT keyword - -.Syntax ----- -STRUCT [] ----- - -.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. - -:: 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. - -:: 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 __ reference is simply the name of a field -in the attribute of type `struct` which was defined immediately before -this definition. -+ -The __ 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. - -:: When the __ has this value, the data is interpreted -as this `struct`. Numbers can be specified as decimal (`19`), or as -hex (`0xffee`). - -:: 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=` | 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. diff --git a/doc/antora/modules/reference/pages/type/all_types.adoc b/doc/antora/modules/reference/pages/type/all_types.adoc index 4587de9d53e..a3e338a9ca9 100644 --- a/doc/antora/modules/reference/pages/type/all_types.adoc +++ b/doc/antora/modules/reference/pages/type/all_types.adoc @@ -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 diff --git a/src/lib/util/dict_tokenize.c b/src/lib/util/dict_tokenize.c index 5fe714cfb6f..4aee1d5e921 100644 --- a/src/lib/util/dict_tokenize.c +++ b/src/lib/util/dict_tokenize.c @@ -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 } }, };