From 9200a8f39a71d50cef4d2783f20229af4cb16f27 Mon Sep 17 00:00:00 2001 From: "Alan T. DeKok" Date: Thu, 5 Dec 2024 15:30:47 -0500 Subject: [PATCH] Better handle group refs to somewhere in the middle of the tree --- .../reference/pages/type/all_types.adoc | 6 ++- src/lib/util/pair_print.c | 25 +++++----- src/tests/unit/protocols/dhcpv6/dictionary | 49 ++----------------- src/tests/unit/protocols/dhcpv6/group-tlv.txt | 30 ++++++++++++ 4 files changed, 52 insertions(+), 58 deletions(-) create mode 100644 src/tests/unit/protocols/dhcpv6/group-tlv.txt diff --git a/doc/antora/modules/reference/pages/type/all_types.adoc b/doc/antora/modules/reference/pages/type/all_types.adoc index 3e5392870d2da..4587de9d53e94 100644 --- a/doc/antora/modules/reference/pages/type/all_types.adoc +++ b/doc/antora/modules/reference/pages/type/all_types.adoc @@ -78,6 +78,10 @@ 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 +the same protocol dictionary, or to a different protocol dictionary. +The `group` allows for dictionaries to contain cross-references. ++ The `group` can contain any child attributes, so long as they are within the same protocol namespace. See the dictionary/attribute.adoc[ATTRIBUTE] documentation for more @@ -86,7 +90,7 @@ information. The `group` only encodes the child attributes which have been created and stored within the `group`. The order of children does not matter. -tlv:: A `tlv` is a `group` which has a limited subset of children. +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 children of the `tlv.` diff --git a/src/lib/util/pair_print.c b/src/lib/util/pair_print.c index dac3d1a80d1c5..667ac1c28012f 100644 --- a/src/lib/util/pair_print.c +++ b/src/lib/util/pair_print.c @@ -14,6 +14,16 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +/* + * Groups are printed from the referenced attribute. + */ +#define fr_pair_reset_parent(parent) do { \ + if (parent && (parent->type == FR_TYPE_GROUP)) { \ + parent = fr_dict_attr_ref(parent); \ + if (parent->flags.is_root) parent = NULL; \ + } \ + } while (0) + /** Pair serialisation API * * @file src/lib/util/pair_print.c @@ -114,10 +124,7 @@ ssize_t fr_pair_print(fr_sbuff_t *out, fr_dict_attr_t const *parent, fr_pair_t c token = ""; } - /* - * Groups are printed from the root. - */ - if (parent && (parent->type == FR_TYPE_GROUP)) parent = NULL; + fr_pair_reset_parent(parent); if (vp->vp_raw) FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "raw."); FR_DICT_ATTR_OID_PRINT_RETURN(&our_out, parent, vp->da, false); @@ -176,10 +183,7 @@ ssize_t fr_pair_print_secure(fr_sbuff_t *out, fr_dict_attr_t const *parent, fr_p token = ""; } - /* - * Groups are printed from the root. - */ - if (parent && (parent->type == FR_TYPE_GROUP)) parent = NULL; + fr_pair_reset_parent(parent); if (vp->vp_raw) FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "raw."); FR_DICT_ATTR_OID_PRINT_RETURN(&our_out, parent, vp->da, false); @@ -241,10 +245,7 @@ ssize_t fr_pair_list_print(fr_sbuff_t *out, fr_dict_attr_t const *parent, fr_pai return fr_sbuff_used(out); } - /* - * Groups are printed from the root. - */ - if (parent && (parent->type == FR_TYPE_GROUP)) parent = NULL; + fr_pair_reset_parent(parent); while (true) { FR_SBUFF_RETURN(fr_pair_print, &our_out, parent, vp); diff --git a/src/tests/unit/protocols/dhcpv6/dictionary b/src/tests/unit/protocols/dhcpv6/dictionary index 1e244109e988b..17d83493611e8 100644 --- a/src/tests/unit/protocols/dhcpv6/dictionary +++ b/src/tests/unit/protocols/dhcpv6/dictionary @@ -1,50 +1,9 @@ BEGIN PROTOCOL DHCPv6 3 -# -# Basic options needed by the DHCPv6 pair encoder and decoder -# -ATTRIBUTE Packet-Type 65536 uint32 internal -ATTRIBUTE Transaction-ID 65537 uint32 internal +ATTRIBUTE test-tlv 6809 tlv +ATTRIBUTE child1 .1 uint32 +ATTRIBUTE child2 .2 uint32 -ATTRIBUTE Option-Request 65535 uint16 array # Magic option listing requested options - -# -# Test attributes -# -ATTRIBUTE Test-string 1 string -ATTRIBUTE Test-octets 2 octets - -ATTRIBUTE Test-ipaddr 3 ipaddr -ATTRIBUTE Test-ipv4addr 4 ipv4addr -ATTRIBUTE Test-ipv4prefix 5 ipv4prefix -ATTRIBUTE Test-ipv6addr 6 ipv6addr -ATTRIBUTE Test-ipv6prefix 7 ipv6prefix -ATTRIBUTE Test-ifid 8 ifid -ATTRIBUTE Test-ether 11 ether - -ATTRIBUTE Test-bool 12 bool - -ATTRIBUTE Test-uint8 13 uint8 -ATTRIBUTE Test-uint16 14 uint16 -ATTRIBUTE Test-uint32 15 uint32 -ATTRIBUTE Test-uint64 16 uint64 - -ATTRIBUTE Test-int8 17 int8 -ATTRIBUTE Test-int16 18 int16 -ATTRIBUTE Test-int32 19 int32 -ATTRIBUTE Test-int64 20 int64 - -ATTRIBUTE Test-float32 21 float32 - -ATTRIBUTE Test-time-delta 23 time_delta -ATTRIBUTE Test-date 24 date - -ATTRIBUTE Test-size 26 size - -ATTRIBUTE Test-tlv 27 tlv -ATTRIBUTE Test-struct 28 struct - -ATTRIBUTE Test-vsa 30 vsa -ATTRIBUTE Test-group 32 group +ATTRIBUTE test-group 6810 group ref=test-tlv END-PROTOCOL DHCPv6 diff --git a/src/tests/unit/protocols/dhcpv6/group-tlv.txt b/src/tests/unit/protocols/dhcpv6/group-tlv.txt new file mode 100644 index 0000000000000..861369ccd6507 --- /dev/null +++ b/src/tests/unit/protocols/dhcpv6/group-tlv.txt @@ -0,0 +1,30 @@ +# -*- text -*- +# Copyright (C) 2019 Network RADIUS SARL (legal@networkradius.com) +# This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 +# +# Version $Id$ +# + +proto dhcpv6 +proto-dictionary dhcpv6 +load-dictionary dictionary +fuzzer-out dhcpv6 + +pair test-group = { child1 = 1 } +match test-group = { child1 = 1 } + + +encode-pair test-group = { child1 = 1 } +match 1a 9a 00 0c 1a 99 00 08 00 01 00 04 00 00 00 01 + +# +# Yeah, this is wrong. The decoder can only handle group refs which +# point to the top of the tree. +# +# @todo - fix it! +# +decode-pair - +match test-group = { = { child1 = 1 } } + +count +match 10