]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add function to check for "da can contain other da"
authorAlan T. DeKok <aland@freeradius.org>
Fri, 10 Feb 2023 20:34:00 +0000 (15:34 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Sat, 11 Feb 2023 13:00:14 +0000 (08:00 -0500)
really for fr_pair_t validation, but it's still useful to have a
sanity check function in the dictionary code.

src/lib/util/dict.h
src/lib/util/dict_util.c
src/lib/util/pair.c

index 12709aa98c0624df42d0a86b81ec3e1e68cb2b55..dcce2e6ae35ece857aa9655c027958c0237ff5ee 100644 (file)
@@ -470,6 +470,8 @@ fr_dict_attr_t const        *fr_dict_attr_by_oid(fr_dict_attr_err_t *err,
 
 bool                   fr_dict_attr_compatible(fr_dict_attr_t const *a, fr_dict_attr_t const *b) CC_HINT(nonnull);
 
+bool                   fr_dict_attr_can_contain(fr_dict_attr_t const *parent, fr_dict_attr_t const *child) CC_HINT(nonnull);
+
 /** @} */
 
 /** @name Attribute, vendor and dictionary lookup
index 89030f869994859c0a39e72404643444a269ad47..9bf38a836f307d5e1b9fdc0342dc877bbb883d59 100644 (file)
@@ -4304,3 +4304,63 @@ bool fr_dict_attr_compatible(fr_dict_attr_t const *a, fr_dict_attr_t const *b)
 
        return (a == b);
 }
+
+/** See if a structural da is allowed to contain another da
+ *
+ *  We have some complex rules with different structural types,
+ *  different protocol dictionaries, references to other protocols,
+ *  etc.
+ *
+ *  @param[in] parent  The parent da, must be structural
+ *  @param[in] child   The alleged child
+ *  @return
+ *     - false - the child is not allowed to be contained by the parent
+ *     - true - the child is allowed to be contained by the parent
+ */
+bool fr_dict_attr_can_contain(fr_dict_attr_t const *parent, fr_dict_attr_t const *child)
+{
+       /*
+        *      This is the common case: child is from the parent.
+        */
+       if (child->parent == parent) return true;
+
+       /*
+        *      Only structural types can have children.
+        *
+        *      @todo - yes, "key" members of FR_TYPE_STRUCT.
+        */
+       if (!fr_type_structural[parent->type]) return false;
+
+       /*
+        *      An internal attribute can go into any other container.
+        *
+        *      Any other attribute can go into an internal structural
+        *      attribute, because why not?
+        */
+       if (dict_gctx) {
+               if (child->dict == dict_gctx->internal) return true;
+
+               if (parent->dict == dict_gctx->internal) return true;
+       }
+
+       /*
+        *      Protocol attributes have to be in the same dictionary.
+        *
+        *      Unless they're a cross-protocol grouping attribute.
+        *      In which case we check if the ref is the same.
+        */
+       if (child->dict != parent->dict) {
+               fr_dict_attr_t const *ref;
+
+               ref = fr_dict_attr_ref(parent);
+               return (ref && (ref->dict == child->dict));
+       }
+
+       /*
+        *      We're in the same protocol dictionary, but the child
+        *      isn't directly from the parent.  Therefore the only
+        *      type of same-protocol structure it can go into is a
+        *      group.
+        */
+       return (parent->type == FR_TYPE_GROUP);
+}
index 2c39808477c01dc0cde983367d50f1f6cca7b546..f38db6c1443b65f10103ca41316a8a4aa7f15cfd 100644 (file)
@@ -2979,6 +2979,7 @@ void fr_pair_verify(char const *file, int line, fr_pair_list_t const *list, fr_p
                                            vp, talloc_get_name(vp),
                                            parent, talloc_get_name(parent));
 
+                       fr_assert(fr_dict_attr_can_contain(vp->da, child->da));
                        fr_pair_verify(file, line, &vp->vp_group, child);
                }
        }