};
typedef struct {
- fr_value_box_t *key; //!< To lookup the cache entry with.
+ fr_value_box_list_t key; //!< To lookup the cache entry with.
map_list_t *maps; //!< Attribute map applied to cache entries.
} cache_call_env_t;
}
}
+/** Macro to reduce boilerplate in all the module methods / xlat functions
+ * If multiple values are in the input list, concat them as a string
+ * Then check that a variable length key is longer than zero bytes
+ */
+#define FIXUP_KEY(_fail, _invalid) \
+if ((fr_value_box_list_num_elements(&env->key) > 1) && \
+ (fr_value_box_list_concat_in_place(key, key, &env->key, FR_TYPE_STRING, \
+ FR_VALUE_BOX_LIST_FREE, true, SIZE_MAX) < 0)) { \
+ REDEBUG("Failed concatenating values to form the key"); \
+ _fail; \
+} \
+if (fr_type_is_variable_size(key->type) && (key->vb_length == 0)) { \
+ REDEBUG("Zero length key string is invalid"); \
+ _invalid; \
+}
+
/** Do caching checks
*
* Since we can update ANY VP list, we do exactly the same thing for all sections
rlm_cache_entry_t *c = NULL;
rlm_cache_t const *inst = talloc_get_type_abort_const(mctx->mi->data, rlm_cache_t);
cache_call_env_t *env = talloc_get_type_abort(mctx->env_data, cache_call_env_t);
-
+ fr_value_box_t *key = fr_value_box_list_head(&env->key);
rlm_cache_handle_t *handle;
fr_dcursor_t cursor;
p_result->rcode = RLM_MODULE_NOOP;
- if (fr_type_is_variable_size(env->key->type) && (env->key->vb_length == 0)) {
- REDEBUG("Zero length key string is invalid");
- RETURN_UNLANG_INVALID;
- }
+ FIXUP_KEY(RETURN_UNLANG_FAIL, RETURN_UNLANG_INVALID)
/*
* If Cache-Status-Only == yes, only return whether we found a
RETURN_UNLANG_FAIL;
}
- cache_find(p_result, &c, inst, request, &handle, env->key);
+ cache_find(p_result, &c, inst, request, &handle, key);
if (p_result->rcode == RLM_MODULE_FAIL) goto finish;
fr_assert(!inst->driver->acquire || handle);
* recording whether the entry existed.
*/
if (merge) {
- cache_find(p_result, &c, inst, request, &handle, env->key);
+ cache_find(p_result, &c, inst, request, &handle, key);
switch (p_result->rcode) {
case RLM_MODULE_FAIL:
goto finish;
unlang_result_t tmp;
fr_assert(!set_ttl);
- cache_expire(&tmp, inst, request, &handle, env->key);
+ cache_expire(&tmp, inst, request, &handle, key);
switch (tmp.rcode) {
case RLM_MODULE_FAIL:
p_result->rcode = RLM_MODULE_FAIL;
if ((exists < 0) && (insert || set_ttl)) {
unlang_result_t tmp;
- cache_find(&tmp, &c, inst, request, &handle, env->key);
+ cache_find(&tmp, &c, inst, request, &handle, key);
switch (tmp.rcode) {
case RLM_MODULE_FAIL:
p_result->rcode = RLM_MODULE_FAIL;
if (insert && (exists == 0)) {
unlang_result_t tmp;
- cache_insert(&tmp, inst, request, &handle, env->key, env->maps, ttl);
+ cache_insert(&tmp, inst, request, &handle, key, env->maps, ttl);
switch (tmp.rcode) {
case RLM_MODULE_FAIL:
p_result->rcode = RLM_MODULE_FAIL;
rlm_cache_entry_t *c = NULL;
rlm_cache_t *inst = talloc_get_type_abort(xctx->mctx->mi->data, rlm_cache_t);
cache_call_env_t *env = talloc_get_type_abort(xctx->env_data, cache_call_env_t);
+ fr_value_box_t *key = fr_value_box_list_head(&env->key);
rlm_cache_handle_t *handle = NULL;
ssize_t slen;
map_t *map = NULL;
unlang_result_t result = { .rcode = RLM_MODULE_NOOP };
+ FIXUP_KEY(return XLAT_ACTION_FAIL, return XLAT_ACTION_FAIL)
+
slen = tmpl_afrom_attr_substr(ctx, NULL, &target,
&FR_SBUFF_IN(attr->vb_strvalue, attr->vb_length),
NULL,
return XLAT_ACTION_FAIL;
}
- cache_find(&result, &c, inst, request, &handle, env->key);
+ cache_find(&result, &c, inst, request, &handle, key);
switch (result.rcode) {
case RLM_MODULE_OK: /* found */
break;
xlat_ctx_t const *xctx,
request_t *request, UNUSED fr_value_box_list_t *in)
{
-
rlm_cache_entry_t *c = NULL;
rlm_cache_t *inst = talloc_get_type_abort(xctx->mctx->mi->data, rlm_cache_t);
cache_call_env_t *env = talloc_get_type_abort(xctx->env_data, cache_call_env_t);
+ fr_value_box_t *key = fr_value_box_list_head(&env->key);
rlm_cache_handle_t *handle = NULL;
unlang_result_t result = { .rcode = RLM_MODULE_NOOP };
fr_value_box_t *vb;
+ FIXUP_KEY(return XLAT_ACTION_FAIL, return XLAT_ACTION_FAIL)
+
if (cache_acquire(&handle, inst, request) < 0) {
return XLAT_ACTION_FAIL;
}
- cache_find(&result, &c, inst, request, &handle, env->key);
+ cache_find(&result, &c, inst, request, &handle, key);
switch (result.rcode) {
case RLM_MODULE_OK: /* found */
break;
{
rlm_cache_t const *inst = talloc_get_type_abort(mctx->mi->data, rlm_cache_t);
cache_call_env_t *env = talloc_get_type_abort(mctx->env_data, cache_call_env_t);
+ fr_value_box_t *key = fr_value_box_list_head(&env->key);
rlm_cache_entry_t *entry = NULL;
rlm_cache_handle_t *handle = NULL;
p_result->rcode = RLM_MODULE_NOOP;
- if (fr_type_is_variable_size(env->key->type) && (env->key->vb_length == 0)) {
- REDEBUG("Zero length key string is invalid");
- RETURN_UNLANG_FAIL;
- }
+ FIXUP_KEY(RETURN_UNLANG_FAIL, RETURN_UNLANG_INVALID)
/* Good to go? */
if (cache_acquire(&handle, inst, request) < 0) {
fr_assert(!inst->driver->acquire || handle);
- cache_find(p_result, &entry, inst, request, &handle, env->key);
+ cache_find(p_result, &entry, inst, request, &handle, key);
if (p_result->rcode == RLM_MODULE_FAIL) goto finish;
p_result->rcode = (entry) ? RLM_MODULE_OK : RLM_MODULE_NOTFOUND;
cache_call_env_t *env = talloc_get_type_abort(mctx->env_data, cache_call_env_t);
rlm_cache_entry_t *entry = NULL;
rlm_cache_handle_t *handle = NULL;
+ fr_value_box_t *key = fr_value_box_list_head(&env->key);
p_result->rcode = RLM_MODULE_NOOP;
- if (fr_type_is_variable_size(env->key->type) && (env->key->vb_length == 0)) {
- REDEBUG("Zero length key string is invalid");
- RETURN_UNLANG_FAIL;
- }
+ FIXUP_KEY(RETURN_UNLANG_FAIL, RETURN_UNLANG_INVALID)
/* Good to go? */
if (cache_acquire(&handle, inst, request) < 0) {
RETURN_UNLANG_FAIL;
}
- cache_find(p_result, &entry, inst, request, &handle, env->key);
+ cache_find(p_result, &entry, inst, request, &handle, key);
if (p_result->rcode == RLM_MODULE_FAIL) goto finish;
if (!entry) {
{
rlm_cache_t const *inst = talloc_get_type_abort(mctx->mi->data, rlm_cache_t);
cache_call_env_t *env = talloc_get_type_abort(mctx->env_data, cache_call_env_t);
+ fr_value_box_t *key = fr_value_box_list_head(&env->key);
fr_time_delta_t ttl;
bool expire = false;
rlm_cache_entry_t *entry = NULL;
p_result->rcode = RLM_MODULE_NOOP;
- if (fr_type_is_variable_size(env->key->type) && (env->key->vb_length == 0)) {
- REDEBUG("Zero length key string is invalid");
- RETURN_UNLANG_FAIL;
- }
+ FIXUP_KEY(RETURN_UNLANG_FAIL, RETURN_UNLANG_INVALID)
/* Good to go? */
if (cache_acquire(&handle, inst, request) < 0) {
/*
* We can only alter the TTL on an entry if it exists.
*/
- cache_find(p_result, &entry, inst, request, &handle, env->key);
+ cache_find(p_result, &entry, inst, request, &handle, key);
if (p_result->rcode == RLM_MODULE_FAIL) goto finish;
if (p_result->rcode == RLM_MODULE_OK) {
if (expire) {
DEBUG3("Expiring cache entry");
- cache_expire(p_result, inst, request, &handle, env->key);
+ cache_expire(p_result, inst, request, &handle, key);
if (p_result->rcode == RLM_MODULE_FAIL) goto finish;
}
* Inserts are upserts, so we don't care about the
* entry state.
*/
- cache_insert(p_result, inst, request, &handle, env->key, env->maps, ttl);
+ cache_insert(p_result, inst, request, &handle, key, env->maps, ttl);
if (p_result->rcode == RLM_MODULE_OK) p_result->rcode = RLM_MODULE_UPDATED;
finish:
{
rlm_cache_t const *inst = talloc_get_type_abort(mctx->mi->data, rlm_cache_t);
cache_call_env_t *env = talloc_get_type_abort(mctx->env_data, cache_call_env_t);
+ fr_value_box_t *key = fr_value_box_list_head(&env->key);
fr_time_delta_t ttl;
rlm_cache_entry_t *entry = NULL;
rlm_cache_handle_t *handle = NULL;
p_result->rcode = RLM_MODULE_NOOP;
- if (fr_type_is_variable_size(env->key->type) && (env->key->vb_length == 0)) {
- REDEBUG("Zero length key string is invalid");
- RETURN_UNLANG_FAIL;
- }
+ FIXUP_KEY(RETURN_UNLANG_FAIL, RETURN_UNLANG_INVALID)
if (cache_acquire(&handle, inst, request) < 0) {
RETURN_UNLANG_FAIL;
/*
* We can only alter the TTL on an entry if it exists.
*/
- cache_find(p_result, &entry, inst, request, &handle, env->key);
+ cache_find(p_result, &entry, inst, request, &handle, key);
switch (p_result->rcode) {
default:
case RLM_MODULE_OK:
* setting the TTL, which precludes performing an
* insert.
*/
- cache_insert(p_result, inst, request, &handle, env->key, env->maps, ttl);
+ cache_insert(p_result, inst, request, &handle, key, env->maps, ttl);
finish:
cache_unref(request, inst, entry, handle);
{
rlm_cache_t const *inst = talloc_get_type_abort(mctx->mi->data, rlm_cache_t);
cache_call_env_t *env = talloc_get_type_abort(mctx->env_data, cache_call_env_t);
+ fr_value_box_t *key = fr_value_box_list_head(&env->key);
rlm_cache_entry_t *entry = NULL;
rlm_cache_handle_t *handle = NULL;
DEBUG3("Calling %s.clear", mctx->mi->name);
- if (fr_type_is_variable_size(env->key->type) && (env->key->vb_length == 0)) {
- REDEBUG("Zero length key string is invalid");
- RETURN_UNLANG_FAIL;
- }
+ FIXUP_KEY(RETURN_UNLANG_FAIL, RETURN_UNLANG_INVALID)
/* Good to go? */
if (cache_acquire(&handle, inst, request) < 0) {
RETURN_UNLANG_FAIL;
}
- cache_find(p_result, &entry, inst, request, &handle, env->key);
+ cache_find(p_result, &entry, inst, request, &handle, key);
if (p_result->rcode == RLM_MODULE_FAIL) goto finish;
if (!entry) {
goto finish;
}
- cache_expire(p_result, inst, request, &handle, env->key);
+ cache_expire(p_result, inst, request, &handle, key);
finish:
cache_unref(request, inst, entry, handle);
{
rlm_cache_t const *inst = talloc_get_type_abort(mctx->mi->data, rlm_cache_t);
cache_call_env_t *env = talloc_get_type_abort(mctx->env_data, cache_call_env_t);
+ fr_value_box_t *key = fr_value_box_list_head(&env->key);
fr_time_delta_t ttl;
rlm_cache_entry_t *entry = NULL;
rlm_cache_handle_t *handle = NULL;
DEBUG3("Calling %s.ttl", mctx->mi->name);
- if (fr_type_is_variable_size(env->key->type) && (env->key->vb_length == 0)) {
- REDEBUG("Zero length key string is invalid");
- RETURN_UNLANG_FAIL;
- }
+ FIXUP_KEY(RETURN_UNLANG_FAIL, RETURN_UNLANG_INVALID)
/* Good to go? */
if (cache_acquire(&handle, inst, request) < 0) {
/*
* We can only alter the TTL on an entry if it exists.
*/
- cache_find(p_result, &entry, inst, request, &handle, env->key);
+ cache_find(p_result, &entry, inst, request, &handle, key);
if (p_result->rcode == RLM_MODULE_FAIL) goto finish;
if (p_result->rcode == RLM_MODULE_OK) {