From: Arran Cudbard-Bell Date: Mon, 15 Apr 2024 03:22:21 +0000 (-0400) Subject: Support custom key callenv parsers in rlm_cache X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=88d299cfa6aa0dadb182293f25b3a13e3eaa49bf;p=thirdparty%2Ffreeradius-server.git Support custom key callenv parsers in rlm_cache --- diff --git a/src/modules/rlm_cache/rlm_cache.c b/src/modules/rlm_cache/rlm_cache.c index 79bd385fcb6..3df0664ee56 100644 --- a/src/modules/rlm_cache/rlm_cache.c +++ b/src/modules/rlm_cache/rlm_cache.c @@ -19,6 +19,7 @@ * @file rlm_cache.c * @brief Cache values and merge them back into future requests. * + * @copyright 2024 Arran Cudbard-Bell (a.cudbardb@freeradius.org) * @copyright 2012-2014 The FreeRADIUS server project */ RCSID("$Id$") @@ -30,6 +31,7 @@ RCSID("$Id$") #include #include #include +#include #include #include #include @@ -40,6 +42,7 @@ RCSID("$Id$") extern module_rlm_t rlm_cache; +static int cache_key_parse(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, void const *data, call_env_parser_t const *rule); static int cache_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, UNUSED call_env_parser_t const *rule); static const conf_parser_t module_config[] = { @@ -59,10 +62,15 @@ typedef struct { map_list_t *maps; //!< Attribute map applied to cache entries. } cache_call_env_t; +typedef struct { + fr_type_t ktype; //!< Key type + +} cache_htrie_t; + static const call_env_method_t cache_method_env = { FR_CALL_ENV_METHOD_OUT(cache_call_env_t), .env = (call_env_parser_t[]) { - { FR_CALL_ENV_OFFSET("key", FR_TYPE_STRING, CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_CONCAT, cache_call_env_t, key) }, + { FR_CALL_ENV_OFFSET("key", FR_TYPE_VOID, CALL_ENV_FLAG_REQUIRED, cache_call_env_t, key), .pair.func = cache_key_parse }, { FR_CALL_ENV_SUBSECTION_FUNC("update", CF_IDENT_ANY, CALL_ENV_FLAG_NONE, cache_update_section_parse) }, CALL_ENV_TERMINATOR } @@ -94,6 +102,48 @@ fr_dict_attr_autoload_t rlm_cache_dict_attr[] = { { NULL } }; +static int cache_key_parse(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, void const *data, call_env_parser_t const *rule) +{ + rlm_cache_t *inst = talloc_get_type_abort(data, rlm_cache_t); + call_env_parse_pair_t func = inst->driver->key_parse ? inst->driver->key_parse : call_env_parse_pair; + tmpl_t *key_tmpl; + fr_type_t cast; + int ret; + /* + * Call the custom key parse function, OR the standard call_env_parse_pair + * function, depending on whether the driver calls a custom parsing function. + */ + if (unlikely((ret = func(ctx, &key_tmpl, t_rules, ci, inst->driver_submodule->dl_inst->data, rule)) < 0)) return ret; + *((tmpl_t **)out) = key_tmpl; + + /* + * Unless the driver has a custom key parse function, we only allow keys of + * type string. + */ + if (inst->driver->key_parse) return 0; + + cast = tmpl_cast_get(key_tmpl); + switch (cast) { + case FR_TYPE_STRING: + case FR_TYPE_NULL: + case FR_TYPE_VOID: + break; + + default: + cf_log_err(ci, "Driver only allows key type '%s', got '%s'", + fr_type_to_str(FR_TYPE_STRING), fr_type_to_str(cast)); + return -1; + } + + if (tmpl_cast_set(key_tmpl, FR_TYPE_STRING) < 0) { + cf_log_perr(ci, "Can't convert key type '%s' to '%s'", + fr_type_to_str(tmpl_expanded_type(key_tmpl)), fr_type_to_str(FR_TYPE_STRING)); + return -1; + } + + return 0; +} + /** Get exclusive use of a handle to access the cache * */ diff --git a/src/modules/rlm_cache/rlm_cache.h b/src/modules/rlm_cache/rlm_cache.h index d9ced711172..7915bb91ec3 100644 --- a/src/modules/rlm_cache/rlm_cache.h +++ b/src/modules/rlm_cache/rlm_cache.h @@ -272,4 +272,10 @@ struct rlm_cache_driver_s { cache_release_t release; //!< (optional) Release access to resource acquired //!< with acquire callback. cache_reconnect_t reconnect; //!< (optional) Re-initialise resource. + + call_env_parse_pair_t key_parse; //!< (optional) custom key parser. Allows the driver + ///< to have complete control over how the key is + ///< parsed. If not provided, the default key parser + ///< will be used. data will be set to the submodule's + ///< instance data, NOT the #rlm_cache_t. };