instead of "yes" and "no".
this doesn't *always* work. A bare
(bool) true
will result in a box of FR_TYPE_BOOL, with no enumv, and will thus
print as "yes". But we blame value.c for that.
ATTRIBUTE Tmp-Date-8 1758 date
ATTRIBUTE Tmp-Date-9 1759 date
-#
-# Attributes 1850 through 1850 + FR_TYPE_MAX are reserved.
-#
-
ATTRIBUTE Tmp-uint64-0 1760 uint64
ATTRIBUTE Tmp-uint64-1 1761 uint64
ATTRIBUTE Tmp-uint64-2 1762 uint64
ATTRIBUTE Tmp-Ethernet-2 1792 ether
ATTRIBUTE Tmp-Ethernet-3 1793 ether
ATTRIBUTE Tmp-Ethernet-4 1794 ether
+ATTRIBUTE Tmp-Ethernet-5 1795 ether
+ATTRIBUTE Tmp-Ethernet-6 1796 ether
+ATTRIBUTE Tmp-Ethernet-7 1797 ether
+ATTRIBUTE Tmp-Ethernet-8 1798 ether
+ATTRIBUTE Tmp-Ethernet-9 1799 ether
ATTRIBUTE Tmp-Float-0 1880 float32
+ATTRIBUTE Tmp-Float-1 1881 float32
+ATTRIBUTE Tmp-Float-2 1882 float32
+ATTRIBUTE Tmp-Float-3 1883 float32
+ATTRIBUTE Tmp-Float-4 1884 float32
+ATTRIBUTE Tmp-Float-5 1885 float32
+ATTRIBUTE Tmp-Float-6 1886 float32
+ATTRIBUTE Tmp-Float-7 1887 float32
+ATTRIBUTE Tmp-Float-8 1888 float32
+ATTRIBUTE Tmp-Float-9 1889 float32
+
+# Used by xlat expressions to print true/false instead of yes/no
+ATTRIBUTE Expr-Bool-Enum 1890 bool
+VALUE Expr-Bool-Enum true 1
+VALUE Expr-Bool-Enum false 0
ATTRIBUTE Log-Message 1894 string
ATTRIBUTE Log-Level 1895 integer
static fr_dict_attr_t const *attr_packet_authentication_vector;
static fr_dict_attr_t const *attr_packet_type;
-fr_dict_attr_t const *attr_cast_base; /* for xlat_expr.c */
+fr_dict_attr_t const *attr_expr_bool_enum; /* xlat_expr.c */
static fr_dict_attr_autoload_t xlat_eval_dict_attr[] = {
{ .out = &attr_client_ip_address, .name = "Client-IP-Address", .type = FR_TYPE_IPV4_ADDR, .dict = &dict_freeradius },
{ .out = &attr_packet_authentication_vector, .name = "Packet-Authentication-Vector", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
{ .out = &attr_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_radius },
- { .out = &attr_cast_base, .name = "Cast-Base", .type = FR_TYPE_UINT8, .dict = &dict_freeradius },
+ { .out = &attr_expr_bool_enum, .name = "Expr-Bool-Enum", .type = FR_TYPE_BOOL, .dict = &dict_freeradius },
{ NULL }
};
static xlat_action_t xlat_binary_op(TALLOC_CTX *ctx, fr_dcursor_t *out,
UNUSED xlat_ctx_t const *xctx,
request_t *request, fr_value_box_list_t *in,
- fr_token_t op)
+ fr_token_t op,
+ fr_type_t default_type, fr_dict_attr_t const *enumv)
{
int rcode;
fr_value_box_t *dst, *a, *b;
return XLAT_ACTION_FAIL;
}
- rcode = fr_value_calc_binary_op(dst, dst, FR_TYPE_NULL,
+ rcode = fr_value_calc_binary_op(dst, dst, default_type,
fr_dlist_head(&a->vb_group),
op,
fr_dlist_head(&b->vb_group));
return XLAT_ACTION_FAIL;
}
+ /*
+ * Over-write, but only if it's present. Otherwise leave
+ * any existing enum alone.
+ */
+ if (enumv) dst->enumv = enumv;
+
fr_dcursor_append(out, dst);
return XLAT_ACTION_DONE;
}
xlat_ctx_t const *xctx, \
request_t *request, fr_value_box_list_t *in) \
{ \
- return xlat_binary_op(ctx, out, xctx, request, in, _op); \
+ return xlat_binary_op(ctx, out, xctx, request, in, _op, FR_TYPE_NULL, NULL); \
}
XLAT_BINARY_FUNC(op_add, T_ADD)
XLAT_BINARY_FUNC(op_rshift, T_RSHIFT)
XLAT_BINARY_FUNC(op_lshift, T_LSHIFT)
-XLAT_BINARY_FUNC(cmp_eq, T_OP_CMP_EQ)
-XLAT_BINARY_FUNC(cmp_ne, T_OP_NE)
-XLAT_BINARY_FUNC(cmp_lt, T_OP_LT)
-XLAT_BINARY_FUNC(cmp_le, T_OP_LE)
-XLAT_BINARY_FUNC(cmp_gt, T_OP_GT)
-XLAT_BINARY_FUNC(cmp_ge, T_OP_GE)
+#define XLAT_CMP_FUNC(_name, _op) \
+static xlat_action_t xlat_func_ ## _name(TALLOC_CTX *ctx, fr_dcursor_t *out, \
+ xlat_ctx_t const *xctx, \
+ request_t *request, fr_value_box_list_t *in) \
+{ \
+ return xlat_binary_op(ctx, out, xctx, request, in, _op, FR_TYPE_BOOL, attr_expr_bool_enum); \
+}
+
+XLAT_CMP_FUNC(cmp_eq, T_OP_CMP_EQ)
+XLAT_CMP_FUNC(cmp_ne, T_OP_NE)
+XLAT_CMP_FUNC(cmp_lt, T_OP_LT)
+XLAT_CMP_FUNC(cmp_le, T_OP_LE)
+XLAT_CMP_FUNC(cmp_gt, T_OP_GT)
+XLAT_CMP_FUNC(cmp_ge, T_OP_GE)
/*
* Cast to bool for && / ||. The casting rules for expressions /
*/
if (!xlat_logical_match(&result, &rctx->list, inst->sense)) {
done:
- MEM(dst = fr_value_box_alloc(ctx, FR_TYPE_BOOL, NULL, false));
+ MEM(dst = fr_value_box_alloc(ctx, FR_TYPE_BOOL, attr_expr_bool_enum, false));
dst->vb_bool = result;
fr_dcursor_append(out, dst);
fr_value_box_t *dst, *a;
a = fr_dlist_head(in);
- MEM(dst = fr_value_box_alloc(ctx, FR_TYPE_BOOL, NULL, a->tainted));
+ MEM(dst = fr_value_box_alloc(ctx, FR_TYPE_BOOL, attr_expr_bool_enum, a->tainted));
dst->vb_bool = !a->vb_bool;
fr_dcursor_append(out, dst);
/*
* xlat_eval.c
*/
-extern fr_dict_attr_t const *attr_cast_base;
+extern fr_dict_attr_t const *attr_expr_bool_enum;
void xlat_signal(xlat_func_signal_t signal, xlat_exp_t const *exp,
request_t *request, void *rctx, fr_state_signal_t action);
# and then statically evaluated.
#
xlat_purify <ipaddr>127.0.0.1 == "127.0.0.1"
-match yes
+match true
# @todo - why isn't the RHS being purified?
xlat_purify <ipaddr>127.0.0.1 == "%{md4: 127.0.0.1}"
match (127.0.0.1 == %{md4: SELECT user FROM table WHERE user='%{Request[0].User-Name}'})
xlat_purify <ether> 00:11:22:33:44:55 == "00:11:22:33:44:55"
-match yes
+match true
# @todo - why isn't the RHS being purified?
xlat_purify <ether>00:11:22:33:44:55 == "%{md4:00:11:22:33:44:55}"
#
# Tests for boolean data types.
#
+# @todo - we probably want this to use "true", too.
xlat_purify true
match yes
# Both sides static data with a cast: evaluate at parse time.
#
xlat_purify <integer>20 < 100
-match yes
+match true
#
# Both sides literal: evaluate at parse time
#
xlat_purify ('foo' == 'bar')
-match no
+match false
xlat_purify ('foo' < 'bar')
-match no
+match false
xlat_purify ('foo' > 'bar')
-match yes
+match true
xlat_purify ('foo' == 'foo')
-match yes
+match true
#
# @todo - why isn't the RHS being purified?
match ("foo bar" == "%{md4: foo}")
xlat_purify ("foo" == "bar")
-match no
+match false
xlat_purify ("foo" == 'bar')
-match no
+match false
#
# The RHS gets parsed as a VPT_TYPE_DATA, which is
match (&User-Name == "0x544924d05ec4481925ba3749a096a0a7")
xlat_purify <ipaddr>127.0.0.1 == 2130706433
-match yes
+match true
# /32 suffix should be trimmed for this type
xlat_purify <ipaddr>127.0.0.1/32 == 127.0.0.1
-match yes
+match true
xlat_purify <ipaddr>127.0.0.1/327 == 127.0.0.1
match ERROR offset 9: Invalid IPv4 mask length "/327". Should be between 0-32
xlat_purify <ipaddr>127.0.0.1/32 == 127.0.0.1
-match yes
+match true
xlat_purify (/foo/)
match ERROR offset 1: Unexpected regular expression
# The LHS is a string with ASCII 5C 30 30 30 inside of it vs the RHS which should contain ASCII 0.
#
xlat_purify ('i have scary embedded things\000 inside me' == "i have scary embedded things\000 inside me")
-match no
+match false
#
# 'Unknown' attributes which are defined in the main dictionary
# and empty strings
#
xlat_purify ("$ENV{SOMETHING_OR_OTHER}" == '')
-match no
+match false
#
# Attributes with a protocol namespace
#match &User-Name == 'bob'
xlat_purify !(!(0))
-match no
+match false
xlat_purify (true) && (false)
-match no
+match false
#
# More short-circuit evaluations
match (&Framed-IP-Address + 4)
xlat_purify 1 < 4
-match yes
+match true
#
# There's sopme bunch of things to fix here:
match (&Filter-Id == "foo")
xlat_purify "foo" == "bar"
-match no
+match false
# note '/' is a prefix, not "divide by 24".
# and a useless cast is removed
# Logical && and ||
#
xlat_purify 1 < 2 || 4 > 3
-match yes
+match true
xlat_purify 2 || (1 > 4)
-match yes
+match true
xlat_purify &Filter-Id
match &Filter-Id
# useless casts are omitted.
#
xlat_purify 1 < (uint32) 2
-match yes
+match true
#
# @todo - for exec, xlat, etc., if we're doing an existence check of
# This should likely be a parse error at boot time?
#
xlat_purify 1 < 2 < 3
-match yes
+match true
xlat_purify &Service-Type == 1
match (&Service-Type == 1)
match !&User-Name
xlat_purify (1 < 2)
-match yes
+match true
xlat_purify !(1 < 2)
-match no
+match false
xlat_purify !true
-match no
+match false
count
match 69