]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add utility function to allow dictionaries to be dynamically autoloaded
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 6 Dec 2023 23:19:45 +0000 (17:19 -0600)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 6 Dec 2023 23:20:19 +0000 (17:20 -0600)
src/lib/util/dict.h
src/lib/util/dict_util.c

index 9a1359109571967fd4904b345e69b1b2b2cab006..c31ebf439fe5ba583e9001888fb6743066c64072 100644 (file)
@@ -66,6 +66,8 @@ typedef struct value_box_s fr_value_box_t;
 #  define DA_VERIFY(_x)                fr_cond_assert(_x)
 #endif
 
+typedef struct fr_dict_autoload_talloc_s fr_dict_autoload_talloc_t;
+
 /** Values of the encryption flags
  */
 typedef struct {
@@ -617,6 +619,9 @@ int                 _fr_dict_autoload(fr_dict_autoload_t const *to_load, char const *dependent
 #define                        fr_dict_autofree(_to_free) _fr_dict_autofree(_to_free, __FILE__)
 int                    _fr_dict_autofree(fr_dict_autoload_t const *to_free, char const *dependent);
 
+#define                        fr_dict_autoload_talloc(_ctx, _dict_out, _proto) _fr_dict_autoload_talloc(_ctx, _dict_out, _proto, __FILE__)
+fr_dict_autoload_talloc_t *_fr_dict_autoload_talloc(TALLOC_CTX *ctx, fr_dict_t const **out, char const *proto, char const *dependent);
+
 int                    fr_dl_dict_enum_autoload(dl_t const *module, void *symbol, void *user_ctx);
 
 int                    fr_dl_dict_attr_autoload(dl_t const *module, void *symbol, void *user_ctx);
index ec7ca83d6d8ce5dc423d2320faeeb47d736d8a0f..32392626c32985f90d9eacdb3c33d1ce26a83e12 100644 (file)
@@ -3737,6 +3737,68 @@ int _fr_dict_autofree(fr_dict_autoload_t const *to_free, char const *dependent)
        return 0;
 }
 
+/** Structure used to managed the lifetime of a dictionary
+ *
+ * This should only be used when dictionaries are being dynamically loaded during
+ * compilation.  It should not be used to load dictionaries at runtime, or if
+ * modules need to load dicitonaries (use static fr_dict_autoload_t defs).
+
+ */
+struct fr_dict_autoload_talloc_s {
+       fr_dict_autoload_t load[2];             //!< Autoloader def.
+       char const *dependent;                  //!< Dependent that loaded the dictionary.
+};
+
+/** Talloc destructor to automatically free dictionaries
+ *
+ * @param[in] to_free  dictionary autoloader definition describing the dictionary to free.
+ */
+static int _fr_dict_autoload_talloc_free(fr_dict_autoload_talloc_t const *to_free)
+{
+       return _fr_dict_autofree(to_free->load, to_free->dependent);
+}
+
+/** Autoload a dictionary and bind the lifetime to a talloc chunk
+ *
+ * Mainly useful for resolving "forward" references from unlang immediately.
+ *
+ * @note If the talloc chunk is freed it does not mean the dictionary will
+ *      be immediately freeed.  It will be freed when all other references
+ *      to the dictionary are gone.
+ *
+ * @parma[in] ctx      to bind the dictionary lifetime to.
+ * @parma[in] proto    to load.
+ * @param[in] dependent to register this reference to.  Will be dupd.
+ */
+fr_dict_autoload_talloc_t *_fr_dict_autoload_talloc(TALLOC_CTX *ctx, fr_dict_t const **out, char const *proto, char const *dependent)
+{
+       fr_dict_autoload_talloc_t *dict_ref;
+       int ret;
+
+       dict_ref = talloc(ctx, fr_dict_autoload_talloc_t);
+       if (unlikely(dict_ref == NULL)) {
+       oom:
+               fr_strerror_const("Out of memory");
+               return NULL;
+       }
+
+       dict_ref->load[0] = (fr_dict_autoload_t){ .proto = proto, .out = out};
+       dict_ref->load[1] = (fr_dict_autoload_t){ NULL };
+       dict_ref->dependent = talloc_strdup(dict_ref, dependent);
+       if (unlikely(dict_ref->dependent == NULL)) {
+               talloc_free(dict_ref);
+               goto oom;
+       }
+
+       ret = _fr_dict_autoload(dict_ref->load, dependent);
+       if (ret < 0) {
+               talloc_free(dict_ref);
+               return NULL;
+       }
+
+       return dict_ref;
+}
+
 /** Callback to automatically resolve enum values
  *
  * @param[in] module   being loaded.