/* * Allow single attribute values to be retrieved from the dhcp. */ static ssize_t dhcp_options_xlat(UNUSED void *instance, REQUEST *request, char const *fmt, char **out, size_t freespace) { vp_cursor_t cursor, src_cursor; vp_tmpl_t src; VALUE_PAIR *vp, *head = NULL; int decoded = 0; ssize_t slen; while (isspace((int) *fmt)) fmt++; slen = tmpl_from_attr_str(&src, fmt, REQUEST_CURRENT, PAIR_LIST_REQUEST, false, false); if (slen <= 0) { REMARKER(fmt, slen, fr_strerror()); error: return -1; } if (src.type != TMPL_TYPE_ATTR) { REDEBUG("dhcp_options cannot operate on a %s", fr_int2str(tmpl_names, src.type, "<INVALID>")); goto error; } if (src.tmpl_da->type != PW_TYPE_OCTETS) { REDEBUG("dhcp_options got a %s attribute needed octets", fr_int2str(dict_attr_types, src.tmpl_da->type, "<INVALID>")); goto error; } for (vp = tmpl_cursor_init(NULL, &src_cursor, request, &src); vp; vp = tmpl_cursor_next(&src_cursor, &src)) { /* * @fixme: we should pass in a cursor, then decoding multiple * source attributes can be made atomic. */ if ((fr_dhcp_decode_options(request->packet, &head, vp->vp_octets, vp->vp_length) < 0) || (!head)) { RWDEBUG("DHCP option decoding failed: %s", fr_strerror()); goto error; } for (vp = fr_cursor_init(&cursor, &head); vp; vp = fr_cursor_next(&cursor)) { rdebug_pair(L_DBG_LVL_2, request, vp, "dhcp_options: "); decoded++; } fr_pair_list_move(request->packet, &(request->packet->vps), &head); /* Free any unmoved pairs */ fr_pair_list_free(&head); } snprintf(*out, freespace, "%i", decoded); return strlen(*out); }
/** Copy VP(s) from the specified request. * * @param ctx to alloc new VALUE_PAIRs in. * @param out where to write the pointer to the copied VP. * Will be NULL if the attribute couldn't be resolved. * @param request current request. * @param name attribute name including qualifiers. * @return -4 if either the attribute or qualifier were invalid, and the same error codes as tmpl_find_vp for other * error conditions. */ int radius_copy_vp(TALLOC_CTX *ctx, VALUE_PAIR **out, REQUEST *request, char const *name) { value_pair_tmpl_t vpt; *out = NULL; if (tmpl_from_attr_str(&vpt, name, REQUEST_CURRENT, PAIR_LIST_REQUEST) < 0) { return -4; } return tmpl_copy_vps(ctx, out, request, &vpt); }
/** Return a VP from the specified request. * * @param out where to write the pointer to the resolved VP. * Will be NULL if the attribute couldn't be resolved. * @param request current request. * @param name attribute name including qualifiers. * @return -4 if either the attribute or qualifier were invalid, and the same error codes as tmpl_find_vp for other * error conditions. */ int radius_get_vp(VALUE_PAIR **out, REQUEST *request, char const *name) { value_pair_tmpl_t vpt; *out = NULL; if (tmpl_from_attr_str(&vpt, name, REQUEST_CURRENT, PAIR_LIST_REQUEST) < 0) { return -4; } return tmpl_find_vp(out, request, &vpt); }
/** Create a new rlm_cache_redis instance * * @copydetails cache_instantiate_t */ static int mod_instantiate(CONF_SECTION *conf, rlm_cache_config_t const *config, void *driver_inst) { rlm_cache_redis_t *driver = driver_inst; char buffer[256]; buffer[0] = '\0'; fr_redis_version_print(); if (cf_section_parse(conf, driver, driver_config) < 0) return -1; snprintf(buffer, sizeof(buffer), "rlm_cache (%s)", config->name); driver->cluster = fr_redis_cluster_alloc(driver, conf, &driver->conf); if (!driver->cluster) { ERROR("rlm_cache_redis: Cluster failure"); return -1; } /* * These never change, so do it once on instantiation */ if (tmpl_from_attr_str(&driver->created_attr, "&Cache-Created", REQUEST_CURRENT, PAIR_LIST_REQUEST, false, false) < 0) { ERROR("rlm_cache_redis: Cache-Created attribute not defined"); return -1; } if (tmpl_from_attr_str(&driver->expires_attr, "&Cache-Expires", REQUEST_CURRENT, PAIR_LIST_REQUEST, false, false) < 0) { ERROR("rlm_cache_redis: Cache-Expires attribute not defined"); return -1; } return 0; }
/** Parse qualifiers to convert attrname into a value_pair_tmpl_t. * * VPTs are used in various places where we need to pre-parse configuration * sections into attribute mappings. * * @param[in] ctx for talloc * @param[in] name attribute name including qualifiers. * @param[in] request_def The default request to insert unqualified * attributes into. * @param[in] list_def The default list to insert unqualified attributes into. * @return pointer to a value_pair_tmpl_t struct (must be freed with * tmpl_free) or NULL on error. */ value_pair_tmpl_t *tmpl_afrom_attr_str(TALLOC_CTX *ctx, char const *name, request_refs_t request_def, pair_lists_t list_def) { value_pair_tmpl_t *vpt; char const *copy; vpt = talloc(ctx, value_pair_tmpl_t); /* parse_attr zeroes it */ copy = talloc_typed_strdup(vpt, name); if (tmpl_from_attr_str(vpt, copy, request_def, list_def) < 0) { ERROR("%s", fr_strerror()); tmpl_free(&vpt); return NULL; } return vpt; }
/** Convert module specific attribute id to value_pair_tmpl_t. * * @param[in] ctx for talloc * @param[in] name string to convert. * @param[in] type Type of quoting around value. * @param[in] request_def The default request to insert unqualified * attributes into. * @param[in] list_def The default list to insert unqualified attributes into. * @return pointer to new VPT. */ value_pair_tmpl_t *tmpl_afrom_str(TALLOC_CTX *ctx, char const *name, FR_TOKEN type, request_refs_t request_def, pair_lists_t list_def) { int rcode; char const *p; value_pair_tmpl_t *vpt; char buffer[1024]; vpt = talloc_zero(ctx, value_pair_tmpl_t); vpt->name = talloc_typed_strdup(vpt, name); switch (type) { case T_BARE_WORD: /* * If we can parse it as an attribute, it's an attribute. * Otherwise, treat it as a literal. */ rcode = tmpl_from_attr_str(vpt, vpt->name, request_def, list_def); if (rcode == -2) { talloc_free(vpt); return NULL; } if (rcode == 0) { break; } /* FALL-THROUGH */ case T_SINGLE_QUOTED_STRING: vpt->type = TMPL_TYPE_LITERAL; break; case T_DOUBLE_QUOTED_STRING: p = name; while (*p) { if (*p == '\\') { if (!p[1]) break; p += 2; continue; } if (*p == '%') break; p++; } /* * If the double quoted string needs to be * expanded at run time, make it an xlat * expansion. Otherwise, convert it to be a * literal. */ if (*p) { vpt->type = TMPL_TYPE_XLAT; } else { vpt->type = TMPL_TYPE_LITERAL; } break; case T_BACK_QUOTED_STRING: vpt->type = TMPL_TYPE_EXEC; break; case T_OP_REG_EQ: /* hack */ vpt->type = TMPL_TYPE_REGEX; break; default: rad_assert(0); return NULL; } tmpl_prints(buffer, sizeof(buffer), vpt); return vpt; }