Skip to content

Commit

Permalink
Fixup = and += with nested LHS for callers of map_to_request
Browse files Browse the repository at this point in the history
This gives at least partial nesting functionality for LDAP, SQL maps, and redis_ippool

Add support for nested attribute references for ':=', '=', '+='
  • Loading branch information
arr2036 committed Nov 13, 2020
1 parent adf66cb commit 0b30515
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 14 deletions.
135 changes: 121 additions & 14 deletions src/lib/server/map.c
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,7 @@ int map_to_request(request_t *request, map_t const *map, radius_map_getvalue_t f
fr_assert(map->lhs != NULL);
fr_assert(map->rhs != NULL);

tmp_ctx = talloc_new(request);
tmp_ctx = talloc_pool(request, 1024);
fr_cursor_init(&src_list, &head);

/*
Expand Down Expand Up @@ -1473,43 +1473,150 @@ int map_to_request(request_t *request, map_t const *map, radius_map_getvalue_t f
* = - Set only if not already set
*/
case T_OP_EQ:
{
tmpl_attr_extent_t *extent = NULL;
fr_dlist_head_t leaf;
fr_dlist_head_t interior;
fr_pair_t *src_vp;

if (dst) {
RDEBUG3("Refusing to overwrite (use :=)");
fr_pair_list_free(&head);
goto finish;
}

/* Insert first instance (if multiple) */
fr_cursor_head(&src_list);
fr_cursor_append(&dst_list, fr_cursor_remove(&src_list));
fr_dlist_talloc_init(&leaf, tmpl_attr_extent_t, entry);
fr_dlist_talloc_init(&interior, tmpl_attr_extent_t, entry);

/*
* Find out what we need to build and build it
*/
if ((tmpl_extents_find(tmp_ctx, &leaf, &interior, request, map->lhs) < 0) ||
(tmpl_extents_build_to_leaf(&leaf, &interior, map->lhs) < 0)) {
fr_dlist_talloc_free(&leaf);
fr_dlist_talloc_free(&interior);
rcode = -1;
goto finish;
}

/*
* Need to copy src to all dsts
*/
src_vp = fr_cursor_head(&src_list);
if (!src_vp) {
fr_dlist_talloc_free(&leaf);
rcode = -1;
goto finish;
}

if (fr_dlist_num_elements(&leaf) > 1) {
while ((extent = fr_dlist_head(&leaf))) {
fr_pair_add(extent->list, fr_pair_copy(extent->list_ctx, src_vp));
fr_dlist_talloc_free_head(&leaf);
}
} else {
extent = fr_dlist_head(&leaf);
fr_pair_add(extent->list, fr_pair_copy(extent->list_ctx, src_vp));
fr_dlist_talloc_free_head(&leaf);
}

/* Free any we didn't insert */
fr_pair_list_free(&head);
fr_assert(fr_dlist_num_elements(&interior) == 0);
fr_assert(fr_dlist_num_elements(&leaf) == 0);
}
break;

/*
* := - Overwrite existing attribute with last src_list attribute
*/
case T_OP_SET:
/* Wind to last instance */
fr_cursor_tail(&src_list);
if (dst) {
DEBUG_OVERWRITE(dst, fr_cursor_current(&src_list));
dst = fr_cursor_replace(&dst_list, fr_cursor_remove(&src_list));
talloc_free(dst);
{
tmpl_attr_extent_t *extent = NULL;
fr_dlist_head_t leaf;
fr_dlist_head_t interior;
fr_pair_t *src_vp;

fr_dlist_talloc_init(&leaf, tmpl_attr_extent_t, entry);
fr_dlist_talloc_init(&interior, tmpl_attr_extent_t, entry);

/*
* Find out what we need to build and build it
*/
src_vp = fr_cursor_tail(&src_list);
if ((tmpl_extents_find(tmp_ctx, &leaf, &interior, request, map->lhs) < 0) ||
(tmpl_extents_build_to_leaf(&leaf, &interior, map->lhs) < 0)) {
op_set_error:
fr_dlist_talloc_free(&leaf);
fr_dlist_talloc_free(&interior);
rcode = -1;
goto finish;
}

if (fr_dlist_num_elements(&leaf) > 1) {
ERROR("Not yet supported");

goto op_set_error;
} else {
fr_cursor_append(&dst_list, fr_cursor_remove(&src_list));
if (dst) {
DEBUG_OVERWRITE(dst, fr_cursor_current(&src_list));
dst = fr_cursor_replace(&dst_list, fr_pair_copy(extent->list_ctx, src_vp));
talloc_free(dst);
} else {
extent = fr_dlist_head(&leaf);
fr_pair_add(extent->list, fr_pair_copy(extent->list_ctx, src_vp));
}
}

/* Free any we didn't insert */
fr_pair_list_free(&head);
fr_assert(fr_dlist_num_elements(&interior) == 0);
fr_dlist_talloc_free(&leaf);
}
break;

/*
* += - Add all src_list attributes to the destination
*/
case T_OP_ADD:
/* Insert all the instances! (if multiple) */
fr_pair_add(list, head);
head = NULL;
{
tmpl_attr_extent_t *extent = NULL;
fr_dlist_head_t leaf;
fr_dlist_head_t interior;
fr_pair_t *src_vp;

fr_dlist_talloc_init(&leaf, tmpl_attr_extent_t, entry);
fr_dlist_talloc_init(&interior, tmpl_attr_extent_t, entry);

/*
* Find out what we need to build and build it
*/
if ((tmpl_extents_find(tmp_ctx, &leaf, &interior, request, map->lhs) < 0) ||
(tmpl_extents_build_to_leaf(&leaf, &interior, map->lhs) < 0)) {
fr_dlist_talloc_free(&leaf);
fr_dlist_talloc_free(&interior);
rcode = -1;
goto finish;
}

if (fr_dlist_num_elements(&leaf) > 1) {
while ((extent = fr_dlist_remove(&leaf, NULL))) {
fr_pair_add(extent->list, fr_pair_copy(extent->list_ctx, src_vp));
fr_pair_list_copy(extent->list_ctx, extent->list, &head);
fr_dlist_talloc_free_head(&leaf);
}
/* Free all the src vps */
fr_pair_list_free(&head);
} else {
extent = fr_dlist_head(&leaf);
fr_pair_list_copy(extent->list_ctx, extent->list, &head);
fr_dlist_talloc_free_head(&leaf);
}

fr_pair_list_free(&head);
fr_assert(fr_dlist_num_elements(&interior) == 0);
fr_assert(fr_dlist_num_elements(&leaf) == 0);
}
break;

/*
Expand Down
30 changes: 30 additions & 0 deletions src/lib/server/tmpl_eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -1551,10 +1551,29 @@ int tmpl_extents_find(TALLOC_CTX *ctx,
* If it's a list, just return the list head
*/
if (vpt->type == TMPL_TYPE_LIST) {
do_list:
if (leaf) EXTENT_ADD(leaf, NULL, list_ctx, list_head);
return 0;
}

/*
* If it's a leaf skip all the expensive
* initialisation and just return the list
* it's part of.
*
* This is only needed because lists are
* treated specially. Once lists are groups
* this can be removed.
*/
ar = fr_dlist_head(&vpt->data.attribute.ar);
switch (ar->ar_da->type) {
case FR_TYPE_STRUCTURAL:
break;

default:
goto do_list;
}

/*
* Initialise the temporary cursor context
*/
Expand Down Expand Up @@ -1661,6 +1680,17 @@ int tmpl_extents_build_to_leaf(fr_dlist_head_t *leaf, fr_dlist_head_t *interior,
switch (ar->type) {
case TMPL_ATTR_TYPE_NORMAL:
case TMPL_ATTR_TYPE_UNKNOWN:
/*
* Don't build leaf attributes
*/
switch (ar->ar_da->type) {
case FR_TYPE_STRUCTURAL:
break;

default:
continue;
}

MEM(vp = fr_pair_afrom_da(list_ctx, ar->ar_da)); /* Copies unknowns */
fr_pair_add(list, vp);
list = &vp->vp_group;
Expand Down

0 comments on commit 0b30515

Please sign in to comment.