From 39900e5ee2ec39d6cc6771003c02d2ab08848f5e Mon Sep 17 00:00:00 2001 From: "Alan T. DeKok" Date: Tue, 29 Jul 2025 05:38:54 -0400 Subject: [PATCH] cleanups and tests we might as well use "::" for FR_TYPE_ATTR, too. This makes them look and feel like enums, rather than adding extra-special syntax --- src/bin/unit_test_attribute.c | 2 -- src/lib/util/value.c | 65 +++++++++++++++++++++-------------- src/tests/unit/attr.txt | 14 ++++++++ 3 files changed, 54 insertions(+), 27 deletions(-) create mode 100644 src/tests/unit/attr.txt diff --git a/src/bin/unit_test_attribute.c b/src/bin/unit_test_attribute.c index 8ede049f2b..6ca12faf6e 100644 --- a/src/bin/unit_test_attribute.c +++ b/src/bin/unit_test_attribute.c @@ -1111,8 +1111,6 @@ static size_t parse_typed_value(command_result_t *result, command_file_ctx_t *cc enumv = fr_dict_root(dict); } - fprintf(stderr, "PARSE TYPE %s %p\n", fr_type_to_str(type), enumv); - slen = fr_value_box_from_substr(box, box, type, enumv, &sbuff, &value_parse_rules_bareword_unquoted); diff --git a/src/lib/util/value.c b/src/lib/util/value.c index 5edffdb0a5..dbba61b79b 100644 --- a/src/lib/util/value.c +++ b/src/lib/util/value.c @@ -1643,7 +1643,7 @@ ssize_t fr_value_box_to_network(fr_dbuff_t *dbuff, fr_value_box_t const *value) * something special for attributes at other depths. */ if (value->vb_attr->depth != 1) { - fr_strerror_printf("Unsupported depth '%u' for attribute %s", + fr_strerror_printf("Unsupported depth '%u' for encoding attribute %s", value->vb_attr->depth, value->vb_attr->name); return 0; } @@ -1665,7 +1665,7 @@ ssize_t fr_value_box_to_network(fr_dbuff_t *dbuff, fr_value_box_t const *value) break; default: - fr_strerror_printf("Unsupported length '%d' for attribute %s", + fr_strerror_printf("Unsupported length '%d' for decoding attribute %s", value->vb_attr->flags.length, value->vb_attr->name); return 0; } @@ -3758,15 +3758,8 @@ int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, break; /* use generic string/octets stuff below */ case FR_TYPE_ATTR: - if (src->vb_attr->depth != 1) { - fr_strerror_printf("Unsupported depth '%d' for attribute %s", - src->vb_attr->depth, src->vb_attr->name); - return 0; - - } - /* - * Convert it to an integer of the correct lenght. Then, cast it in place. + * Convert it to an integer of the correct length. Then, cast it in place. */ switch (src->vb_attr->flags.length) { case 1: @@ -4996,7 +4989,7 @@ ssize_t fr_value_box_from_substr(TALLOC_CTX *ctx, fr_value_box_t *dst, /* * Lookup any names before continuing */ - if (dst_enumv && dst_enumv->flags.has_value) { + if (dst_enumv && dst_enumv->flags.has_value && (dst_type != FR_TYPE_ATTR)) { size_t name_len; fr_dict_enum_value_t const *enumv; @@ -5473,18 +5466,23 @@ parse: return -1; } - if (!fr_sbuff_next_if_char(&our_in, '@')) { - fr_strerror_const("Expected '@...' for attribute reference"); + fr_value_box_init(dst, dst_type, dst_enumv, false); + + if (!fr_sbuff_adv_past_str_literal(&our_in, "::")) { + fr_strerror_const("Missing '::' for attribute reference"); return -1; } - - fr_value_box_init(dst, dst_type, dst_enumv, false); - slen = fr_dict_attr_by_name_substr(NULL, &dst->vb_attr, dst_enumv, &our_in, rules->terminals); + slen = fr_dict_attr_by_oid_substr(NULL, &dst->vb_attr, dst_enumv, &our_in, rules->terminals); if (slen <= 0) { - fr_strerror_printf("Failed to find the named attribute in %s", dst_enumv->name); - return -2; + slen = fr_dict_attr_by_oid_substr(NULL, &dst->vb_attr, dst_enumv, + &our_in, rules->terminals); + if (slen <= 0) { + fr_strerror_printf("Failed to find the named attribute in %s", dst_enumv->name); + return -2; + } } + fr_assert(dst->vb_attr != NULL); FR_SBUFF_SET_RETURN(in, &our_in); @@ -5762,15 +5760,32 @@ ssize_t fr_value_box_print(fr_sbuff_t *out, fr_value_box_t const *data, fr_sbuff break; case FR_TYPE_ATTR: - if (data->vb_attr->depth != 1) { - fr_strerror_printf("Unsupported depth '%u' for attribute %s", - data->vb_attr->depth, data->vb_attr->name); - return 0; + FR_SBUFF_IN_CHAR_RETURN(&our_out, ':', ':'); + + fr_assert(data->enumv != NULL); + + /* + * No escaping, just dump the name as-is. + */ + if (!e_rules) { + FR_DICT_ATTR_OID_PRINT_RETURN(&our_out, data->enumv, data->vb_attr, false); + break; } - FR_SBUFF_IN_CHAR_RETURN(&our_out, '@'); - FR_SBUFF_IN_ESCAPE_RETURN(&our_out, data->vb_attr->name, - strlen(data->vb_attr->name), e_rules); + /* + * Escaping, use an intermediate buffer. Because + * we can't pipe sbuffs together. + */ + { + fr_sbuff_t *unescaped = NULL; + + FR_SBUFF_TALLOC_THREAD_LOCAL(&unescaped, 256, 4096); + + FR_DICT_ATTR_OID_PRINT_RETURN(unescaped, data->enumv, data->vb_attr, false); + + FR_SBUFF_IN_ESCAPE_RETURN(&our_out, fr_sbuff_start(unescaped), + fr_sbuff_used(unescaped), e_rules); + } break; case FR_TYPE_NULL: diff --git a/src/tests/unit/attr.txt b/src/tests/unit/attr.txt new file mode 100644 index 0000000000..b48924fd3a --- /dev/null +++ b/src/tests/unit/attr.txt @@ -0,0 +1,14 @@ +# +# Parse and print data type 'attribute' +# +proto radius +proto-dictionary radius + +value attribute ::User-Name +match ::User-Name + +value attribute ::26.9.1 +match ::Vendor-Specific.Cisco.AVPair + +count +match 6 -- 2.47.2