]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Require '.' or '@' in references
authorAlan T. DeKok <aland@freeradius.org>
Sun, 23 Feb 2025 11:33:42 +0000 (06:33 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Sun, 23 Feb 2025 12:18:51 +0000 (07:18 -0500)
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.

25 files changed:
doc/antora/modules/reference/nav.adoc
doc/antora/modules/reference/pages/dictionary/attribute.adoc
doc/antora/modules/reference/pages/dictionary/define.adoc
doc/antora/modules/reference/pages/dictionary/enum.adoc
doc/antora/modules/reference/pages/dictionary/member.adoc
doc/antora/modules/reference/pages/dictionary/reference.adoc [new file with mode: 0644]
share/dictionary/der/dictionary
share/dictionary/der/dictionary.common
share/dictionary/der/dictionary.crl
share/dictionary/der/dictionary.extensions
share/dictionary/der/dictionary.rfc2986
share/dictionary/der/dictionary.rfc5280
share/dictionary/dhcpv6/dictionary.rfc3315
share/dictionary/dns/dictionary.freeradius.internal
share/dictionary/dns/dictionary.rfc1034
share/dictionary/freeradius/dictionary.freeradius.internal
share/dictionary/radius/dictionary.rfc8045
share/dictionary/radius/dictionary.unisphere
src/lib/util/dict_fixup.c
src/lib/util/dict_fixup_priv.h
src/lib/util/dict_tokenize.c
src/tests/unit/protocols/der/dictionary.test
src/tests/unit/protocols/dhcpv6/dictionary
src/tests/unit/protocols/internal/dictionary.test
src/tests/unit/protocols/radius/dictionary.test

index 282766e9c6f2d3ae1015db51294adbd19cfe2dd1..9e4c37f1189f247023fc46d56f569891edde4e62 100644 (file)
@@ -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]
index e17291e80b9a99b5ab05c9dbe4afc534069d9f12..c6bed49b21c5e26e3b155d9e6bed1b130ec4a18a 100644 (file)
@@ -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 `<ref>` field in the examples above is an attribute references such as `Foo`, or `Foo.Bar`, or `@dhcpv4.foo.bar`.  All `<ref>` 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.
index e532beb87d5d660eb51ca3ed730058875d797028..1d52fff68650ab1d3f43da1debea6d21728f104c 100644 (file)
@@ -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=<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
index 152d7ad855c236cdcb7d3f1ff4bbec0182d341b7..e8d6f2272a33b88284cef360ad120df689071032 100644 (file)
@@ -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.
index e686c01ccaec99f297ef939131943be470f933bb..49cde0db249784b9215ea723d6cf253a7234fbc1 100644 (file)
@@ -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 (file)
index 0000000..0b1fdef
--- /dev/null
@@ -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=<ref>`  | For `tlv` or 'struct' types, clone (or copy) child definitions from another attribute of the same type
+| `enum=<ref>`   | For "leaf" types, copy xref:dictionary/value.adoc[VALUE]s from an xref:dictionary/enum.adoc[ENUM] or other attribute.
+| `ref=<ref>`    | For `group` types, the referenced attributes will be allowed in the group
+|=====
+
+All `<ref>` 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.
index ca6796b63dfd15120e8dd3cc1079e8e0d3b67199..0b47226a1e1436407ef7aafd6eb41276b5dd11f4 100644 (file)
@@ -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
 
index c0f3049b7e0c4d36199078a59328a5e89af46b20..b41848d28a19d4222546c559b11e9fdad6b81ba8 100644 (file)
@@ -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
index 63d5572a9721248042e27460584736357c16d391..382e6a8dc2f2a4984d572d19ed3bbe9696a7627b 100644 (file)
@@ -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
index 51f46a59443499b35f35bd3d303ff73f80548b97..3ff3240536c6f6c3b1cd920a799f6eb16900d79c 100644 (file)
@@ -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
 
index 6affcb534fa834795bd775bc4caf62c45daf8b88..1075467ca6f65e5a9ace122c044277969f1eb513 100644 (file)
@@ -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
 
index 0b2674e51b78a2d9f5e3c9ca14e1193f01f31f49..424f970ae7b46e091c0aeb464ca2efc7407c88a2 100644 (file)
@@ -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
index c8f5e2111d14eb0b9ba5b3109f3624c1d04e4405..bc349e8e6bc61a24f1b18069c29d05584bd83d06 100644 (file)
@@ -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
index 635f4921b5205ec3e475428b4057d6c8572f7fb6..f5992576756145c9ce4424686422fe3bcec9ec46 100644 (file)
@@ -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
index 7bfc845394c26f45d69913f5c3013687083e4e26..5c69631f7331d349b24c3984ca423e49b843e5f6 100644 (file)
@@ -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
index 0bebfaa2974b52a2ce47862dd1a444bdd424debf..62617db2d82502178c14bc9e349335601b47e249 100644 (file)
@@ -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
 
 #
index 3e66e09f214ae0af8a8952ab78fdc48e24665173..2ff2e6536e6306c91325fc2064e65f5d54a56bd0 100644 (file)
@@ -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
index 4a3b4ecf00c2f181da73aa86b05661de825f3587..f1a7efefc2fd9da4eadd1d7948ffe1ad216b8488 100644 (file)
@@ -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
index fb1a84610588311b4d049227082f32e85a0271ee..2ed695797a41fdad18224569a2b32cac9b7f078d 100644 (file)
@@ -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);
index 94e0688b5c2e5a71db35abe4f5fe8a62679fd722..71067206747e03494b1ecb239050e6a98c12bb84 100644 (file)
@@ -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,
index cb2abefc814e7be539bd87e4a67ce1ffd4da108c..8762fbe637e69f343658ca578af00d51ebc662c2 100644 (file)
@@ -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;
index fe2bb4cbd51315ea0ffaf5758ff88870ee3bcedb..1abac7303d6ee6435c8e6869e19c73ed58a86ae2 100644 (file)
@@ -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
index 17d83493611e8cf60f4b02609fbb2528cf779dbc..149bf4350683a383fe3452cd263a5674717fe102 100644 (file)
@@ -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
index 56547d40d5af9a3924f1c7b536d314bfb10daddb..2cec10ded67046033de26e8a8e622235cfef92ac 100644 (file)
@@ -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
index 1bea820520fe5d4b7eb637dc449ae2a2b1cc7f48..149af1714455d3f2f2c59123022d470f0535ba44 100644 (file)
@@ -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