From: Alan T. DeKok Date: Sun, 23 Feb 2025 11:33:42 +0000 (-0500) Subject: Require '.' or '@' in references X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=aa1431c0fde659a8af6dd52f3f2b0c06ff7d1cd3;p=thirdparty%2Ffreeradius-server.git Require '.' or '@' in references which ends up being a lot clearer than DEFINE foo bar clone=foo where the DEFINE is in a child context via BEGIN/END, and the 'clone' ref is in the root context Update all of the dictionaries to match. As a bonus, dict_protocol_reference() can now distinguish the cases of "error" from "reference not found" Update the antora documentation to match. Create a new reference page which contains all of the documentation for references. --- diff --git a/doc/antora/modules/reference/nav.adoc b/doc/antora/modules/reference/nav.adoc index 282766e9c6f..9e4c37f1189 100644 --- a/doc/antora/modules/reference/nav.adoc +++ b/doc/antora/modules/reference/nav.adoc @@ -99,6 +99,7 @@ *** xref:dictionary/include.adoc[$INCLUDE] *** 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] diff --git a/doc/antora/modules/reference/pages/dictionary/attribute.adoc b/doc/antora/modules/reference/pages/dictionary/attribute.adoc index e17291e80b9..c6bed49b21c 100644 --- a/doc/antora/modules/reference/pages/dictionary/attribute.adoc +++ b/doc/antora/modules/reference/pages/dictionary/attribute.adoc @@ -60,13 +60,7 @@ Common flags and meanings | `secret` | The server will not print `secret` values in debug mode, and in many other situations. |===== -The `` field in the examples above is an attribute references such as `Foo`, or `Foo.Bar`, or `@dhcpv4.foo.bar`. All `` fields use the same syntax. - -If the ref begins with `@` the ref will be treated as a "foreign" reference to another protocol. The first component will be used as the protocol name e.g. `ref=@RADIUS`. - -If the ref begins with `.` the ref will be treated as relative to the current attribute, else resolution will begin from the root of the current dictionary. - -Multiple consecutive `.` can be used to traverse up the attribute hierarchy from the current attribute. +See the the xref:dictionary/reference.adoc[reference] page for the syntax of references in the dictionary. .Examples ---- @@ -75,59 +69,9 @@ ATTRIBUTE Bar 2 octets ATTRIBUTE baz 3 ipv4addr ---- - -== Enum - -In some cases, attributes need to reuse the same set of `VALUE` statements. -The `enum=...` flag allows an attribute to copy enumerated vl - -The `enum` flag can only be used for "leaf" data types. i.e. ones -which can contain a `VALUE`. - -.Enum Examples ----- -ATTRIBUTE Foo 1 integer -VALUE Zero Foo 0 - -ATTRIBUTE Bar 2 integer enum=Foo ----- - -The result of the above dictionary is that the `Bar` attribute also has `VALUE` defined, with name `Zero`. - -== 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 data types `tlv` and `struct`. - -.Clone Examples ----- -ATTRIBUTE Foo 1 tlv -ATTRIBUTE Bar 1.1 ipaddr -ATTRIBUTE Baz 2 tlv clone=Foo ----- - -The result of the above dictionary is that the `Baz` attribute also has child attribute, of name `Bar`. - -== Ref - -In some cases, attributes can "group" other attributes without adding -a new hierarchy. The `ref=...` flag allows a grouped attribute to -reference another attribute. The grouped attribute can then contain -the referenced attributes, as if those other attributes were members -of the group. - -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`. The referenced attribute must be of data type `group` or `tlv`. -613 816 8331 == Fixed Size Data types -The following data types can be marked up as having fixed size, by +Some following data types can be marked up as having fixed size, by using an array suffix, e.g. `octets[14]`. Fixed Size types and meanings @@ -141,5 +85,5 @@ Fixed Size types and meanings |===== -// 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/define.adoc b/doc/antora/modules/reference/pages/dictionary/define.adoc index e532beb87d5..1d52fff6865 100644 --- a/doc/antora/modules/reference/pages/dictionary/define.adoc +++ b/doc/antora/modules/reference/pages/dictionary/define.adoc @@ -35,8 +35,11 @@ Common flags and meanings | Name | Description | `enum=...` | For "leaf" types, copy xref:dictionary/value.adoc[VALUE]s from an `xref:dictionary/enum.adoc[ENUM] or other attribute. | `clone=...` | For `tlv` or 'struct' types, clone (or copy) child definitions from another attribute of the same type +| `ref=` | For `group` types, the referenced attributes will be allowed in the group |===== +See the the xref:dictionary/reference.adoc[reference] page for the syntax of references in the dictionary. + .Examples ---- DEFINE Foo string diff --git a/doc/antora/modules/reference/pages/dictionary/enum.adoc b/doc/antora/modules/reference/pages/dictionary/enum.adoc index 152d7ad855c..e8d6f2272a3 100644 --- a/doc/antora/modules/reference/pages/dictionary/enum.adoc +++ b/doc/antora/modules/reference/pages/dictionary/enum.adoc @@ -45,5 +45,7 @@ ATTRIBUTE Some-Protocol 2112 uint16 enum=Ethernet-Type ATTRIBUTE Other-Thing 6809 uint16 enum=Ethernet-Type ---- +See the the xref:dictionary/reference.adoc[reference] page for the syntax of references in the dictionary. + // 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/dictionary/member.adoc b/doc/antora/modules/reference/pages/dictionary/member.adoc index e686c01ccae..49cde0db249 100644 --- a/doc/antora/modules/reference/pages/dictionary/member.adoc +++ b/doc/antora/modules/reference/pages/dictionary/member.adoc @@ -47,6 +47,8 @@ Common flags and meanings | `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. |===== +See the the xref:dictionary/reference.adoc[reference] page for the syntax of references in the dictionary. + .Examples ---- STRUCT Foo diff --git a/doc/antora/modules/reference/pages/dictionary/reference.adoc b/doc/antora/modules/reference/pages/dictionary/reference.adoc new file mode 100644 index 00000000000..0b1fdef9460 --- /dev/null +++ b/doc/antora/modules/reference/pages/dictionary/reference.adoc @@ -0,0 +1,75 @@ +# References + +Some dictionary keywords allow references. For example, xref:dictionary/attribute.adoc[ATTRIBUTE], xref:dictionary/define.adoc[DEFINE], xref:dictionary/enum.adoc[ENUM], and xref:dictionary/member.adoc[MEMBER]. + +References allow the dictionaries to be smaller, by re-using previous definitions via a reference. + +Common References and meanings +[options="header"] +[cols="30%,70%"] +|===== +| Name | Description +| `clone=` | For `tlv` or 'struct' types, clone (or copy) child definitions from another attribute of the same type +| `enum=` | For "leaf" types, copy xref:dictionary/value.adoc[VALUE]s from an xref:dictionary/enum.adoc[ENUM] or other attribute. +| `ref=` | For `group` types, the referenced attributes will be allowed in the group +|===== + +All `` fields use the same syntax. + +If the ref begins with `.` the ref will be treated as relative to the _parent_ of the current attribute. Since the current attribute is in the process of being defined, it is not possible to refer to it or to its children. + +Multiple consecutive `.` can be used to traverse up the attribute hierarchy from the current attribute. + +If the ref begins with `@` the ref will be treated as an absolute reference. The reference is either to the root of the current dictionary (`@.foo`), or to the root of a different dictionary (`@DHCPv4`, or `@DHCPv4.foo`). + +== 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 data types `tlv` and `struct`. + +.Clone Examples +---- +ATTRIBUTE Foo 1 tlv +ATTRIBUTE Bar 1.1 ipaddr +ATTRIBUTE Baz 2 tlv clone=Foo +---- + +The result of the above dictionary is that the `Baz` attribute also has child attribute, of name `Bar`. + +== enum=... + +In some cases, attributes need to reuse the same set of `VALUE` statements. +The `enum=...` flag allows an attribute to copy enumerated vl + +The `enum` flag can only be used for "leaf" data types. i.e. ones +which can contain a `VALUE`. + +.Enum Examples +---- +ATTRIBUTE Foo 1 integer +VALUE Zero Foo 0 + +ATTRIBUTE Bar 2 integer enum=Foo +---- + +The result of the above dictionary is that the `Bar` attribute also has `VALUE` defined, with name `Zero`. + +== ref=... + +In some cases, attributes can "group" other attributes without adding +a new hierarchy. The `ref=...` flag allows a grouped attribute to +reference another attribute. The grouped attribute can then contain +attributes from the destination reference, as if those other +attributes were members of the group. + +If a `ref=` is not define 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`. The destination of the reference must be of data type `group` or `tlv`. + +// Copyright (C) 2025 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// This documentation was developed by Network RADIUS SAS. diff --git a/share/dictionary/der/dictionary b/share/dictionary/der/dictionary index ca6796b63df..0b47226a1e1 100644 --- a/share/dictionary/der/dictionary +++ b/share/dictionary/der/dictionary @@ -19,8 +19,8 @@ BEGIN PROTOCOL DER 11354911 # The server manages all DER `null` as `bool`. # -$INCLUDE dictionary.common $INCLUDE dictionary.oids +$INCLUDE dictionary.common $INCLUDE dictionary.rfc2986 $INCLUDE dictionary.rfc5280 diff --git a/share/dictionary/der/dictionary.common b/share/dictionary/der/dictionary.common index c0f3049b7e0..b41848d28a1 100644 --- a/share/dictionary/der/dictionary.common +++ b/share/dictionary/der/dictionary.common @@ -2,6 +2,16 @@ # Copyright (C) 2025 Network RADIUS SAS (legal@networkradius.com) # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 # Version $Id$ + +# +# This is used in lots of places. +# +DEFINE RelativeDistinguishedName set set_of=sequence,size=1.. +BEGIN RelativeDistinguishedName +DEFINE AttributeTypeAndValue sequence sequence_of=oid_and_value,ref=@.OID-Tree +END RelativeDistinguishedName + + DEFINE GeneralName choice BEGIN GeneralName @@ -21,10 +31,13 @@ ATTRIBUTE directoryName 4 sequence option BEGIN directoryName DEFINE RDNSequence sequence sequence_of=set BEGIN RDNSequence -DEFINE RelativeDistinguishedName set set_of=sequence,size=1.. -BEGIN RelativeDistinguishedName -DEFINE AttributeTypeAndValue sequence sequence_of=oid_and_value,ref=OID-Tree -END RelativeDistinguishedName + +DEFINE RelativeDistinguishedName set clone=@.RelativeDistinguishedName +#DEFINE RelativeDistinguishedName set set_of=sequence,size=1.. +#BEGIN RelativeDistinguishedName +#DEFINE AttributeTypeAndValue sequence sequence_of=oid_and_value,ref=@.OID-Tree +#END RelativeDistinguishedName + END RDNSequence END directoryName @@ -41,7 +54,7 @@ END DirectoryName DEFINE GeneralSubtree sequence BEGIN GeneralSubtree -DEFINE base sequence clone=GeneralName +DEFINE base sequence clone=@.GeneralName DEFINE minimum integer option=0,has_default VALUE minimum DEFAULT 0 DEFINE maximum integer option=1 @@ -53,7 +66,7 @@ DEFINE RDNSequence sequence sequence_of=set BEGIN RDNSequence DEFINE RelativeDistinguishedName set set_of=sequence,size=1.. BEGIN RelativeDistinguishedName -DEFINE AttributeTypeAndValue sequence sequence_of=oid_and_value,ref=OID-Tree +DEFINE AttributeTypeAndValue sequence sequence_of=oid_and_value,ref=@.OID-Tree END RelativeDistinguishedName END RDNSequence END Name diff --git a/share/dictionary/der/dictionary.crl b/share/dictionary/der/dictionary.crl index 63d5572a972..382e6a8dc2f 100644 --- a/share/dictionary/der/dictionary.crl +++ b/share/dictionary/der/dictionary.crl @@ -7,12 +7,12 @@ DEFINE distributionPoint sequence size=1.. BEGIN distributionPoint DEFINE distributionPointName sequence option=0 BEGIN distributionPointName -ATTRIBUTE fullName 0 group ref=GeneralName,der_type=sequence,sequence_of=choice,option +ATTRIBUTE fullName 0 group ref=@.GeneralName,der_type=sequence,sequence_of=choice,option ATTRIBUTE nameRelativeToCRLIssuer 1 sequence option BEGIN nameRelativeToCRLIssuer DEFINE RelativeDistinguishedName set set_of=sequence,size=1.. BEGIN RelativeDistinguishedName -DEFINE AttributeTypeandValue sequence sequence_of=oid_and_value,ref=OID-Tree +DEFINE AttributeTypeandValue sequence sequence_of=oid_and_value,ref=@.OID-Tree END RelativeDistinguishedName END nameRelativeToCRLIssuer END distributionPointName @@ -30,6 +30,6 @@ MEMBER privilegeWithdrawn bit[1] MEMBER aACompromise bit[1] END reasons -DEFINE cRLIssuer group ref=GeneralName,der_type=sequence,sequence_of=choice,option=2 +DEFINE cRLIssuer group ref=@.GeneralName,der_type=sequence,sequence_of=choice,option=2 END distributionPoint diff --git a/share/dictionary/der/dictionary.extensions b/share/dictionary/der/dictionary.extensions index 51f46a59443..3ff3240536c 100644 --- a/share/dictionary/der/dictionary.extensions +++ b/share/dictionary/der/dictionary.extensions @@ -2,7 +2,7 @@ # Copyright (C) 2025 Network RADIUS SAS (legal@networkradius.com) # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 # Version $Id$ -DEFINE Critical sequence sequence_of=oid_and_value,ref=OID-Tree +DEFINE Critical sequence sequence_of=oid_and_value,ref=@.OID-Tree ATTRIBUTE authorityInfoAccess 1.3.6.1.5.5.7.1.1 sequence sequence_of=sequence,is_oid_leaf BEGIN 1.3.6.1.5.5.7.1.1 @@ -72,9 +72,9 @@ MEMBER decipherOnly bit[1] MEMBER unused_bits bit[7] END 2.5.29.15 -ATTRIBUTE subjectAltName 2.5.29.17 group ref=GeneralName,der_type=sequence,sequence_of=choice,is_oid_leaf,size=1.. +ATTRIBUTE subjectAltName 2.5.29.17 group ref=@.GeneralName,der_type=sequence,sequence_of=choice,is_oid_leaf,size=1.. -ATTRIBUTE issuerAltName 2.5.29.18 group ref=GeneralName,der_type=sequence,sequence_of=choice,is_oid_leaf,size=1.. +ATTRIBUTE issuerAltName 2.5.29.18 group ref=@.GeneralName,der_type=sequence,sequence_of=choice,is_oid_leaf,size=1.. ATTRIBUTE basicConstraints 2.5.29.19 sequence is_oid_leaf BEGIN 2.5.29.19 @@ -85,8 +85,8 @@ END 2.5.29.19 ATTRIBUTE nameConstraints 2.5.29.30 sequence is_oid_leaf BEGIN 2.5.29.30 -DEFINE permittedSubtrees group ref=GeneralSubtree,sequence_of=sequence,option=0 -DEFINE excludedSubtrees group ref=GeneralSubtree,sequence_of=sequence,option=1 +DEFINE permittedSubtrees group ref=@.GeneralSubtree,sequence_of=sequence,option=0 +DEFINE excludedSubtrees group ref=@.GeneralSubtree,sequence_of=sequence,option=1 END 2.5.29.30 ATTRIBUTE cRLDIstributionPoints 2.5.29.31 sequence sequence_of=sequence,is_oid_leaf @@ -102,7 +102,7 @@ DEFINE policyIdentifier oid DEFINE policyQualifiers sequence sequence_of=sequence,size=1.. BEGIN policyQualifiers -DEFINE policyQualifierInfo sequence sequence_of=oid_and_value,ref=OID-Tree +DEFINE policyQualifierInfo sequence sequence_of=oid_and_value,ref=@.OID-Tree END policyQualifiers END policyInformation @@ -117,7 +117,7 @@ END 2.5.29.33 ATTRIBUTE authorityKeyIdentifier 2.5.29.35 sequence sequence_of=choice,is_oid_leaf BEGIN 2.5.29.35 ATTRIBUTE keyIdentifier 0 octetstring option -ATTRIBUTE authorityCertIssuer 1 group ref=GeneralName,der_type=sequence,sequence_of=choice,option +ATTRIBUTE authorityCertIssuer 1 group ref=@.GeneralName,der_type=sequence,sequence_of=choice,option ATTRIBUTE authorityCertSerialNumber 2 octetstring option END 2.5.29.35 diff --git a/share/dictionary/der/dictionary.rfc2986 b/share/dictionary/der/dictionary.rfc2986 index 6affcb534fa..1075467ca6f 100644 --- a/share/dictionary/der/dictionary.rfc2986 +++ b/share/dictionary/der/dictionary.rfc2986 @@ -35,7 +35,7 @@ BEGIN Attributes DEFINE Attribute-thing sequence BEGIN Attribute-thing DEFINE OID oid -DEFINE Extensions set set_of=oid_and_value,ref=OID-Tree,is_extensions +DEFINE Extensions set set_of=oid_and_value,ref=@.OID-Tree,is_extensions END Attribute-thing END Attributes diff --git a/share/dictionary/der/dictionary.rfc5280 b/share/dictionary/der/dictionary.rfc5280 index 0b2674e51b7..424f970ae7b 100644 --- a/share/dictionary/der/dictionary.rfc5280 +++ b/share/dictionary/der/dictionary.rfc5280 @@ -12,13 +12,13 @@ BEGIN version DEFINE VersionNum integer END version DEFINE serialNumber octets der_type=integer -DEFINE signature sequence sequence_of=oid_and_value,ref=OID-Tree +DEFINE signature sequence sequence_of=oid_and_value,ref=@.OID-Tree DEFINE issuer sequence sequence_of=set BEGIN issuer DEFINE RelativeDistinguishedName set set_of=sequence,size=1.. BEGIN RelativeDistinguishedName -DEFINE AttributeTypeAndValue sequence sequence_of=oid_and_value,ref=OID-Tree +DEFINE AttributeTypeAndValue sequence sequence_of=oid_and_value,ref=@.OID-Tree END RelativeDistinguishedName END issuer @@ -32,21 +32,21 @@ DEFINE subject sequence sequence_of=set BEGIN subject DEFINE RelativeDistinguishedName set set_of=sequence,size=1.. BEGIN RelativeDistinguishedName -DEFINE AttributeTypeandValue sequence sequence_of=oid_and_value,ref=OID-Tree +DEFINE AttributeTypeandValue sequence sequence_of=oid_and_value,ref=@.OID-Tree END RelativeDistinguishedName END subject DEFINE subjectPublicKeyInfo sequence BEGIN subjectPublicKeyInfo -DEFINE algorithm sequence sequence_of=oid_and_value,ref=OID-Tree +DEFINE algorithm sequence sequence_of=oid_and_value,ref=@.OID-Tree DEFINE subjectPublicKey bitstring END subjectPublicKeyInfo -DEFINE extensions x509_extensions ref=OID-Tree,size=1.. +DEFINE extensions x509_extensions ref=@.OID-Tree,size=1.. END tbsCertificate -DEFINE signatureAlgorithm sequence sequence_of=oid_and_value,ref=OID-Tree +DEFINE signatureAlgorithm sequence sequence_of=oid_and_value,ref=@.OID-Tree DEFINE signature bitstring END Certificate diff --git a/share/dictionary/dhcpv6/dictionary.rfc3315 b/share/dictionary/dhcpv6/dictionary.rfc3315 index c8f5e2111d1..bc349e8e6bc 100644 --- a/share/dictionary/dhcpv6/dictionary.rfc3315 +++ b/share/dictionary/dhcpv6/dictionary.rfc3315 @@ -41,7 +41,7 @@ MEMBER Address ether # # Server-ID is a clone of Client-ID # -ATTRIBUTE Server-ID 2 struct clone=Client-ID +ATTRIBUTE Server-ID 2 struct clone=@.Client-ID ATTRIBUTE IA-NA 3 struct MEMBER IAID uint32 diff --git a/share/dictionary/dns/dictionary.freeradius.internal b/share/dictionary/dns/dictionary.freeradius.internal index 635f4921b52..f5992576756 100644 --- a/share/dictionary/dns/dictionary.freeradius.internal +++ b/share/dictionary/dns/dictionary.freeradius.internal @@ -10,6 +10,6 @@ VALUE Packet-Type Status-Response 18 VALUE Packet-Type Notify-Response 20 VALUE Packet-Type Update-Response 21 VALUE Packet-Type Stateful-Operation-Response 22 -ATTRIBUTE Packet-Type 1000 uint32 enum=Header.Opcode +ATTRIBUTE Packet-Type 1000 uint32 enum=@.Header.Opcode VALUE Packet-Type Do-Not-Respond 256 diff --git a/share/dictionary/dns/dictionary.rfc1034 b/share/dictionary/dns/dictionary.rfc1034 index 7bfc845394c..5c69631f733 100644 --- a/share/dictionary/dns/dictionary.rfc1034 +++ b/share/dictionary/dns/dictionary.rfc1034 @@ -70,7 +70,7 @@ VALUE Class Any 255 ATTRIBUTE Resource-Record 3 struct MEMBER Name string dns_label MEMBER Type uint16 key -MEMBER Class uint16 enum=Question.Class +MEMBER Class uint16 enum=@.Question.Class MEMBER TTL time_delta ###################################################################### @@ -165,7 +165,7 @@ ATTRIBUTE EDNS0-Tcp-Keepalive .11 uint16 # time_delta in units of 100 millisec ATTRIBUTE Padding .12 octets # Name server RR -ATTRIBUTE Name-Server 4 struct clone=Resource-Record +ATTRIBUTE Name-Server 4 struct clone=@.Resource-Record # additional "glue" RR, or OPT RR for peer signalling -ATTRIBUTE Additional-Record 5 struct clone=Resource-Record +ATTRIBUTE Additional-Record 5 struct clone=@.Resource-Record diff --git a/share/dictionary/freeradius/dictionary.freeradius.internal b/share/dictionary/freeradius/dictionary.freeradius.internal index 0bebfaa2974..62617db2d82 100644 --- a/share/dictionary/freeradius/dictionary.freeradius.internal +++ b/share/dictionary/freeradius/dictionary.freeradius.internal @@ -81,7 +81,7 @@ ATTRIBUTE Net 60 tlv ATTRIBUTE Src .1 tlv ATTRIBUTE IP .1.1 combo-ip ATTRIBUTE Port .1.2 uint16 -ATTRIBUTE Dst .2 tlv clone=Net.Src +ATTRIBUTE Dst .2 tlv clone=.Src ATTRIBUTE Timestamp .3 date # diff --git a/share/dictionary/radius/dictionary.rfc8045 b/share/dictionary/radius/dictionary.rfc8045 index 3e66e09f214..2ff2e6536e6 100644 --- a/share/dictionary/radius/dictionary.rfc8045 +++ b/share/dictionary/radius/dictionary.rfc8045 @@ -25,12 +25,12 @@ ATTRIBUTE Range-Start .9 integer ATTRIBUTE Range-End .10 integer ATTRIBUTE Local-Id .11 string -ATTRIBUTE IP-Port-Range 241.6 tlv clone=Extended-Attribute-1.IP-Port-Limit-Info +ATTRIBUTE IP-Port-Range 241.6 tlv clone=.IP-Port-Limit-Info ATTRIBUTE Range-Start .9 integer ATTRIBUTE Range-End .10 integer ATTRIBUTE Local-Id .11 string -ATTRIBUTE IP-Port-Forwarding-Map 241.7 tlv clone=Extended-Attribute-1.IP-Port-Range +ATTRIBUTE IP-Port-Forwarding-Map 241.7 tlv clone=.IP-Port-Range ALIAS IP-Port-Limit-Info Extended-Attribute-1.IP-Port-Limit-Info ALIAS IP-Port-Range Extended-Attribute-1.IP-Port-Range diff --git a/share/dictionary/radius/dictionary.unisphere b/share/dictionary/radius/dictionary.unisphere index 4a3b4ecf00c..f1a7efefc2f 100644 --- a/share/dictionary/radius/dictionary.unisphere +++ b/share/dictionary/radius/dictionary.unisphere @@ -218,7 +218,7 @@ ATTRIBUTE IPv6-Acct-Input-Gigawords 155 integer ATTRIBUTE IPv6-Acct-Output-Gigawords 156 integer ATTRIBUTE IPv6-NdRa-Pool-Name 157 string ATTRIBUTE PppoE-Padn 158 string -ATTRIBUTE DHCP-Option-82 159 octets # ref=..DHCPv4.Relay-Agent-Information +ATTRIBUTE DHCP-Option-82 159 octets # ref=@.DHCPv4.Relay-Agent-Information ATTRIBUTE Vlan-Map-Id 160 integer ATTRIBUTE IPv6-Delegated-Pool-Name 161 string ATTRIBUTE Tx-Connect-Speed 162 integer diff --git a/src/lib/util/dict_fixup.c b/src/lib/util/dict_fixup.c index fb1a8461058..2ed695797a4 100644 --- a/src/lib/util/dict_fixup.c +++ b/src/lib/util/dict_fixup.c @@ -126,23 +126,25 @@ static inline CC_HINT(always_inline) int dict_fixup_common(fr_dlist_head_t *fixu return 0; } -/** Resolve a ref= or copy= value to a dictionary */ - /** Resolve a reference string to a dictionary attribute * + * @param[out] da_p Where the attribute will be stored * @param[in] rel Relative attribute to resolve from. * @param[in] ref Reference string. - * @param[in] absolute_root If true, and there is no '.' prefix, searching will begin from - * the root of the dictionary, else we pretend there was a '.' and - * search from rel. + * @return + * - <0 on error + * - 0 on parse OK, but *da_p is NULL; + * - 1 for parse OK, and *da_p is !NULL */ -fr_dict_attr_t const *dict_protocol_reference(fr_dict_attr_t const *rel, char const *ref, bool absolute_root) +int dict_protocol_reference(fr_dict_attr_t const **da_p, fr_dict_attr_t const *rel, char const *ref) { fr_dict_t *dict = fr_dict_unconst(rel->dict); - fr_dict_attr_t const *da = rel, *found; + fr_dict_attr_t const *da = rel; ssize_t slen; fr_sbuff_t sbuff = FR_SBUFF_IN(ref, strlen(ref)); + *da_p = NULL; + /* * Are we resolving a foreign reference? */ @@ -150,6 +152,18 @@ fr_dict_attr_t const *dict_protocol_reference(fr_dict_attr_t const *rel, char co char proto_name[FR_DICT_ATTR_MAX_NAME_LEN + 1]; fr_sbuff_t proto_name_sbuff = FR_SBUFF_OUT(proto_name, sizeof(proto_name)); + /* + * @.foo is "foo from the current root". + * + * This is a bit clearer than "foo". + */ + if (fr_sbuff_next_if_char(&sbuff, '.')) { + if (fr_sbuff_is_char(&sbuff, '.')) goto above_root; + + da = rel->dict->root; + goto more; + } + slen = dict_by_protocol_substr(NULL, &dict, &sbuff, NULL); /* Need to load it... */ if (slen <= 0) { @@ -161,7 +175,7 @@ fr_dict_attr_t const *dict_protocol_reference(fr_dict_attr_t const *rel, char co &FR_SBUFF_TERMS(L(""), L(".")), NULL) <= 0) { invalid_name: fr_strerror_const("Invalid protocol name"); - return NULL; + return -1; } /* @@ -181,48 +195,60 @@ fr_dict_attr_t const *dict_protocol_reference(fr_dict_attr_t const *rel, char co * Load the new dictionary, and mark it as loaded from our dictionary. */ if (fr_dict_protocol_afrom_file(&dict, proto_name, NULL, (rel->dict)->root->name) < 0) { - return NULL; + return -1; } if (!fr_hash_table_insert((rel->dict)->autoref, dict)) { fr_strerror_const("Failed inserting into internal autoref table"); - return NULL; + return -1; } } /* * Didn't stop at an attribute ref... we're done */ - if (!fr_sbuff_next_if_char(&sbuff, '.')) { - return dict->root; + if (fr_sbuff_eof(&sbuff)) { + *da_p = dict->root; + return 1; } da = dict->root; } + if (!fr_sbuff_next_if_char(&sbuff, '.')) { + fr_strerror_printf("Attribute %s has reference '%s' which does not begin with '.' or '@'", + rel->name, ref); + return -1; + } + /* * First '.' makes it reletive, subsequent ones traverse up the tree. * * No '.' means use the root. */ - if (fr_sbuff_next_if_char(&sbuff, '.')) { - while (fr_sbuff_next_if_char(&sbuff, '.')) { - if (!da->parent) { - fr_strerror_const("Reference attempted to navigate above dictionary root"); - return NULL; - } - da = da->parent; + while (fr_sbuff_next_if_char(&sbuff, '.')) { + if (!da->parent) { + above_root: + fr_strerror_const("Reference attempted to navigate above dictionary root"); + return -1; } - } else { - da = absolute_root ? dict->root : rel; + da = da->parent; } /* - * Look up the attribute. + * Look up the attribute. Note that this call will + * update *da_p with a partial reference if it exists. */ - if (fr_dict_attr_by_oid_substr(NULL, &found, da, &sbuff, NULL) <= 0) return NULL; +more: + slen = fr_dict_attr_by_oid_substr(NULL, da_p, da, &sbuff, NULL); + if (slen < 0) return -1; + + if (slen == 0) { + *da_p = NULL; + return 0; + } - return found; + return 1; } /** Add an enumeration value to an attribute which has not yet been defined @@ -357,7 +383,7 @@ static inline CC_HINT(always_inline) int dict_fixup_group_apply(UNUSED dict_fixu { fr_dict_attr_t const *da; - da = dict_protocol_reference(fixup->da->parent, fixup->ref, true); + (void) dict_protocol_reference(&da, fixup->da->parent, fixup->ref); if (!da) { fr_strerror_printf_push("Failed resolving reference for attribute at %s[%d]", fr_cwd_strip(fixup->da->filename), fixup->da->line); @@ -580,7 +606,7 @@ static inline CC_HINT(always_inline) int dict_fixup_clone_apply(UNUSED dict_fixu { fr_dict_attr_t const *src; - src = dict_protocol_reference(fixup->da->parent, fixup->ref, true); + (void) dict_protocol_reference(&src, fixup->da->parent, fixup->ref); if (!src) { fr_strerror_printf_push("Failed resolving reference for attribute at %s[%d]", fr_cwd_strip(fixup->da->filename), fixup->da->line); @@ -639,7 +665,7 @@ static inline CC_HINT(always_inline) int dict_fixup_clone_enum_apply(UNUSED dict fr_dict_attr_t const *src; int copied; - src = dict_protocol_reference(fixup->da->parent, fixup->ref, true); + (void) dict_protocol_reference(&src, fixup->da->parent, fixup->ref); if (!src) { fr_strerror_printf_push("Failed resolving reference for attribute at %s[%d]", fr_cwd_strip(fixup->da->filename), fixup->da->line); diff --git a/src/lib/util/dict_fixup_priv.h b/src/lib/util/dict_fixup_priv.h index 94e0688b5c2..71067206747 100644 --- a/src/lib/util/dict_fixup_priv.h +++ b/src/lib/util/dict_fixup_priv.h @@ -40,7 +40,7 @@ typedef struct { fr_dlist_head_t alias; //!< Aliases that can't be resolved immediately. } dict_fixup_ctx_t; -fr_dict_attr_t const *dict_protocol_reference(fr_dict_attr_t const *root, char const *ref, bool absolute_root); +int dict_protocol_reference(fr_dict_attr_t const **da_p, fr_dict_attr_t const *root, char const *ref); int dict_fixup_enumv_enqueue(dict_fixup_ctx_t *fctx, char const *filename, int line, char const *attr, size_t attr_len, diff --git a/src/lib/util/dict_tokenize.c b/src/lib/util/dict_tokenize.c index cb2abefc814..8762fbe637e 100644 --- a/src/lib/util/dict_tokenize.c +++ b/src/lib/util/dict_tokenize.c @@ -857,7 +857,8 @@ static int dict_attr_add_or_fixup(dict_fixup_ctx_t *fixup, fr_dict_attr_t **da_p /* * IF the ref exists, we can always add it. The ref won't be changed later. */ - src = dict_protocol_reference(da->parent, ref->unresolved, true); + if (dict_protocol_reference(&src, da->parent, ref->unresolved) < 0) return -1; + if (src) { if (dict_attr_ref_set(*da_p, src, FR_DICT_ATTR_REF_ALIAS) < 0) return -1; break; @@ -882,7 +883,7 @@ static int dict_attr_add_or_fixup(dict_fixup_ctx_t *fixup, fr_dict_attr_t **da_p * @todo - if we defer this clone, we get errors loading dictionary.wimax. That * likely means there are issues with the dict_fixup_clone_apply() function. */ - src = dict_protocol_reference(da->parent, ref->unresolved, true); + if (dict_protocol_reference(&src, da->parent, ref->unresolved) < 0) return -1; if (src) { if (dict_fixup_clone(da_p, src) < 0) return -1; break; diff --git a/src/tests/unit/protocols/der/dictionary.test b/src/tests/unit/protocols/der/dictionary.test index fe2bb4cbd51..1abac7303d6 100644 --- a/src/tests/unit/protocols/der/dictionary.test +++ b/src/tests/unit/protocols/der/dictionary.test @@ -2,13 +2,13 @@ # Copyright (C) 2025 The FreeRADIUS Server project and contributors # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 # Version $Id$ -DEFINE Certificate-Extensions x509_extensions ref=OID-Tree +DEFINE Certificate-Extensions x509_extensions ref=@.OID-Tree DEFINE Issuer sequence sequence_of=set BEGIN Issuer DEFINE RelativeDistinguishedName set set_of=sequence,size=1.. BEGIN RelativeDistinguishedName -DEFINE AttributeTypeAndValue sequence sequence_of=oid_and_value,ref=OID-Tree +DEFINE AttributeTypeAndValue sequence sequence_of=oid_and_value,ref=@.OID-Tree END RelativeDistinguishedName END Issuer @@ -16,7 +16,7 @@ DEFINE Issuer-Set set set_of=set BEGIN Issuer-Set DEFINE RelativeDistinguishedName set set_of=sequence,size=1.. BEGIN RelativeDistinguishedName -DEFINE AttributeTypeAndValue sequence sequence_of=oid_and_value,ref=OID-Tree +DEFINE AttributeTypeAndValue sequence sequence_of=oid_and_value,ref=@.OID-Tree END RelativeDistinguishedName END Issuer-Set @@ -30,7 +30,7 @@ BEGIN Test-Set-Of DEFINE Test-First-Integer integer END Test-Set-Of -DEFINE Test-Set-Of-Group group ref=Test-Set-Of,der_type=set,set_of=integer +DEFINE Test-Set-Of-Group group ref=@.Test-Set-Of,der_type=set,set_of=integer DEFINE Test-Boolean bool @@ -159,7 +159,7 @@ DEFINE Test-Integer integer DEFINE Test-Boolean bool END Test-TLV -DEFINE Test-Sequence-GROUP group der_type=sequence,ref=Test-TLV +DEFINE Test-Sequence-GROUP group der_type=sequence,ref=@.Test-TLV DEFINE Test-Set-Struct set BEGIN Test-Set-Struct @@ -179,4 +179,4 @@ DEFINE Test-Integer integer DEFINE Test-Boolean bool END Test-Set-TLV -DEFINE Test-Set-GROUP group der_type=set,ref=Test-TLV +DEFINE Test-Set-GROUP group der_type=set,ref=@.Test-TLV diff --git a/src/tests/unit/protocols/dhcpv6/dictionary b/src/tests/unit/protocols/dhcpv6/dictionary index 17d83493611..149bf435068 100644 --- a/src/tests/unit/protocols/dhcpv6/dictionary +++ b/src/tests/unit/protocols/dhcpv6/dictionary @@ -4,6 +4,6 @@ ATTRIBUTE test-tlv 6809 tlv ATTRIBUTE child1 .1 uint32 ATTRIBUTE child2 .2 uint32 -ATTRIBUTE test-group 6810 group ref=test-tlv +ATTRIBUTE test-group 6810 group ref=@.test-tlv END-PROTOCOL DHCPv6 diff --git a/src/tests/unit/protocols/internal/dictionary.test b/src/tests/unit/protocols/internal/dictionary.test index 56547d40d5a..2cec10ded67 100644 --- a/src/tests/unit/protocols/internal/dictionary.test +++ b/src/tests/unit/protocols/internal/dictionary.test @@ -45,10 +45,10 @@ ATTRIBUTE Delta-Sec-uint32 254.9 time_delta precision=seconds,subtype=uint32 ATTRIBUTE Delta-MSec-int32 254.10 time_delta precision=milliseconds,subtype=int32 ATTRIBUTE Delta-Sec-int32 254.11 time_delta precision=seconds,subtype=int32 -ATTRIBUTE Test-Enum-Integer64 254.12 uint64 enum=base-enum-uint64 +ATTRIBUTE Test-Enum-Integer64 254.12 uint64 enum=@.base-enum-uint64 # and this casting should work -ATTRIBUTE Test-Enum-Integer32 254.13 uint32 enum=base-enum-uint64 +ATTRIBUTE Test-Enum-Integer32 254.13 uint32 enum=@.base-enum-uint64 # # Copied here for simplicity diff --git a/src/tests/unit/protocols/radius/dictionary.test b/src/tests/unit/protocols/radius/dictionary.test index 1bea820520f..149af171445 100644 --- a/src/tests/unit/protocols/radius/dictionary.test +++ b/src/tests/unit/protocols/radius/dictionary.test @@ -50,10 +50,10 @@ ATTRIBUTE Delta-Sec-uint32 254.9 time_delta precision=seconds,subtype=uint32 ATTRIBUTE Delta-MSec-int32 254.10 time_delta precision=milliseconds,subtype=int32 ATTRIBUTE Delta-Sec-int32 254.11 time_delta precision=seconds,subtype=int32 -ATTRIBUTE Test-Enum-Integer64 254.12 uint64 enum=base-enum-uint64 +ATTRIBUTE Test-Enum-Integer64 254.12 uint64 enum=@.base-enum-uint64 # and this casting should work -ATTRIBUTE Test-Enum-Integer32 254.13 uint32 enum=base-enum-uint64 +ATTRIBUTE Test-Enum-Integer32 254.13 uint32 enum=@.base-enum-uint64 VENDOR FreeRADIUS 11344 BEGIN-Vendor FreeRADIUS parent=.Extended-Attribute-2.Extended-Vendor-Specific-2