RETURN_OK(escaped_len);
}
-/** Parse an reprint and xlat expression expansion
+/** Parse and reprint an xlat expression expansion
*
*/
static size_t command_xlat_expr(command_result_t *result, command_file_ctx_t *cc,
RETURN_OK(escaped_len);
}
+/** Parse, purify, and reprint an xlat expression expansion
+ *
+ */
+static size_t command_xlat_purify(command_result_t *result, command_file_ctx_t *cc,
+ char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
+{
+ ssize_t dec_len;
+ xlat_exp_t *head = NULL;
+ size_t input_len = strlen(in), escaped_len;
+// fr_sbuff_parse_rules_t p_rules = { .escapes = &fr_value_unescape_double };
+ xlat_flags_t flags = {
+ .pure = true,
+ };
+
+ dec_len = xlat_tokenize_expression(cc->tmp_ctx, &head, &flags, &FR_SBUFF_IN(in, input_len), NULL,
+ &(tmpl_attr_rules_t) {
+ .dict_def = cc->tmpl_rules.attr.dict_def ?
+ cc->tmpl_rules.attr.dict_def : cc->config->dict,
+ .allow_unresolved = cc->tmpl_rules.attr.allow_unresolved
+ });
+ if (dec_len <= 0) {
+ fr_strerror_printf_push_head("ERROR offset %d", (int) -dec_len);
+
+ return_error:
+ RETURN_OK_WITH_ERROR();
+ }
+
+ if (((size_t) dec_len != input_len)) {
+ fr_strerror_printf_push_head("Passed in %zu characters, but only parsed %zd characters", input_len, dec_len);
+ goto return_error;
+ }
+
+ escaped_len = xlat_print(&FR_SBUFF_OUT(data, COMMAND_OUTPUT_MAX), head, &fr_value_escape_double);
+ RETURN_OK(escaped_len);
+}
+
+
/** Parse an reprint and xlat argv expansion
*
*/
.description = "Parse then print an xlat expression, writing the normalised xlat expansion to the data buffer"
}},
+ { L("xlat_purify "), &(command_entry_t){
+ .func = command_xlat_purify,
+ .usage = "xlat_purify <string>",
+ .description = "Parse, purify, then print an xlat expression, writing the normalised xlat expansion to the data buffer"
+ }},
+
};
static size_t commands_len = NUM_ELEMENTS(commands);
--- /dev/null
+proto-dictionary radius
+
+#
+# xlat_expr, but purified
+#
+xlat_purify 3 + 4
+match 7
+
+xlat_purify 3 * 4
+match 12
+
+xlat_purify 2 + 3 * 4
+match 14
+
+xlat_purify 2 + 3 * 4 + 5
+match 19
+
+# Same as above with brackets
+xlat_purify 2 + (3 * 4) + 5
+match 19
+
+# not the same
+xlat_purify (2 + 3) * (4 + 5)
+match 45
+
+xlat_purify (2 + 3) * 4 + 5
+match 25
+
+xlat_purify &NAS-Port + 5
+match (%{NAS-Port} + 5)
+
+xlat_purify &Framed-IP-Address & 0xffff0000
+match (%{Framed-IP-Address} & 255.255.0.0)
+
+xlat_purify %{Framed-IP-Address} + 4
+match (%{Framed-IP-Address} + 0.0.0.4)
+
+xlat_purify 1 < 4
+match yes
+
+xlat_purify &Service-Type == Framed-User
+match (%{Service-Type} == Framed-User)
+
+xlat_purify 1 + (&Service-Type == Framed-User)
+match (1 + (%{Service-Type} == Framed-User))
+
+#
+# Strings of various forms
+#
+xlat_purify &Filter-Id == "foo"
+match (%{Filter-Id} == \"foo\")
+
+xlat_purify "foo" == "bar"
+match no
+
+# note '/' is a prefix, not "divide by 24".
+# and a useless cast is removed
+xlat_purify &Framed-IP-Address < (ipv4prefix) 192.168.0.0/24
+match (%{Framed-IP-Address} < 192.168.0.0/24)
+
+xlat_purify &Framed-IP-Address < (ipv4prefix) 192.168.0.0
+match (%{Framed-IP-Address} < 192.168.0.0/32)
+
+#
+# For IP addresses, the other side is automatically upcast to a prefix
+#
+
+#xlat_purify &Framed-IP-Address < 192.168.0.0/24
+#match %(cmp_lt:%{Framed-IP-Address}%(cast:ipv4prefix 192.168.0.0/32))
+
+# same as above, but swap the order
+xlat_purify (ipv4prefix) 192.168.0.0/24 > &Framed-IP-Address
+match (192.168.0.0/24 > %{Framed-IP-Address})
+
+#
+# Logical && and ||
+#
+xlat_purify 1 < 2 || 4 > 3
+match yes
+
+xlat_purify 2 || (1 > 4)
+match yes
+
+xlat_purify &Filter-Id
+match %{Filter-Id}
+
+xlat_purify %{md5:foo} + "foo"
+match (%{md5:foo} + \"foo\")
+
+# We can name the xlat's, tho we don't need to
+xlat_purify %(op_add:4 3) + 6
+match ((4 + 3) + 6)
+
+
+#
+# useless casts are omitted.
+#
+xlat_purify 1 < (uint32) 2
+match yes
+
+#
+# @todo - for exec, xlat, etc., if we're doing an existence check of
+# string / octets, then the check is for "length>0", NOT for parsing
+# the contents of the data type.
+#
+
+#
+# This should likely be a parse error at boot time?
+#
+xlat_purify 1 < 2 < 3
+match ERROR offset 9: Cannot compare incompatible types (bool)... < (int64)...
+
+count
+match 51