From: Alan T. DeKok Date: Sat, 8 Jul 2023 19:44:50 +0000 (-0400) Subject: add pair_afrom_da_nested() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a7e5b8a1fe0e9bc6fd89c69e7a064e59d2bb42b0;p=thirdparty%2Ffreeradius-server.git add pair_afrom_da_nested() which is similar to fr_pair_update_by_da_parent(), except that function takes a parent pair. In some cases, we need to use separate TALLOC_CTX and fr_pair_list_t. --- diff --git a/src/lib/util/pair.c b/src/lib/util/pair.c index 632a53a65af..1b1dcedbee1 100644 --- a/src/lib/util/pair.c +++ b/src/lib/util/pair.c @@ -447,6 +447,59 @@ fr_pair_t *fr_pair_afrom_child_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent return vp; } +/** Create a pair (and all intermediate parents), and append it to the list + * + * If the relevant leaf pair already exists, then a new one is created. + * + * This function is similar to fr_pair_update_by_da_parent(), except that function requires + * a parent pair, and this one takes a separate talloc ctx and pair list. + * + * @param[in] ctx for allocated memory, usually a pointer to a #fr_radius_packet_t. + * @param[out] list where the created pair is supposed to go. + * @param[in] da the da for the pair to create + * @return + * - A new #fr_pair_t. + * - NULL on error. + */ +fr_pair_t *fr_pair_afrom_da_nested(TALLOC_CTX *ctx, fr_pair_list_t *list, fr_dict_attr_t const *da) +{ + fr_pair_t *vp; + unsigned int i; + TALLOC_CTX *cur_ctx; + fr_dict_attr_t const *find; /* DA currently being looked for */ + fr_pair_list_t *cur_list; /* Current list being searched */ + fr_da_stack_t da_stack; + + if (da->depth <= 1) { + if (fr_pair_append_by_da(ctx, &vp, list, da) < 0) return NULL; + return vp; + } + + fr_proto_da_stack_build(&da_stack, da); + cur_list = list; + cur_ctx = ctx; + + for (i = 0; i <= da->depth; i++) { + find = da_stack.da[i]; + + vp = fr_pair_find_by_da(cur_list, NULL, find); + if (!vp || (vp->da == da)) { + if (fr_pair_append_by_da(cur_ctx, &vp, cur_list, find) < 0) return NULL; + } + + if (find == da) return vp; + + fr_assert(fr_type_is_structural(vp->da->type)); + + cur_ctx = vp; + cur_list = &vp->vp_group; + } + + fr_assert(0); + + return NULL; +} + /** Copy a single valuepair * * Allocate a new valuepair and copy the da from the old vp. diff --git a/src/lib/util/pair.h b/src/lib/util/pair.h index 67665efbffd..62976c0c050 100644 --- a/src/lib/util/pair.h +++ b/src/lib/util/pair.h @@ -438,6 +438,8 @@ int fr_pair_reinit_from_da(fr_pair_list_t *list, fr_pair_t *vp, fr_dict_attr_t fr_pair_t *fr_pair_afrom_child_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int attr) CC_HINT(warn_unused_result); +fr_pair_t *fr_pair_afrom_da_nested(TALLOC_CTX *ctx, fr_pair_list_t *list, fr_dict_attr_t const *da) CC_HINT(warn_unused_result) CC_HINT(nonnull(2,3)); + fr_pair_t *fr_pair_copy(TALLOC_CTX *ctx, fr_pair_t const *vp) CC_HINT(nonnull(2)) CC_HINT(warn_unused_result); int fr_pair_steal(TALLOC_CTX *ctx, fr_pair_t *vp) CC_HINT(nonnull); diff --git a/src/lib/util/pair_tests.c b/src/lib/util/pair_tests.c index 447cc54f64e..6a1d58533b4 100644 --- a/src/lib/util/pair_tests.c +++ b/src/lib/util/pair_tests.c @@ -127,6 +127,35 @@ static void test_fr_pair_afrom_child_num(void) talloc_free(vp); } +static void test_fr_pair_afrom_da_nested(void) +{ + fr_pair_t *vp, *parent = NULL; + fr_pair_list_t local_pairs; + + fr_pair_list_init(&local_pairs); + + TEST_CASE("Allocation using fr_pair_afrom_da_nested"); + TEST_CHECK((vp = fr_pair_afrom_da_nested(autofree, &local_pairs, fr_dict_attr_test_tlv_string)) != NULL); + + TEST_CHECK(vp && vp->da == fr_dict_attr_test_tlv_string); + TEST_MSG("Expected attr(%s) == vp->da->attr(%s)", fr_dict_attr_test_tlv_string->name, vp->da->name); + + TEST_CASE("Validating PAIR_VERIFY()"); + PAIR_VERIFY(vp); + + TEST_CASE("Top list does not have the tlv child attribute"); + TEST_CHECK(fr_pair_find_by_da(&local_pairs, NULL, fr_dict_attr_test_tlv_string) == NULL); + + TEST_CASE("Top list does have the tlv attribute"); + parent = fr_pair_find_by_da(&local_pairs, NULL, fr_dict_attr_test_tlv); + TEST_CHECK(parent != NULL); + + TEST_CASE("Parent list does have the tlv child attribute"); + TEST_CHECK(fr_pair_find_by_da(&parent->vp_group, NULL, fr_dict_attr_test_tlv_string) == vp); + + talloc_free(parent); /* not vp! */ +} + static void test_fr_pair_copy(void) { fr_pair_t *vp, *copy; @@ -1354,6 +1383,7 @@ TEST_LIST = { */ { "fr_pair_afrom_da", test_fr_pair_afrom_da }, { "fr_pair_afrom_child_num", test_fr_pair_afrom_child_num }, + { "fr_pair_afrom_da_nested", test_fr_pair_afrom_da_nested }, { "fr_pair_copy", test_fr_pair_copy }, { "fr_pair_steal", test_fr_pair_steal },