26 RCSID(
"$Id: 1bced2b10bfa00119e9ca1ab89fa5ad843efbd84 $")
28 #include <freeradius-devel/server/paircmp.h>
29 #include <freeradius-devel/server/pairmove.h>
30 #include <freeradius-devel/server/tmpl_dcursor.h>
32 #include <freeradius-devel/util/debug.h>
33 #include <freeradius-devel/util/calc.h>
34 #include <freeradius-devel/util/edit.h>
35 #include <freeradius-devel/util/pair_legacy.h>
37 #include <freeradius-devel/protocol/radius/rfc2865.h>
38 #include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
47 int i, j,
count, to_count, tailto;
48 fr_pair_t *from_vp, *next_from, *to_vp, *next_to = NULL;
76 edited = talloc_zero_array(request,
bool, to_count);
77 deleted = talloc_zero_array(request,
bool, to_count);
87 for (i = 0, from_vp =
fr_pair_list_head(from); from_vp; i++, from_vp = next_from) {
92 RDEBUG4(
"::: Examining %s", from_vp->
da->name);
107 RDEBUG4(
"::: PREPENDING %s FROM %d", from_vp->
da->name, i);
117 if (edited[j] || deleted[j] || !from_vp)
continue;
122 if (from_vp->
da != to_vp->
da) {
139 RDEBUG4(
"::: OVERWRITING %s FROM %d TO %d",
140 to_vp->
da->name, i, j);
175 int old_op = from_vp->op;
193 from_vp->op = old_op;
197 if (rcode != 0)
goto delete;
203 RDEBUG4(
"::: DELETING %s FROM %d TO %d",
204 from_vp->
da->name, i, j);
218 RDEBUG4(
"::: REPLACING %s FROM %d TO %d",
219 from_vp->
da->name, i, j);
226 RDEBUG4(
"::: REPLACING %s FROM %d TO %d",
227 from_vp->
da->name, i, j);
249 if (!found && from_vp) {
250 if ((from_vp->op ==
T_OP_EQ) ||
255 RDEBUG4(
"::: APPENDING %s FROM %d TO %d",
256 from_vp->
da->name, i, tailto++);
269 RDEBUG4(
"::: TO in %d out %d", to_count, tailto);
284 RDEBUG4(
"::: to[%d] = %s", i, to_vp->
da->name);
333 if (rhs->vp_type != da->type) {
353 TALLOC_FREE(to_free);
357 TALLOC_FREE(to_free);
377 for (child = map_list_next(&map->
child, NULL);
379 child = map_list_next(&map->
child, child)) {
395 if (rhs->vp_type !=
vp->vp_type) {
415 if (
tmpl_aexpand(request, &to_free, request, map->
rhs, NULL, NULL) < 0)
return -1;
426 TALLOC_FREE(to_free);
435 if (box->vb_strvalue[0]) {
444 .list = &
vp->vp_group,
445 .allow_compare =
false,
446 .tainted = box->tainted,
451 RPEDEBUG(
"Failed parsing string '%pV' as attribute list", box);
452 TALLOC_FREE(to_free);
457 TALLOC_FREE(to_free);
476 if (!
vp)
return NULL;
560 if ((num >= 0) || (num ==
NUM_LAST)) {
625 RWDEBUG(
"Failed creating attribute %s", map->
lhs->name);
698 if (rhs->vp_type != da->type) {
711 if (
tmpl_aexpand(ctx, &to_free, request, map->
rhs, NULL, NULL) < 0)
return -1;
726 TALLOC_FREE(to_free);
730 TALLOC_FREE(to_free);
741 if (rcode < 0)
goto fail;
743 if (rcode != 0)
break;
750 if (rcode < 0)
goto fail;
767 TALLOC_FREE(to_free);
775 for (map = map_list_head(list);
777 map = map_list_next(list, map)) {
779 map->
rhs ? map->
rhs->name :
"{ ... }");
834 if (
tmpl_aexpand(request, &to_free, request, map->
rhs, NULL, NULL) < 0)
goto error;
860 if ((rcode >= 0) && dst.vb_bool)
break;
863 TALLOC_FREE(to_free);
866 if (rcode < 0)
return rcode;
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
int fr_value_calc_binary_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t hint, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b)
Calculate DST = A OP B.
static void * fr_dcursor_set_current(fr_dcursor_t *cursor, void *item)
Set the cursor to a specified item.
fr_dcursor_eval_t void const * uctx
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
#define RPEDEBUG(fmt,...)
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_BOOL
A truth value.
int fr_pair_append_by_da(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list, fr_dict_attr_t const *da)
Alloc a new fr_pair_t (and append)
fr_pair_t * fr_pair_parent(fr_pair_t const *vp)
Return a pointer to the parent pair.
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
int fr_pair_list_copy(TALLOC_CTX *ctx, fr_pair_list_t *to, fr_pair_list_t const *from)
Duplicate a list of pairs.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
void fr_pair_replace(fr_pair_list_t *list, fr_pair_t *to_replace, fr_pair_t *vp)
Replace a given VP.
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
fr_pair_list_t * fr_pair_parent_list(fr_pair_t const *vp)
Return a pointer to the parent pair list.
fr_pair_t * fr_pair_find_by_da_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
int fr_pair_prepend(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the start of the list.
fr_slen_t fr_pair_list_afrom_substr(fr_pair_parse_t const *root, fr_pair_parse_t *relative, fr_sbuff_t *in)
Parse a fr_pair_list_t from a substring.
struct fr_pair_parse_s fr_pair_parse_t
int paircmp_pairs(UNUSED request_t *request, fr_pair_t const *check, fr_pair_t *vp)
Compares check and vp by value.
static int radius_legacy_map_to_vp(request_t *request, fr_pair_t *parent, map_t const *map)
void radius_pairmove(request_t *request, fr_pair_list_t *to, fr_pair_list_t *from)
int radius_legacy_map_cmp(request_t *request, map_t const *map)
static fr_pair_t * legacy_pair_build(fr_pair_t *parent, fr_dcursor_t *cursor, fr_dict_attr_t const *da, void *uctx)
Build the relevant pairs at each level.
int radius_legacy_map_apply(request_t *request, map_t const *map, fr_edit_list_t *el)
Move a map using the operators from the old pairmove functionality.
static int radius_legacy_map_apply_structural(request_t *request, map_t const *map, fr_pair_t *vp)
int radius_legacy_map_list_apply(request_t *request, map_list_t const *list, fr_edit_list_t *el)
fr_dict_attr_t const * request_attr_request
fr_dict_attr_t const * request_attr_control
fr_dict_attr_t const * request_attr_state
fr_dict_attr_t const * request_attr_reply
#define FR_SBUFF_IN(_start, _len_or_end)
int tmpl_find_vp(fr_pair_t **out, request_t *request, tmpl_t const *vpt))
Returns the first VP matching a tmpl_t.
static int16_t tmpl_attr_tail_num(tmpl_t const *vpt)
Return the last attribute reference's attribute number.
#define tmpl_contains_xlat(vpt)
#define tmpl_is_xlat(vpt)
#define tmpl_value(_tmpl)
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
#define tmpl_is_attr(vpt)
#define tmpl_pair_list_and_ctx(_ctx, _head, _request, _ref, _list)
Determine the correct context and list head.
#define tmpl_is_data(vpt)
#define tmpl_is_regex(vpt)
static fr_dict_attr_t const * tmpl_list(tmpl_t const *vpt)
#define tmpl_aexpand(_ctx, _out, _request, _vpt, _escape, _escape_ctx)
Expand a tmpl to a C type, allocing a new buffer to hold the string.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
fr_token_t op
The operator that controls insertion of the dst attribute.
tmpl_t * lhs
Typically describes the attribute to add, modify or compare.
map_list_t child
parent map, for nested ones
tmpl_t * rhs
Typically describes a literal value or a src attribute to copy or compare.
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
void tmpl_dcursor_clear(tmpl_dcursor_ctx_t *cc)
Clear any temporary state allocations.
#define tmpl_dcursor_build_init(_err, _ctx, _cc, _cursor, _request, _vpt, _build, _uctx)
#define tmpl_dcursor_init(_err, _ctx, _cc, _cursor, _request, _vpt)
Maintains state between cursor calls.
char const * fr_tokens[T_TOKEN_LAST]
const bool fr_comparison_op[T_TOKEN_LAST]
static fr_event_list_t * el
int fr_edit_list_pair_delete(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *vp)
Delete a VP.
int fr_edit_list_save_pair_value(fr_edit_list_t *el, fr_pair_t *vp)
Record the value of a leaf fr_value_box_t.
int fr_edit_list_free_pair_children(fr_edit_list_t *el, fr_pair_t *vp)
Free children of a structural pair.
#define fr_edit_list_insert_pair_tail(_el, _list, _vp)
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
fr_pair_t * fr_pair_remove(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list without freeing.
fr_pair_t * fr_pair_list_next(fr_pair_list_t const *list, fr_pair_t const *item))
Get the next item in a valuepair list after a specific entry.
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
void fr_pair_list_append(fr_pair_list_t *dst, fr_pair_list_t *src)
Appends a list of fr_pair_t from a temporary list to a destination list.
void fr_pair_list_prepend(fr_pair_list_t *dst, fr_pair_list_t *src)
Move a list of fr_pair_t from a temporary list to the head of a destination list.
size_t fr_pair_list_num_elements(fr_pair_list_t const *list)
Get the length of a list of fr_pair_t.
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
#define fr_type_is_structural(_x)
#define fr_type_is_leaf(_x)
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
int fr_value_box_cmp_op(fr_token_t op, fr_value_box_t const *a, fr_value_box_t const *b)
Compare two attributes using an operator.
void fr_value_box_strdup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Assign a buffer containing a nul terminated string to a box, but don't copy it.