]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add API to copy attributes to a different dictionary
authorAlan T. DeKok <aland@freeradius.org>
Tue, 3 Sep 2024 18:31:55 +0000 (14:31 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Tue, 3 Sep 2024 19:05:26 +0000 (15:05 -0400)
src/lib/util/dict.h
src/lib/util/dict_util.c

index 0ad1bda348c50556e9d12359321a6485794c017c..31558b68ea29bbfca5f56004594d61c07abb4809 100644 (file)
@@ -413,6 +413,8 @@ int                 fr_dict_enum_add_name(fr_dict_attr_t *da, char const *name,
 int                    fr_dict_enum_add_name_next(fr_dict_attr_t *da, char const *name) CC_HINT(nonnull);
 
 int                    fr_dict_str_to_argv(char *str, char **argv, int max_argc);
+
+int                    fr_dict_attr_acopy_local(fr_dict_attr_t const *dst, fr_dict_attr_t const *src) CC_HINT(nonnull);
 /** @} */
 
 /** @name Unknown ephemeral attributes
index be45c6c79b638a31de8dc2b9a2fe27043983bc87..ee34d25c0ba55e34c157f6b7a90fbd397cd46aff 100644 (file)
@@ -739,6 +739,51 @@ fr_dict_attr_t *dict_attr_acopy(TALLOC_CTX *ctx, fr_dict_attr_t const *in, char
        return n;
 }
 
+/** Copy an existing attribute to a different dictionary
+ *
+ * @param[in] ctx              to allocate new attribute in.
+ * @param[in] parent           new parent to copy into
+ * @param[in] in               attribute to copy.
+ * @return
+ *     - A copy of the input fr_dict_attr_t on success.
+ *     - NULL on failure.
+ */
+static fr_dict_attr_t *dict_attr_acopy_dict(TALLOC_CTX *ctx, fr_dict_attr_t *parent, fr_dict_attr_t const *in)
+{
+       fr_dict_attr_t          *n;
+
+       n = dict_attr_alloc(ctx, parent,in->name,
+                           in->attr, in->type, &(dict_attr_args_t){ .flags = &in->flags });
+       if (unlikely(!n)) return NULL;
+
+       if (dict_attr_ext_copy_all(&n, in) < 0) {
+               talloc_free(n);
+               return NULL;
+       }
+       DA_VERIFY(n);
+
+       return n;
+}
+
+int fr_dict_attr_acopy_local(fr_dict_attr_t const *dst, fr_dict_attr_t const *src)
+{
+       if (!dst->flags.local) {
+               fr_strerror_const("Cannot copy attributes to a non-local dictionary");
+               return -1;
+       }
+
+       /*
+        *      Why not?  @todo - check and fix
+        */
+       if (src->flags.local) {
+               fr_strerror_const("Cannot copy a local attribute");
+               return -1;
+       }
+
+       return dict_attr_acopy_children(dst->dict, UNCONST(fr_dict_attr_t *, dst), src);
+}
+
+
 /** Copy the children of an existing attribute
  *
  * @param[in] dict             to allocate the children in
@@ -761,7 +806,11 @@ int dict_attr_acopy_children(fr_dict_t *dict, fr_dict_attr_t *dst, fr_dict_attr_
        for (child = fr_dict_attr_iterate_children(src, &child);
             child != NULL;
             child = fr_dict_attr_iterate_children(src, &child)) {
-               copy = dict_attr_acopy(dict->pool, child, NULL);
+               if (child->dict == dict) {
+                       copy = dict_attr_acopy(dict->pool, child, NULL);
+               } else {
+                       copy = dict_attr_acopy_dict(dict->pool, dst, child);
+               }
                if (!copy) {
                        fr_strerror_printf("Failed cloning child %s", child->name);
                        return -1;