From: Alan T. DeKok Date: Fri, 25 Nov 2022 18:29:14 +0000 (-0500) Subject: Allow dictionaries to depend on each other X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=166f9ee217f9a595c51c1bb37bc2f9a75cd0d9e7;p=thirdparty%2Ffreeradius-server.git Allow dictionaries to depend on each other and add API to see if the dictionaries are compatible. Because we can no longer depend on comparing pointers --- diff --git a/src/lib/server/tmpl_tokenize.c b/src/lib/server/tmpl_tokenize.c index 8a3ad962672..e93ca00cde6 100644 --- a/src/lib/server/tmpl_tokenize.c +++ b/src/lib/server/tmpl_tokenize.c @@ -1824,7 +1824,7 @@ check_attr: * |_ RADIUS attribute */ if (found_in != fr_dict_internal() && - !at_rules->allow_foreign && (found_in != fr_dict_by_da(our_parent))) { + !at_rules->allow_foreign && !fr_dict_compatible(found_in, fr_dict_by_da(our_parent))) { fr_strerror_printf("Foreign %s attribute found. Only %s attributes are allowed here", fr_dict_root(found_in)->name, fr_dict_root(dict_def)->name); diff --git a/src/lib/unlang/compile.c b/src/lib/unlang/compile.c index 9e67346f8e8..fc6f9e50813 100644 --- a/src/lib/unlang/compile.c +++ b/src/lib/unlang/compile.c @@ -4731,8 +4731,8 @@ static unlang_t *compile_module(unlang_t *parent, unlang_compile_t *unlang_ctx, */ if (mrlm->dict && *mrlm->dict && unlang_ctx->rules && unlang_ctx->rules->attr.dict_def && (unlang_ctx->rules->attr.dict_def != fr_dict_internal()) && - (*(mrlm->dict) != unlang_ctx->rules->attr.dict_def)) { - cf_log_err(ci, "The \"%s\" module can only used with 'namespace = %s'. It cannot be used with 'namespace = %s'.", + !fr_dict_compatible(*(mrlm->dict), unlang_ctx->rules->attr.dict_def)) { + cf_log_err(ci, "The \"%s\" module can only be used with 'namespace = %s'. It cannot be used with 'namespace = %s'.", inst->module->name, fr_dict_root(*mrlm->dict)->name, fr_dict_root(unlang_ctx->rules->attr.dict_def)->name); diff --git a/src/lib/util/dict.h b/src/lib/util/dict.h index d3025549892..122e6f52875 100644 --- a/src/lib/util/dict.h +++ b/src/lib/util/dict.h @@ -500,6 +500,8 @@ fr_dict_t const *fr_dict_by_da(fr_dict_attr_t const *da) CC_HINT(nonnull); fr_dict_t const *fr_dict_by_attr_name(fr_dict_attr_t const **found, char const *name); +bool fr_dict_compatible(fr_dict_t const *dict1, fr_dict_t const *dict2) CC_HINT(nonnull); + /** Return true if this attribute is parented directly off the dictionary root * * @param[in] da to check. diff --git a/src/lib/util/dict_priv.h b/src/lib/util/dict_priv.h index edb543ea78b..2af25cb9c9a 100644 --- a/src/lib/util/dict_priv.h +++ b/src/lib/util/dict_priv.h @@ -91,6 +91,8 @@ struct fr_dict { fr_hash_table_t *autoref; //!< other dictionaries that we loaded via references + fr_dict_t const *next; //!< for attribute overloading + fr_table_num_ordered_t const *subtype_table; //!< table of subtypes for this protocol size_t subtype_table_len; //!< length of table of subtypes for this protocol diff --git a/src/lib/util/dict_util.c b/src/lib/util/dict_util.c index f72f9397d07..5117acb4a95 100644 --- a/src/lib/util/dict_util.c +++ b/src/lib/util/dict_util.c @@ -2182,6 +2182,23 @@ fr_dict_t const *fr_dict_by_da(fr_dict_attr_t const *da) return dict_by_da(da); } +/** See if two dictionaries have the same end parent + * + * @param[in] dict1 one dictionary + * @param[in] dict2 two dictionary + * @return + * - true the dictionaries have the same end parent + * - false the dictionaries do not have the same end parent. + */ +bool fr_dict_compatible(fr_dict_t const *dict1, fr_dict_t const *dict2) +{ + while (dict1->next) dict1 = dict1->next; + + while (dict2->next) dict2 = dict2->next; + + return (dict1 == dict2); +} + /** Look up a vendor by one of its child attributes * * @param[in] da The vendor attribute.