From: Alan T. DeKok Date: Mon, 20 Feb 2023 20:40:48 +0000 (-0500) Subject: document and clean up "enum=" and "clone=" X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6e130ac8e2bb59e6178660271175346b95a3944a;p=thirdparty%2Ffreeradius-server.git document and clean up "enum=" and "clone=" "enum" is for copying values. "clone" is for copying TLV and STRUCT types --- diff --git a/doc/antora/modules/reference/pages/dictionary/alias.adoc b/doc/antora/modules/reference/pages/dictionary/alias.adoc index 646a943e332..656e61f84b7 100644 --- a/doc/antora/modules/reference/pages/dictionary/alias.adoc +++ b/doc/antora/modules/reference/pages/dictionary/alias.adoc @@ -18,7 +18,8 @@ overlap with the name of any other attribute. :: 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 that` User-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 diff --git a/doc/antora/modules/reference/pages/dictionary/attribute.adoc b/doc/antora/modules/reference/pages/dictionary/attribute.adoc index fbd97aac2b0..9b08fde7a7d 100644 --- a/doc/antora/modules/reference/pages/dictionary/attribute.adoc +++ b/doc/antora/modules/reference/pages/dictionary/attribute.adoc @@ -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 index 00000000000..63576147d1b --- /dev/null +++ b/doc/antora/modules/reference/pages/dictionary/enum.adoc @@ -0,0 +1,50 @@ += The ENUM keyword + +.Syntax +---- +ENUM +---- + +.Description +The `ENUM` keyword defines name for set of xref:dictionary/value.adoc[VALUE]s. + +:: 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 + +:: 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. diff --git a/share/dictionary/dns/dictionary.freeradius.internal b/share/dictionary/dns/dictionary.freeradius.internal index 7743b99d276..6c02b503c77 100644 --- a/share/dictionary/dns/dictionary.freeradius.internal +++ b/share/dictionary/dns/dictionary.freeradius.internal @@ -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 diff --git a/src/lib/util/dict_fixup.c b/src/lib/util/dict_fixup.c index 72570425b3e..aaeaef6e08c 100644 --- a/src/lib/util/dict_fixup.c +++ b/src/lib/util/dict_fixup.c @@ -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 diff --git a/src/lib/util/dict_tokenize.c b/src/lib/util/dict_tokenize.c index ad1e64e4fb0..b1695567199 100644 --- a/src/lib/util/dict_tokenize.c +++ b/src/lib/util/dict_tokenize.c @@ -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;