* Don't keep an intermediate tmpl for xlats. Just hoist
* the xlat to be a child of this node. Exec and regexes
* are left alone, as they are handled by different code.
+ *
+ * However, we also add a cast if the tmpl had a cast.
+ * And if there was no cast, but the input was a string,
+ * then we cast the result to a string, too.
*/
if (tmpl_contains_xlat(vpt) && !tmpl_is_exec(vpt) && !tmpl_contains_regex(vpt)) {
xlat_exp_head_t *xlat = tmpl_xlat(vpt);
+ xlat_exp_t *cast;
+ fr_type_t type;
talloc_steal(node, xlat);
node->fmt = talloc_typed_strdup(node, node->fmt);
node->flags = xlat->flags;
+ if (quote != T_BARE_WORD) {
+ if (tmpl_rules_cast(vpt) != FR_TYPE_NULL) {
+ type = tmpl_rules_cast(vpt);
+ } else {
+ type = FR_TYPE_STRING;
+ }
+
+ MEM(cast = expr_cast_alloc(head, type));
+
+ xlat_func_append_arg(cast, node);
+ node = cast;
+ }
+
} else {
/*
* Else we're not hoisting, set the node to the VPT
xlat_purify (!(&User-Name == &User-Password) || (&Filter-Id == &Reply-Message))
match (!(&User-Name == &User-Password) || (&Filter-Id == &Reply-Message))
+#xlat_purify (!&User-Name == &User-Password || &Filter-Id == &Reply-Message)
+#match (!(&User-Name == &User-Password) || (&Filter-Id == &Reply-Message))
+
# different from the previous ones.
xlat_purify (!((&User-Name == &User-Password) || (&Filter-Id == &Reply-Message)))
match !((&User-Name == &User-Password) || (&Filter-Id == &Reply-Message))
# @todo - yuck. Suppress full path?
#
xlat_purify &Event-Timestamp == "January 1, 2012 %{User-Name}"
-match (&Event-Timestamp == "January 1, 2012 %{Request[0].User-Name}")
+match (&Event-Timestamp == %(cast:string "January 1, 2012 %{Request[0].User-Name}"))
# This one is NOT an expansion, so it's parsed into normal form
xlat_purify &Event-Timestamp == 'January 1 2012'
match true
#
-# @todo - if the types are incompatible, what to do?
+# MD4 hash is not equal to other things
#
-# Cannot compare incompatible types
xlat_purify ("foo" == "%{md4: foo}")
-match NULL
+match false
-#
-# @todo - maybe we just want to allow this?
-#
-# Cannot compare incompatible types
xlat_purify ("foo bar" == "%{md4: foo}")
-match NULL
+match false
xlat_purify ("foo" == "bar")
match false
xlat_purify (&User-Name == "bob")
match (&User-Name == "bob")
+xlat_purify (&User-Name == %{md4: blah})
+match (&User-Name == 0x544924d05ec4481925ba3749a096a0a7)
+
+xlat_purify (&User-Name == (string) %{md4: blah})
+match (&User-Name == 0x544924d05ec4481925ba3749a096a0a7)
+
xlat_purify (&User-Name == "%{md4: blah}")
-match (&User-Name == "0x544924d05ec4481925ba3749a096a0a7")
+match (&User-Name == "TI$\320^\304H\031\%\2727I\240\226\240\247")
xlat_purify <ipaddr>127.0.0.1 == 2130706433
match true
# This used to be expr, but expr isn't a builtin, so it failed...
+#
+# @todo - arguably this is a failed thing, we should get:
+#
+# ERROR: Failed casting 0x002ade8665c69219ca16bd108d92c8d5 to data type uint32: Invalid cast from octets to uint32. Source length 16 is greater than destination type size 4
+#
xlat_purify <integer>"%{md4: 1 + 1}" < &NAS-Port
-match ("0x002ade8665c69219ca16bd108d92c8d5" < &NAS-Port)
+match (%(cast:uint32 "%{md4: 1 + 1}") < &NAS-Port)
#
# The string gets parsed as an IP address.
# but these are allowed
xlat_purify <ether>&Tmp-uint64-0 == "%{module: foo}"
-match ((ether)&Tmp-uint64-0 == "%{module: foo}")
+match ((ether)&Tmp-uint64-0 == %(cast:string "%{module: foo}"))
xlat_purify <ipaddr>&Filter-Id == &Framed-IP-Address
match ((ipaddr)&Filter-Id == &Framed-IP-Address)
#match &Foo-Bar
xlat_purify &Acct-Input-Octets > "%{Session-Timeout}"
-match (&Acct-Input-Octets > "%{Request[0].Session-Timeout}")
+match (&Acct-Input-Octets > %(cast:string "%{Request[0].Session-Timeout}"))
xlat_purify &Acct-Input-Octets > &Session-Timeout
match (&Acct-Input-Octets > &Session-Timeout)
count
-match 300
+match 304