From: Alan T. DeKok Date: Thu, 26 May 2022 18:14:54 +0000 (-0400) Subject: allow comparisons to print "true" and "false" X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bc657f171c39e4f5aa93f98011ece89bee49fb1c;p=thirdparty%2Ffreeradius-server.git allow comparisons to print "true" and "false" 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. --- diff --git a/share/dictionary/freeradius/dictionary.freeradius.internal b/share/dictionary/freeradius/dictionary.freeradius.internal index f11c08d1ebd..96fd37e01be 100644 --- a/share/dictionary/freeradius/dictionary.freeradius.internal +++ b/share/dictionary/freeradius/dictionary.freeradius.internal @@ -357,10 +357,6 @@ ATTRIBUTE Tmp-Date-7 1757 date 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 @@ -399,8 +395,27 @@ ATTRIBUTE Tmp-Ethernet-1 1791 ether 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 diff --git a/src/lib/unlang/xlat_eval.c b/src/lib/unlang/xlat_eval.c index ab6b01eee44..f87f5575fbc 100644 --- a/src/lib/unlang/xlat_eval.c +++ b/src/lib/unlang/xlat_eval.c @@ -60,7 +60,7 @@ static fr_dict_attr_t const *attr_virtual_server; 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 }, @@ -77,7 +77,7 @@ static fr_dict_attr_autoload_t xlat_eval_dict_attr[] = { { .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 } }; diff --git a/src/lib/unlang/xlat_expr.c b/src/lib/unlang/xlat_expr.c index da8a6e39b62..c18a454e661 100644 --- a/src/lib/unlang/xlat_expr.c +++ b/src/lib/unlang/xlat_expr.c @@ -236,7 +236,8 @@ static xlat_arg_parser_t const binary_op_xlat_args[] = { 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; @@ -272,7 +273,7 @@ static xlat_action_t xlat_binary_op(TALLOC_CTX *ctx, fr_dcursor_t *out, 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)); @@ -281,6 +282,12 @@ static xlat_action_t xlat_binary_op(TALLOC_CTX *ctx, fr_dcursor_t *out, 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; } @@ -290,7 +297,7 @@ 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); \ + return xlat_binary_op(ctx, out, xctx, request, in, _op, FR_TYPE_NULL, NULL); \ } XLAT_BINARY_FUNC(op_add, T_ADD) @@ -303,12 +310,20 @@ XLAT_BINARY_FUNC(op_xor, T_XOR) 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 / @@ -476,7 +491,7 @@ static xlat_action_t xlat_logical_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, */ 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); @@ -540,7 +555,7 @@ static xlat_action_t xlat_func_unary_not(TALLOC_CTX *ctx, fr_dcursor_t *out, 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); diff --git a/src/lib/unlang/xlat_priv.h b/src/lib/unlang/xlat_priv.h index a80270bef01..c4d5cab4b59 100644 --- a/src/lib/unlang/xlat_priv.h +++ b/src/lib/unlang/xlat_priv.h @@ -301,7 +301,7 @@ xlat_t *xlat_func_find(char const *name, ssize_t namelen); /* * 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); diff --git a/src/tests/unit/xlat/cond_base.txt b/src/tests/unit/xlat/cond_base.txt index 8775b910d2d..b796c8b78f0 100644 --- a/src/tests/unit/xlat/cond_base.txt +++ b/src/tests/unit/xlat/cond_base.txt @@ -250,7 +250,7 @@ match ERROR offset 1: Failed parsing string as type 'uint32' # and then statically evaluated. # xlat_purify 127.0.0.1 == "127.0.0.1" -match yes +match true # @todo - why isn't the RHS being purified? xlat_purify 127.0.0.1 == "%{md4: 127.0.0.1}" @@ -269,7 +269,7 @@ xlat_purify 127.0.0.1 == %{md4: SELECT user FROM table WHERE user='%{Use match (127.0.0.1 == %{md4: SELECT user FROM table WHERE user='%{Request[0].User-Name}'}) xlat_purify 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 00:11:22:33:44:55 == "%{md4:00:11:22:33:44:55}" @@ -281,6 +281,7 @@ match ERROR offset 12: Missing separator, expected ':' # # Tests for boolean data types. # +# @todo - we probably want this to use "true", too. xlat_purify true match yes @@ -314,22 +315,22 @@ match (yes || (&User-Name == "bob")) # Both sides static data with a cast: evaluate at parse time. # xlat_purify 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? @@ -346,10 +347,10 @@ xlat_purify ("foo bar" == "%{md4: foo}") 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 @@ -363,17 +364,17 @@ xlat_purify (&User-Name == "%{md4: blah}") match (&User-Name == "0x544924d05ec4481925ba3749a096a0a7") xlat_purify 127.0.0.1 == 2130706433 -match yes +match true # /32 suffix should be trimmed for this type xlat_purify 127.0.0.1/32 == 127.0.0.1 -match yes +match true xlat_purify 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 127.0.0.1/32 == 127.0.0.1 -match yes +match true xlat_purify (/foo/) match ERROR offset 1: Unexpected regular expression @@ -594,7 +595,7 @@ match ERROR offset 1: Attribute 'not' not found. Searched in: RADIUS, internal: # 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 @@ -657,7 +658,7 @@ match &reply # and empty strings # xlat_purify ("$ENV{SOMETHING_OR_OTHER}" == '') -match no +match false # # Attributes with a protocol namespace @@ -670,10 +671,10 @@ match (&radius.User-Name == 'bob') #match &User-Name == 'bob' xlat_purify !(!(0)) -match no +match false xlat_purify (true) && (false) -match no +match false # # More short-circuit evaluations diff --git a/src/tests/unit/xlat/purify.txt b/src/tests/unit/xlat/purify.txt index b4c25b82439..420d9e456dd 100644 --- a/src/tests/unit/xlat/purify.txt +++ b/src/tests/unit/xlat/purify.txt @@ -39,7 +39,7 @@ xlat_purify &Framed-IP-Address + 4 match (&Framed-IP-Address + 4) xlat_purify 1 < 4 -match yes +match true # # There's sopme bunch of things to fix here: @@ -60,7 +60,7 @@ xlat_purify &Filter-Id == "foo" 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 @@ -85,10 +85,10 @@ match (192.168.0.0/24 > &Framed-IP-Address) # 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 @@ -117,7 +117,7 @@ match 13 # 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 @@ -129,7 +129,7 @@ match yes # 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) @@ -153,13 +153,13 @@ xlat_purify !&User-Name 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