From: Arran Cudbard-Bell Date: Sun, 26 Aug 2012 22:14:42 +0000 (+0100) Subject: Add xlat support for retrieving specific attributes from the cache X-Git-Tag: release_3_0_0_beta0~47 X-Git-Url: http://www.project-moonshot.org/gitweb/?a=commitdiff_plain;h=1eaeedb5d58fb1402c072e98e0163fb74b954505;p=freeradius.git Add xlat support for retrieving specific attributes from the cache --- diff --git a/src/modules/rlm_cache/rlm_cache.c b/src/modules/rlm_cache/rlm_cache.c index 2058e6c..9040292 100644 --- a/src/modules/rlm_cache/rlm_cache.c +++ b/src/modules/rlm_cache/rlm_cache.c @@ -36,6 +36,7 @@ RCSID("$Id$") * be used as the instance handle. */ typedef struct rlm_cache_t { + const char *xlat_name; char *key; int ttl; int epoch; @@ -338,6 +339,72 @@ static int cache_verify(rlm_cache_t *inst) return 1; } +/* + * Allow single attribute values to be retrieved from the cache. + */ +static int cache_xlat(void *instance, REQUEST *request, + char *fmt, char *out, size_t freespace, + UNUSED RADIUS_ESCAPE_STRING func) +{ + rlm_cache_entry_t *c; + rlm_cache_t *inst = instance; + VALUE_PAIR *vp, *vps; + pair_lists_t list; + DICT_ATTR *target; + const char *p = fmt; + char buffer[1024]; + + radius_xlat(buffer, sizeof(buffer), inst->key, request, NULL); + + c = cache_find(inst, request, buffer); + + if (!c) { + RDEBUG("No cache entry for key \"%s\"", buffer); + + return 0; + } + + list = radius_list_name(&p, PAIR_LIST_REQUEST); + switch (list) + { + case PAIR_LIST_REQUEST: + vps = c->request; + break; + + case PAIR_LIST_REPLY: + vps = c->reply; + break; + + case PAIR_LIST_CONTROL: + vps = c->control; + break; + + case PAIR_LIST_UNKNOWN: + radlog(L_ERR, "rlm_cache: Unknown list qualifier in \"%s\"", fmt); + return 0; + + default: + radlog(L_ERR, "rlm_cache: Unsupported list \"%s\"", fr_int2str(pair_lists, list, "¿Unknown?")); + return 0; + } + + target = dict_attrbyname(p); + if (!target) { + radlog(L_ERR, "rlm_cache: Unknown attribute \"%s\"", p); + + return 0; + } + + vp = pairfind(vps, target->attr, target->vendor); + if (!vp) { + RDEBUG("No instance of this attribute has been cached"); + + return 0; + } + + return vp_prints_value(out, freespace, vp, 0); +} + /* * A mapping of configuration file names to internal variables. @@ -369,6 +436,7 @@ static int cache_detach(void *instance) rlm_cache_t *inst = instance; free(inst->key); + free(inst->xlat_name); fr_heap_delete(inst->heap); rbtree_free(inst->cache); @@ -382,6 +450,7 @@ static int cache_detach(void *instance) */ static int cache_instantiate(CONF_SECTION *conf, void **instance) { + const char *xlat_name; rlm_cache_t *inst; inst = rad_malloc(sizeof(*inst)); @@ -399,6 +468,19 @@ static int cache_instantiate(CONF_SECTION *conf, void **instance) return -1; } + xlat_name = cf_section_name2(conf); + if (xlat_name == NULL) { + xlat_name = cf_section_name1(conf); + } + + rad_assert(xlat_name); + + /* + * Register the cache xlat function + */ + inst->xlat_name = strdup(xlat_name); + xlat_register(xlat_name, (RAD_XLAT_FUNC)cache_xlat, inst); + if (!inst->key || !*inst->key) { radlog(L_ERR, "rlm_cache: You must specify a key"); cache_detach(inst);