]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add map_afrom*_edit() for edit sections
authorAlan T. DeKok <aland@freeradius.org>
Sat, 21 Jan 2023 20:36:32 +0000 (15:36 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Sat, 21 Jan 2023 20:36:32 +0000 (15:36 -0500)
because the RHS of edit sections can now be expressions.

src/lib/server/map.c
src/lib/server/map.h
src/lib/unlang/compile.c

index c090f50d01cd4f7710d2a764a8f9762e68f6a85c..c7892600913a455f4dabc6bee6aceeec5bce89b9 100644 (file)
@@ -91,12 +91,13 @@ static inline map_t *map_alloc(TALLOC_CTX *ctx, map_t *parent)
  * @param[in] cp               to convert to map.
  * @param[in] lhs_rules                rules for parsing LHS attribute references.
  * @param[in] input_rhs_rules  rules for parsing RHS attribute references.
+ * @param[in] edit             treat the map as an edit
  * @return
  *     - #map_t if successful.
  *     - NULL on error.
  */
 int map_afrom_cp(TALLOC_CTX *ctx, map_t **out, map_t *parent, CONF_PAIR *cp,
-                tmpl_rules_t const *lhs_rules, tmpl_rules_t const *input_rhs_rules)
+                tmpl_rules_t const *lhs_rules, tmpl_rules_t const *input_rhs_rules, bool edit)
 {
        map_t           *map;
        char const      *attr, *value, *marker_subject;
@@ -201,6 +202,47 @@ int map_afrom_cp(TALLOC_CTX *ctx, map_t **out, map_t *parent, CONF_PAIR *cp,
                }
                value = unescaped_value;
                p_rules = NULL;
+
+       } else if (edit && (type == T_BARE_WORD)) {
+               fr_slen_t slent;
+               xlat_exp_head_t *head;
+
+               /*
+                *      Try to parse it as a bare word first.  If that
+                *      works, then we leave it as a stand-alone tmpl.
+                */
+               slen = talloc_array_length(value) - 1;
+
+               slen = tmpl_afrom_substr(map, &map->rhs,
+                                        &FR_SBUFF_IN(value, slen),
+                                        type,
+                                        p_rules,
+                                        rhs_rules);
+               if (slen > 0) {
+                       fr_assert(map->rhs);
+                       goto check_rhs;
+               }
+
+               /*
+                *      Not a bare word, it must be a complex expression.
+                */
+               slen = talloc_array_length(value) - 1;
+
+               MEM(map->rhs = tmpl_alloc(map, TMPL_TYPE_XLAT, T_BARE_WORD, value, slen));
+
+               /*
+                *      @todo - if there's only one thing in the expression, just hoist it to the tmpl?  Or do we even need to do that?
+                */
+               slent = xlat_tokenize_expression(map->rhs, &head, &FR_SBUFF_IN(value, slen), p_rules, rhs_rules);
+               if (slent <= 0) {
+                       slen = slent + 1;
+                       marker_subject = value;
+                       goto marker;
+               }
+
+               tmpl_set_xlat(map->rhs, head);
+               goto verify;
+
        } else {
                slen = talloc_array_length(value) - 1;
        }
@@ -220,6 +262,7 @@ int map_afrom_cp(TALLOC_CTX *ctx, map_t **out, map_t *parent, CONF_PAIR *cp,
                goto error;
        }
 
+check_rhs:
        if (tmpl_is_attr(map->rhs) && (tmpl_attr_unknown_add(map->rhs) < 0)) {
                cf_log_perr(cp, "Failed creating attribute %s", map->rhs->name);
                goto error;
@@ -247,6 +290,7 @@ int map_afrom_cp(TALLOC_CTX *ctx, map_t **out, map_t *parent, CONF_PAIR *cp,
                }
        }
 
+verify:
        MAP_VERIFY(map);
        TALLOC_FREE(child_ctx);
 
@@ -687,7 +731,7 @@ check_for_child:
 static int _map_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, map_t *parent, CONF_SECTION *cs,
                         tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules,
                         map_validate_t validate, void *uctx,
-                        unsigned int max, bool update)
+                        unsigned int max, bool update, bool edit)
 {
        CONF_ITEM       *ci;
        CONF_PAIR       *cp;
@@ -857,7 +901,7 @@ do_children:
                         *      correct parent map.
                         */
                        if (_map_afrom_cs(map, &child_list, map, cf_item_to_section(ci),
-                                        &our_lhs_rules, rhs_rules, validate, uctx, max, false) < 0) {
+                                        &our_lhs_rules, rhs_rules, validate, uctx, max, false, edit) < 0) {
                                map_list_talloc_free(&child_list);
                                talloc_free(map);
                                goto error;
@@ -877,7 +921,7 @@ do_children:
                cp = cf_item_to_pair(ci);
                fr_assert(cp != NULL);
 
-               if (map_afrom_cp(parent_ctx, &map, parent, cp, &our_lhs_rules, rhs_rules) < 0) {
+               if (map_afrom_cp(parent_ctx, &map, parent, cp, &our_lhs_rules, rhs_rules, edit) < 0) {
                        cf_log_err(ci, "Failed creating map from '%s = %s'",
                                   cf_pair_attr(cp), cf_pair_value(cp));
                        goto error;
@@ -930,7 +974,33 @@ int map_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, CONF_SECTION *cs,
 
        if (ctx) parent = talloc_get_type(ctx, map_t);
 
-       return _map_afrom_cs(ctx, out, parent, cs, lhs_rules, rhs_rules, validate, uctx, max, update);
+       return _map_afrom_cs(ctx, out, parent, cs, lhs_rules, rhs_rules, validate, uctx, max, update, false);
+}
+
+/** Convert a config section into an attribute map for editing
+ *
+ * @param[in] ctx              for talloc.
+ * @param[out] out             Where to store the allocated map.
+ * @param[in] cs               the update section
+ * @param[in] lhs_rules                rules for parsing LHS attribute references.
+ * @param[in] rhs_rules                rules for parsing RHS attribute references.
+ * @param[in] validate         map using this callback (may be NULL).
+ * @param[in] uctx             to pass to callback.
+ * @param[in] max              number of mappings to process.
+ * @return
+ *     - 0 on success.
+ *     - -1 on failure.
+ */
+int map_afrom_cs_edit(TALLOC_CTX *ctx, map_list_t *out, CONF_SECTION *cs,
+                     tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules,
+                     map_validate_t validate, void *uctx,
+                     unsigned int max)
+{
+       map_t *parent = NULL;
+
+       if (ctx) parent = talloc_get_type(ctx, map_t);
+
+       return _map_afrom_cs(ctx, out, parent, cs, lhs_rules, rhs_rules, validate, uctx, max, false, true);
 }
 
 /** Convert CONFIG_PAIR (which may contain refs) to map_t.
index 46e731e73cb912ad976f58323589bbd9ea80297f..ca9f8ce39dbd4ea71dc6f4ac9bc6a3104d2242c0 100644 (file)
@@ -118,12 +118,16 @@ typedef int (*radius_map_getvalue_t)(TALLOC_CTX *ctx, fr_pair_list_t *out, reque
                                     map_t const *map, void *uctx);
 
 int            map_afrom_cp(TALLOC_CTX *ctx, map_t **out, map_t *parent, CONF_PAIR *cp,
-                            tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules);
+                            tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules, bool edit);
 
 int            map_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, CONF_SECTION *cs,
                             tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules,
                             map_validate_t validate, void *uctx, unsigned int max) CC_HINT(nonnull(2, 3));
 
+int            map_afrom_cs_edit(TALLOC_CTX *ctx, map_list_t *out, CONF_SECTION *cs,
+                                 tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules,
+                                 map_validate_t validate, void *uctx, unsigned int max) CC_HINT(nonnull(2, 3));
+
 int            map_list_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, CONF_SECTION *cs,
                                  tmpl_rules_t const *t_rules,
                                  map_validate_t validate, void *uctx,
index 703a44df818774a5e745aaa780fa4af0997b6062..a82e34be1d2ea914a13c52e98b2de20c5e5a137a 100644 (file)
@@ -1888,7 +1888,7 @@ static unlang_t *compile_edit_section(unlang_t *parent, unlang_compile_t *unlang
        if (fr_type_is_structural(parent_da->type)) {
                map_t *child;
 
-               if (map_afrom_cs(map, &map->child, cs, &t_rules, &t_rules, unlang_fixup_edit, map, 256) < 0) {
+               if (map_afrom_cs_edit(map, &map->child, cs, &t_rules, &t_rules, unlang_fixup_edit, map, 256) < 0) {
                        goto fail;
                }
 
@@ -1988,7 +1988,7 @@ static unlang_t *compile_edit_pair(unlang_t *parent, unlang_compile_t *unlang_ct
        /*
         *      Convert this particular map.
         */
-       if (map_afrom_cp(edit, &map, map_list_tail(&edit->maps), cp, &t_rules, NULL) < 0) {
+       if (map_afrom_cp(edit, &map, map_list_tail(&edit->maps), cp, &t_rules, NULL, true) < 0) {
        fail:
                talloc_free(edit_free);
                return NULL;