From: Arran Cudbard-Bell Date: Sun, 4 Apr 2021 21:48:10 +0000 (+0100) Subject: Add type check macros X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=818d4381db2c3ede4c56d0f76c6939d7792fb897;p=thirdparty%2Ffreeradius-server.git Add type check macros --- diff --git a/src/bin/unit_test_attribute.c b/src/bin/unit_test_attribute.c index d6cdc296ba..875c677617 100644 --- a/src/bin/unit_test_attribute.c +++ b/src/bin/unit_test_attribute.c @@ -2206,7 +2206,7 @@ static size_t command_value_box_normalise(command_result_t *result, UNUSED comma * Parse data types */ type = fr_table_value_by_longest_prefix(&match_len, fr_value_box_type_table, in, strlen(in), FR_TYPE_NULL); - if (type == FR_TYPE_NULL) { + if (fr_type_is_null(type)) { RETURN_PARSE_ERROR(0); } p = in + match_len; diff --git a/src/lib/server/command.c b/src/lib/server/command.c index 9d1a88c21d..26ea204514 100644 --- a/src/lib/server/command.c +++ b/src/lib/server/command.c @@ -244,9 +244,11 @@ static bool fr_command_valid_syntax(fr_cmd_argv_t *argv) type = fr_table_value_by_str(fr_value_box_type_table, argv->name, FR_TYPE_NULL); switch (type) { - case FR_TYPE_VALUE_BOX: - case FR_TYPE_BAD: + case FR_TYPE_MAX: + case FR_TYPE_NULL: case FR_TYPE_STRUCTURAL: + case FR_TYPE_VALUE_BOX: + case FR_TYPE_VOID: fr_strerror_printf("Syntax command '%s' has unknown data type", argv->name); return false; diff --git a/src/lib/server/cond_eval.c b/src/lib/server/cond_eval.c index 0a56604e00..8a0f2a1442 100644 --- a/src/lib/server/cond_eval.c +++ b/src/lib/server/cond_eval.c @@ -144,7 +144,7 @@ static int cond_eval_tmpl(request_t *request, tmpl_t const *in, fr_value_box_t * /* * No cast means that it's an existence check. */ - if (vpt->cast == FR_TYPE_NULL) { + if (fr_type_is_null(vpt->cast)) { return (tmpl_find_vp(NULL, request, vpt) == 0); } @@ -184,7 +184,7 @@ static int cond_eval_tmpl(request_t *request, tmpl_t const *in, fr_value_box_t * * We don't yet have xlats returning lists of * value boxes, so there's an assert. */ - if (vpt->cast == FR_TYPE_NULL) { + if (fr_type_is_null(vpt->cast)) { switch (box->type) { case FR_TYPE_STRING: case FR_TYPE_OCTETS: @@ -386,7 +386,7 @@ static int cond_realize_tmpl(request_t *request, * converted to the correct thing. */ case TMPL_TYPE_DATA: - fr_assert((in->cast == FR_TYPE_NULL) || (in->cast == tmpl_value_type(in))); + fr_assert((fr_type_is_null(in->cast)) || (in->cast == tmpl_value_type(in))); *out = tmpl_value(in); fr_assert(!async); return 0; @@ -523,7 +523,7 @@ static int cond_compare_attrs(request_t *request, fr_value_box_t *lhs, map_t con fr_value_box_t *rhs, rhs_cast; fr_dict_attr_t const *da = NULL; - if (tmpl_is_attr(map->lhs) && (map->lhs->cast == FR_TYPE_NULL)) da = tmpl_da(map->lhs); + if (tmpl_is_attr(map->lhs) && fr_type_is_null(map->lhs->cast)) da = tmpl_da(map->lhs); rhs = NULL; /* shut up clang scan */ fr_value_box_clear(&rhs_cast); diff --git a/src/lib/server/cond_tokenize.c b/src/lib/server/cond_tokenize.c index 255862a581..2399cb481e 100644 --- a/src/lib/server/cond_tokenize.c +++ b/src/lib/server/cond_tokenize.c @@ -226,7 +226,7 @@ static int cond_cast_tmpl(tmpl_t *vpt, fr_type_t *p_type, tmpl_t *other) * Which means we no longer need the cast. */ fr_assert(tmpl_is_data(vpt)); - fr_assert((vpt->cast == FR_TYPE_NULL) || (vpt->cast == tmpl_value_type(vpt))); + fr_assert(fr_type_is_null(vpt->cast) || (vpt->cast == tmpl_value_type(vpt))); (void) tmpl_cast_set(vpt, FR_TYPE_NULL); return 0; } @@ -247,7 +247,7 @@ int fr_cond_promote_types(fr_cond_t *c, fr_sbuff_t *in, fr_sbuff_marker_t *m_lhs if (tmpl_contains_regex(c->data.map->rhs)) { fr_assert((c->data.map->op == T_OP_REG_EQ) || (c->data.map->op == T_OP_REG_NE)); fr_assert(!tmpl_is_list(c->data.map->lhs)); - fr_assert(c->data.map->rhs->cast == FR_TYPE_NULL); + fr_assert(fr_type_is_null(c->data.map->rhs->cast)); /* * Can't use casts with regular expressions, on @@ -422,7 +422,7 @@ int fr_cond_promote_types(fr_cond_t *c, fr_sbuff_t *in, fr_sbuff_marker_t *m_lhs * Both sides are have unresolved issues. Leave * them alone... */ - if (lhs_type == FR_TYPE_NULL) { + if (fr_type_is_null(lhs_type)) { /* * If we still have unresolved data, then * ensure that they are converted to @@ -457,12 +457,12 @@ int fr_cond_promote_types(fr_cond_t *c, fr_sbuff_t *in, fr_sbuff_marker_t *m_lhs * because we will just check it again after the pass2 * fixups. */ - if ((lhs_type != FR_TYPE_NULL) && (rhs_type == FR_TYPE_NULL)) { + if (!fr_type_is_null(lhs_type) && fr_type_is_null(rhs_type)) { cast_type = lhs_type; goto set_types; } - if ((rhs_type != FR_TYPE_NULL) && (lhs_type == FR_TYPE_NULL)) { + if (!fr_type_is_null(rhs_type) && fr_type_is_null(lhs_type)) { cast_type = rhs_type; goto set_types; } @@ -928,7 +928,7 @@ static int cond_forbid_groups(tmpl_t *vpt, fr_sbuff_t *in, fr_sbuff_marker_t *m_ if (!tmpl_is_attr(vpt)) return 0; switch (tmpl_da(vpt)->type) { - case FR_TYPE_VALUE: + case FR_TYPE_VALUES: break; default: diff --git a/src/lib/server/tmpl_tokenize.c b/src/lib/server/tmpl_tokenize.c index e29ed42ea6..fd4d0f21f3 100644 --- a/src/lib/server/tmpl_tokenize.c +++ b/src/lib/server/tmpl_tokenize.c @@ -2781,7 +2781,7 @@ ssize_t tmpl_cast_from_substr(fr_type_t *out, fr_sbuff_t *in) if (fr_sbuff_next_if_char(&our_in, '<')) { fr_sbuff_marker(&m, &our_in); fr_sbuff_out_by_longest_prefix(&slen, &cast, fr_value_box_type_table, &our_in, FR_TYPE_NULL); - if (cast == FR_TYPE_NULL) { + if (fr_type_is_null(cast)) { fr_strerror_const("Unknown data type"); FR_SBUFF_ERROR_RETURN(&our_in); } @@ -2828,7 +2828,7 @@ int tmpl_cast_set(tmpl_t *vpt, fr_type_t dst_type) * Only "base" data types are allowed. Structural types * and horrid WiMAX crap is forbidden. */ - case FR_TYPE_VALUE: + case FR_TYPE_VALUES: break; } @@ -4269,7 +4269,7 @@ void tmpl_verify(char const *file, int line, tmpl_t const *vpt) file, line); } - if (tmpl_value_type(vpt) == FR_TYPE_NULL) { + if (fr_type_is_null(tmpl_value_type(vpt))) { fr_fatal_assert_fail("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_DATA type was " "FR_TYPE_NULL (uninitialised)", file, line); } @@ -4386,7 +4386,7 @@ ssize_t tmpl_preparse(char const **out, size_t *outlen, char const *in, size_t i } cast = fr_table_value_by_substr(fr_value_box_type_table, p, q - p, FR_TYPE_NULL); - if (cast == FR_TYPE_NULL) { + if (fr_type_is_null(cast)) { return_P("Unknown data type"); } diff --git a/src/lib/unlang/compile.c b/src/lib/unlang/compile.c index 00984c1e55..cea14344f0 100644 --- a/src/lib/unlang/compile.c +++ b/src/lib/unlang/compile.c @@ -2160,7 +2160,7 @@ static unlang_t *compile_case(unlang_t *parent, unlang_compile_t *unlang_ctx, CO if (tmpl_is_attr(switch_gext->vpt)) da = tmpl_da(switch_gext->vpt); - if ((cast_type == FR_TYPE_NULL) && da) cast_type = da->type; + if (fr_type_is_null(cast_type) && da) cast_type = da->type; if (tmpl_cast_in_place(vpt, cast_type, da) < 0) { cf_log_perr(cs, "Invalid argument for 'case' statement"); diff --git a/src/lib/unlang/xlat_builtin.c b/src/lib/unlang/xlat_builtin.c index 3e9a3f1a8a..95437b6362 100644 --- a/src/lib/unlang/xlat_builtin.c +++ b/src/lib/unlang/xlat_builtin.c @@ -331,7 +331,7 @@ static inline int xlat_arg_parser_validate(xlat_arg_parser_t const *arg, bool la } switch (arg->type) { - case FR_TYPE_VALUE: + case FR_TYPE_VALUES: case FR_TYPE_VOID: break; @@ -801,7 +801,7 @@ static xlat_action_t xlat_func_debug(TALLOC_CTX *ctx, fr_dcursor_t *out, /* * Assume we just want to get the current value and NOT set it to 0 */ - if (in_head->type == FR_TYPE_NULL) goto done; + if (fr_box_is_null(in_head)) goto done; level = in_head->vb_int8; if (level == 0) { diff --git a/src/lib/util/dict_tokenize.c b/src/lib/util/dict_tokenize.c index 9d56b8666f..2e5a7d3df6 100644 --- a/src/lib/util/dict_tokenize.c +++ b/src/lib/util/dict_tokenize.c @@ -270,7 +270,7 @@ static int dict_process_type_field(dict_tokenize_ctx_t *ctx, char const *name, f * find the type of the attribute. */ type = fr_table_value_by_str(fr_value_box_type_table, name, FR_TYPE_NULL); - if (type == FR_TYPE_NULL) { + if (fr_type_is_null(type)) { fr_strerror_printf("Unknown data type '%s'", name); return -1; } @@ -383,7 +383,7 @@ static int dict_process_flag_field(dict_tokenize_ctx_t *ctx, char *name, fr_type fr_type_t subtype; subtype = fr_table_value_by_str(fr_value_box_type_table, name, FR_TYPE_NULL); - if (subtype == FR_TYPE_NULL) { + if (fr_type_is_null(subtype)) { unknown_type: fr_strerror_printf("Unknown or unsupported %s type '%s'", fr_table_str_by_value(fr_value_box_type_table, type, ""), diff --git a/src/lib/util/dict_validate.c b/src/lib/util/dict_validate.c index 9a9b01284b..7f5630ed72 100644 --- a/src/lib/util/dict_validate.c +++ b/src/lib/util/dict_validate.c @@ -507,7 +507,7 @@ bool dict_attr_flags_valid(fr_dict_t *dict, fr_dict_attr_t const *parent, * the first member. */ if (sibling->flags.length == 0) switch (sibling->type) { - case FR_TYPE_VALUE: + case FR_TYPE_VALUES: break; default: diff --git a/src/lib/util/struct.c b/src/lib/util/struct.c index 292d1a5ce2..48574bd180 100644 --- a/src/lib/util/struct.c +++ b/src/lib/util/struct.c @@ -239,7 +239,7 @@ ssize_t fr_struct_from_network(TALLOC_CTX *ctx, fr_dcursor_t *cursor, FR_PROTO_TRACE("fr_struct_from_network - unknown child type"); goto unknown; - case FR_TYPE_VALUE: + case FR_TYPE_VALUES: break; } diff --git a/src/lib/util/types.c b/src/lib/util/types.c index 8769656c28..ec092bc65c 100644 --- a/src/lib/util/types.c +++ b/src/lib/util/types.c @@ -26,6 +26,25 @@ RCSID("$Id$") #include #include +#define ARRAY_BEG(_type) { [_type] = true, +#define ARRAY_MID(_type) [_type] = true, +#define ARRAY_END(_type) [_type] = true } + +bool const fr_type_integer_except_bool[FR_TYPE_MAX + 1] = FR_TYPE_INTEGER_EXCEPT_BOOL_DEF(ARRAY_BEG, ARRAY_MID, ARRAY_END); +bool const fr_type_integer[FR_TYPE_MAX + 1] = FR_TYPE_INTEGER_DEF(ARRAY_BEG, ARRAY_MID, ARRAY_END); +bool const fr_type_numeric[FR_TYPE_MAX + 1] = FR_TYPE_NUMERIC_DEF(ARRAY_BEG, ARRAY_MID, ARRAY_END); + +bool const fr_type_ip[FR_TYPE_MAX + 1] = FR_TYPE_IP_DEF(ARRAY_BEG, ARRAY_MID, ARRAY_END); + +bool const fr_type_fixed_size[FR_TYPE_MAX + 1] = FR_TYPE_FIXED_SIZE_DEF(ARRAY_BEG, ARRAY_MID, ARRAY_END); +bool const fr_type_variable_size[FR_TYPE_MAX + 1] = FR_TYPE_VARIABLE_SIZE_DEF(ARRAY_BEG, ARRAY_MID, ARRAY_END); +bool const fr_type_values[FR_TYPE_MAX + 1] = FR_TYPE_VALUES_DEF(ARRAY_BEG, ARRAY_MID, ARRAY_END); +bool const fr_type_quoted[FR_TYPE_MAX + 1] = FR_TYPE_QUOTED_DEF(ARRAY_BEG, ARRAY_MID, ARRAY_END); + +bool const fr_type_structural_except_vsa[FR_TYPE_MAX + 1] = FR_TYPE_STRUCTURAL_EXCEPT_VSA_DEF(ARRAY_BEG, ARRAY_MID, ARRAY_END); +bool const fr_type_structural[FR_TYPE_MAX + 1] = FR_TYPE_STRUCTURAL_DEF(ARRAY_BEG, ARRAY_MID, ARRAY_END); +bool const fr_type_non_values[FR_TYPE_MAX + 1] = FR_TYPE_NON_VALUES_DEF(ARRAY_BEG, ARRAY_MID, ARRAY_END); + #define O(_x) [FR_TYPE_ ## _x] = true /* diff --git a/src/lib/util/types.h b/src/lib/util/types.h index 4a75026b89..07cb450c25 100644 --- a/src/lib/util/types.h +++ b/src/lib/util/types.h @@ -19,6 +19,7 @@ * * @file src/lib/util/types.h * + * @copyright 2021 Arran Cudbard-Bell (a.cudbardb@freeradius.org) * @copyright 2017 The FreeRADIUS server project */ RCSIDH(types_h, "$Id$") @@ -84,138 +85,252 @@ typedef enum { FR_TYPE_MAX //!< Number of defined data types. } fr_type_t; -/** Match all fixed length types in case statements - * - * @note This should be used for switch statements in printing and casting - * functions that need to deal with all types representing values - */ -#define FR_TYPE_FIXED_SIZE \ - FR_TYPE_IPV4_ADDR: \ - case FR_TYPE_IPV4_PREFIX: \ - case FR_TYPE_IPV6_ADDR: \ - case FR_TYPE_IPV6_PREFIX: \ - case FR_TYPE_IFID: \ - case FR_TYPE_COMBO_IP_ADDR: \ - case FR_TYPE_COMBO_IP_PREFIX: \ - case FR_TYPE_ETHERNET: \ - case FR_TYPE_BOOL: \ - case FR_TYPE_UINT8: \ - case FR_TYPE_UINT16: \ - case FR_TYPE_UINT32: \ - case FR_TYPE_UINT64: \ - case FR_TYPE_INT8: \ - case FR_TYPE_INT16: \ - case FR_TYPE_INT32: \ - case FR_TYPE_INT64: \ - case FR_TYPE_FLOAT32: \ - case FR_TYPE_FLOAT64: \ - case FR_TYPE_DATE: \ - case FR_TYPE_TIME_DELTA: \ - case FR_TYPE_SIZE - -#define FR_TYPE_INTEGER_EXCEPT_BOOL \ - FR_TYPE_UINT8: \ - case FR_TYPE_UINT16: \ - case FR_TYPE_UINT32: \ - case FR_TYPE_UINT64: \ - case FR_TYPE_INT8: \ - case FR_TYPE_INT16: \ - case FR_TYPE_INT32: \ - case FR_TYPE_INT64: \ - case FR_TYPE_DATE: \ - case FR_TYPE_TIME_DELTA: \ - case FR_TYPE_SIZE +/** @name Type grouping macros + * + * @{ + */ + +/** All integer types except bool + * + * - Integers + * - Dates + * - Delta + */ +#define FR_TYPE_INTEGER_EXCEPT_BOOL_DEF(_beg, _mid, _end) \ + _beg(FR_TYPE_UINT8) \ + _mid(FR_TYPE_UINT16) \ + _mid(FR_TYPE_UINT32) \ + _mid(FR_TYPE_UINT64) \ + _mid(FR_TYPE_INT8) \ + _mid(FR_TYPE_INT16) \ + _mid(FR_TYPE_INT32) \ + _mid(FR_TYPE_INT64) \ + _mid(FR_TYPE_DATE) \ + _mid(FR_TYPE_TIME_DELTA) \ + _end(FR_TYPE_SIZE) /** Signed or unsigned integers * + * - Integers + * - Dates + * - Deltas + * - Bools */ -#define FR_TYPE_INTEGER \ - FR_TYPE_BOOL: \ - case FR_TYPE_INTEGER_EXCEPT_BOOL \ +#define FR_TYPE_INTEGER_DEF(_beg, _mid, _end) \ + _beg(FR_TYPE_BOOL) \ + FR_TYPE_INTEGER_EXCEPT_BOOL_DEF(_mid, _mid, _end) /** Naturally numeric types * + * - Integers + * - Dates + * - Deltas + * - Bools + * - Floats */ -#define FR_TYPE_NUMERIC \ - FR_TYPE_INTEGER: \ - case FR_TYPE_FLOAT32: \ - case FR_TYPE_FLOAT64 \ +#define FR_TYPE_NUMERIC_DEF(_beg, _mid, _end) \ + _beg(FR_TYPE_FLOAT32) \ + _mid(FR_TYPE_FLOAT64) \ + FR_TYPE_INTEGER_DEF(_mid, _mid, _end) -/** Match all variable length types in case statements +/** Types which can fit in an #fr_ipaddr_t * - * @note This should be used for switch statements in printing and casting - * functions that need to deal with all types representing values + * - IPv4 addresses + * - IPv6 addresses + * - IPv4 prefix + * - IPv6 prefix */ -#define FR_TYPE_VARIABLE_SIZE \ - FR_TYPE_STRING: \ - case FR_TYPE_OCTETS +#define FR_TYPE_IP_DEF(_beg, _mid, _end) \ + _beg(FR_TYPE_IPV4_ADDR) \ + _mid(FR_TYPE_IPV4_PREFIX) \ + _mid(FR_TYPE_IPV6_ADDR) \ + _end(FR_TYPE_IPV6_PREFIX) +/** Match all fixed length types + * + * - Network addresses + * - Integers + * - All other fixed types + */ +#define FR_TYPE_FIXED_SIZE_DEF(_beg, _mid, _end) \ + _beg(FR_TYPE_ETHERNET) \ + _mid(FR_TYPE_IFID) \ + FR_TYPE_IP_DEF(_mid, _mid, _mid) \ + FR_TYPE_NUMERIC_DEF(_mid, _mid, _end) + +/** Match all variable length types + * + * - Strings + * - Octets + */ +#define FR_TYPE_VARIABLE_SIZE_DEF(_beg, _mid, _end) \ + _beg(FR_TYPE_STRING) \ + _end(FR_TYPE_OCTETS) + +/** Types which represent concrete values + * + * - Network addresses + * - Strings + * - Octets + * - Numbers + */ +#define FR_TYPE_VALUES_DEF(_beg, _mid, _end) \ + _beg(FR_TYPE_ETHERNET) \ + _mid(FR_TYPE_IFID) \ + FR_TYPE_IP_DEF(_mid, _mid, _mid) \ + FR_TYPE_VARIABLE_SIZE_DEF(_mid, _mid, _mid) \ + FR_TYPE_NUMERIC_DEF(_mid, _mid, _end) -#define FR_TYPE_BAD \ - FR_TYPE_MAX: \ - case FR_TYPE_NULL +/** Types which should be wrapped in double quotes when printed + * + * - Strings + * - Dates + */ +#define FR_TYPE_QUOTED_DEF(_beg, _mid, _end) \ + _beg(FR_TYPE_STRING) \ + _end(FR_TYPE_DATE) /** Stupid hack for things which produce special error messages for VSAs * - * @note This should be used for switch statements in printing and casting - * functions that need to deal with all types representing values + * - Groups + * - Structs + * - TLVs + * - Vendors */ -#define FR_TYPE_STRUCTURAL_EXCEPT_VSA \ - FR_TYPE_GROUP: \ - case FR_TYPE_VENDOR: \ - case FR_TYPE_TLV: \ - case FR_TYPE_STRUCT +#define FR_TYPE_STRUCTURAL_EXCEPT_VSA_DEF(_beg, _mid, _end) \ + _beg(FR_TYPE_GROUP) \ + _mid(FR_TYPE_STRUCT) \ + _mid(FR_TYPE_TLV) \ + _end(FR_TYPE_VENDOR) /** Match all non value types in case statements * - * @note This should be used for switch statements in printing and casting - * functions that need to deal with all types representing values + * - Groups + * - Structs + * - TLVs + * - Vendors + * - VSAs (i.e. a container of vendors) */ -#define FR_TYPE_STRUCTURAL \ - FR_TYPE_STRUCTURAL_EXCEPT_VSA: \ - case FR_TYPE_VSA \ - +#define FR_TYPE_STRUCTURAL_DEF(_beg, _mid, _end) \ + _beg(FR_TYPE_VSA) \ + FR_TYPE_STRUCTURAL_EXCEPT_VSA_DEF(_mid, _mid, _end) /** Types which do not represent concrete values * + * - Combo IPs + * - Combo prefixes + * - Structural + * - Boxes (can represent any type) + * - Void (opaque types) + * - Null (lack of value) + * - Invalid values */ -#define FR_TYPE_NON_VALUES \ - FR_TYPE_COMBO_IP_ADDR: \ - case FR_TYPE_COMBO_IP_PREFIX: \ - case FR_TYPE_STRUCTURAL: \ - case FR_TYPE_VALUE_BOX: \ - case FR_TYPE_VOID: \ - case FR_TYPE_BAD - -/** Types which represent concrete values +#define FR_TYPE_NON_VALUES_DEF(_beg, _mid, _end) \ + _beg(FR_TYPE_COMBO_IP_ADDR) \ + _mid(FR_TYPE_COMBO_IP_PREFIX) \ + _mid(FR_TYPE_VALUE_BOX) \ + _mid(FR_TYPE_VOID) \ + _mid(FR_TYPE_NULL) \ + _mid(FR_TYPE_MAX) \ + FR_TYPE_STRUCTURAL_DEF(_mid, _mid, _end) +/** @} */ + +/** @name Macros that emit multiple case statements to group types * + * @{ */ -#define FR_TYPE_VALUE \ - FR_TYPE_NUMERIC: \ - case FR_TYPE_STRING: \ - case FR_TYPE_OCTETS: \ - case FR_TYPE_IPV4_ADDR: \ - case FR_TYPE_IPV4_PREFIX: \ - case FR_TYPE_IPV6_ADDR: \ - case FR_TYPE_IPV6_PREFIX: \ - case FR_TYPE_ETHERNET: \ - case FR_TYPE_IFID +#define CASE_BEG(_type) _type: +#define CASE_MID(_type) case _type: +#define CASE_END(_type) case _type -/** Types which can fit in an #fr_ipaddr_t +#define FR_TYPE_INTEGER_EXCEPT_BOOL FR_TYPE_INTEGER_EXCEPT_BOOL_DEF(CASE_BEG, CASE_MID, CASE_END) +#define FR_TYPE_INTEGER FR_TYPE_INTEGER_DEF(CASE_BEG, CASE_MID, CASE_END) +#define FR_TYPE_NUMERIC FR_TYPE_NUMERIC_DEF(CASE_BEG, CASE_MID, CASE_END) + +#define FR_TYPE_IP FR_TYPE_IP_DEF(CASE_BEG, CASE_MID, CASE_END) + +#define FR_TYPE_FIXED_SIZE FR_TYPE_FIXED_SIZE_DEF(CASE_BEG, CASE_MID, CASE_END) +#define FR_TYPE_VARIABLE_SIZE FR_TYPE_VARIABLE_SIZE_DEF(CASE_BEG, CASE_MID, CASE_END) +#define FR_TYPE_VALUES FR_TYPE_VALUES_DEF(CASE_BEG, CASE_MID, CASE_END) +#define FR_TYPE_QUOTED FR_TYPE_QUOTED_DEF(CASE_BEG, CASE_MID, CASE_END) + +#define FR_TYPE_STRUCTURAL_EXCEPT_VSA FR_TYPE_STRUCTURAL_EXCEPT_VSA_DEF(CASE_BEG, CASE_MID, CASE_END) +#define FR_TYPE_STRUCTURAL FR_TYPE_STRUCTURAL_DEF(CASE_BEG, CASE_MID, CASE_END) +#define FR_TYPE_NON_VALUES FR_TYPE_NON_VALUES_DEF(CASE_BEG, CASE_MID, CASE_END) +/** @} */ + +/** @name Bool arrays that group types * + * @{ */ -#define FR_TYPE_IP \ - FR_TYPE_IPV4_ADDR: \ - case FR_TYPE_IPV4_PREFIX: \ - case FR_TYPE_IPV6_ADDR: \ - case FR_TYPE_IPV6_PREFIX +extern bool const fr_type_integer_except_bool[FR_TYPE_MAX + 1]; +extern bool const fr_type_integer[FR_TYPE_MAX + 1]; +extern bool const fr_type_numeric[FR_TYPE_MAX + 1]; -/** Types which should be wrapped in double quotes when printed +extern bool const fr_type_ip[FR_TYPE_MAX + 1]; + +extern bool const fr_type_fixed_size[FR_TYPE_MAX + 1]; +extern bool const fr_type_variable_size[FR_TYPE_MAX + 1]; +extern bool const fr_type_values[FR_TYPE_MAX + 1]; +extern bool const fr_type_quoted[FR_TYPE_MAX + 1]; + +extern bool const fr_type_structural_except_vsa[FR_TYPE_MAX + 1]; +extern bool const fr_type_structural[FR_TYPE_MAX + 1]; +extern bool const fr_type_non_values[FR_TYPE_MAX + 1]; +/** @} */ + +/** @name Type checking macros * + * @{ */ -#define FR_TYPE_QUOTED \ - FR_TYPE_STRING: \ - case FR_TYPE_DATE +#define fr_type_is_null(_x) ((_x) == FR_TYPE_NULL) +#define fr_type_is_string(_x) ((_x) == FR_TYPE_STRING) +#define fr_type_is_octets(_x) ((_x) == FR_TYPE_OCTETS) +#define fr_type_is_ipv4addr(_x) ((_x) == FR_TYPE_IPV4_ADDR) +#define fr_type_is_ipv4prefix(_x) ((_x) == FR_TYPE_IPV4_PREFIX) +#define fr_type_is_ipv6addr(_x) ((_x) == FR_TYPE_IPV6_ADDR) +#define fr_type_is_ipv6prefix(_x) ((_x) == FR_TYPE_IPV6_PREFIX) +#define fr_type_is_ifid(_x) ((_x) == FR_TYPE_IFID) +#define fr_type_is_combo_ipaddr(_x) ((_x) == FR_TYPE_COMBO_IP_ADDR) +#define fr_type_is_combo_ipprefix(_x) ((_x) == FR_TYPE_COMBO_IP_PREFIX) +#define fr_type_is_ethernet(_x) ((_x) == FR_TYPE_ETHERNET) +#define fr_type_is_bool(_x) ((_x) == FR_TYPE_BOOL) +#define fr_type_is_uint8(_x) ((_x) == FR_TYPE_UINT8) +#define fr_type_is_uint16(_x) ((_x) == FR_TYPE_UINT16) +#define fr_type_is_uint32(_x) ((_x) == FR_TYPE_UINT32) +#define fr_type_is_uint64(_x) ((_x) == FR_TYPE_UINT64) +#define fr_type_is_int8(_x) ((_x) == FR_TYPE_INT8) +#define fr_type_is_int16(_x) ((_x) == FR_TYPE_INT16) +#define fr_type_is_int32(_x) ((_x) == FR_TYPE_INT32) +#define fr_type_is_int64(_x) ((_x) == FR_TYPE_INT64) +#define fr_type_is_float32(_x) ((_x) == FR_TYPE_FLOAT32) +#define fr_type_is_float64(_x) ((_x) == FR_TYPE_FLOAT64) +#define fr_type_is_date(_x) ((_x) == FR_TYPE_DATE) +#define fr_type_is_time_delta(_x) ((_x) == FR_TYPE_TIME_DELTA) +#define fr_type_is_size(_x) ((_x) == FR_TYPE_SIZE) +#define fr_type_is_tlv(_x) ((_x) == FR_TYPE_TLV) +#define fr_type_is_struct(_x) ((_x) == FR_TYPE_STRUCT) +#define fr_type_is_vsa(_x) ((_x) == FR_TYPE_VSA) +#define fr_type_is_vendor(_x) ((_x) == FR_TYPE_VENDOR) +#define fr_type_is_group(_x) ((_x) == FR_TYPE_GROUP) +#define fr_type_is_value_box(_x) ((_x) == FR_TYPE_VALUE_BOX) +#define fr_type_is_void(_x) ((_x) == FR_TYPE_VOID) + +#define fr_type_is_integer_except_bool(_x) (fr_type_integer_except_bool[_x]) +#define fr_type_is_integer(_x) (fr_type_integer[_x]) +#define fr_type_is_numeric(_x) (fr_type_numeric[_x]) + +#define fr_type_is_ip(_x) (fr_type_ip[_x]) + +#define fr_type_is_fixed_size(_x) (fr_type_fixed_size[_x]) +#define fr_type_is_variable_size(_x) (fr_variable_size[_x]) +#define fr_type_is_value(_x) (fr_type_values[_x]) +#define fr_type_is_quoted(_x) (fr_type_quoted[_x]) + +#define fr_type_is_structural_except_vsa(_x) (fr_type_structural_except_vsa[_x]) +#define fr_type_is_structural(_x) (fr_type_structural[_x]) +#define fr_type_is_non_value(_x) (fr_type_non_values[_x]) +/** @} */ bool fr_type_cast(fr_type_t dst, fr_type_t src); fr_type_t fr_type_promote(fr_type_t a, fr_type_t b); diff --git a/src/lib/util/value.c b/src/lib/util/value.c index 303349ef11..8cd93734a1 100644 --- a/src/lib/util/value.c +++ b/src/lib/util/value.c @@ -4425,7 +4425,8 @@ parse: break; case FR_TYPE_STRUCTURAL: - case FR_TYPE_BAD: + case FR_TYPE_MAX: + case FR_TYPE_NULL: fr_strerror_printf("Invalid dst_type %s", fr_table_str_by_value(fr_value_box_type_table, *dst_type, "")); return -1; @@ -4611,7 +4612,8 @@ parse: case FR_TYPE_VARIABLE_SIZE: /* Should have been dealt with above */ case FR_TYPE_STRUCTURAL: /* Listed again to suppress compiler warnings */ case FR_TYPE_VOID: - case FR_TYPE_BAD: + case FR_TYPE_MAX: + case FR_TYPE_NULL: fr_strerror_printf("Unknown attribute dst_type %d", *dst_type); return -1; } @@ -4894,7 +4896,8 @@ ssize_t fr_value_box_print(fr_sbuff_t *out, fr_value_box_t const *data, fr_sbuff case FR_TYPE_COMBO_IP_PREFIX: case FR_TYPE_VALUE_BOX: case FR_TYPE_VOID: - case FR_TYPE_BAD: + case FR_TYPE_MAX: + case FR_TYPE_NULL: (void)fr_cond_assert(0); return 0; } diff --git a/src/lib/util/value.h b/src/lib/util/value.h index 8c12bfdda7..27a91c93b2 100644 --- a/src/lib/util/value.h +++ b/src/lib/util/value.h @@ -274,6 +274,62 @@ struct value_box_s { #define fr_box_time_delta_usec(_val) fr_box_time_delta_with_res((_val), FR_TIME_RES_USEC) /** @} */ +/** @name Type checking macros + * + * Convenience macros for checking if a box is a + * specific type. + * + * @{ + */ +#define fr_box_is_null(_x) fr_type_is_null((_x)->type) +#define fr_box_is_string(_x) fr_type_is_string((_x)->type) +#define fr_box_is_octets(_x) fr_type_is_octets((_x)->type) +#define fr_box_is_ipv4addr(_x) fr_type_is_ipv4addr((_x)->type) +#define fr_box_is_ipv4prefix(_x) fr_type_is_ipv4prefix((_x)->type) +#define fr_box_is_ipv6addr(_x) fr_type_is_ipv6addr((_x)->type) +#define fr_box_is_ipv6prefix(_x) fr_type_is_ipv6prefix((_x)->type) +#define fr_box_is_ifid(_x) fr_type_is_ifid((_x)->type) +#define fr_box_is_combo_ipaddr(_x) fr_type_is_combo_ipaddr((_x)->type) +#define fr_box_is_combo_ipprefix(_x) fr_type_is_combo_ipprefix((_x)->type) +#define fr_box_is_ethernet(_x) fr_type_is_ethernet((_x)->type) +#define fr_box_is_bool(_x) fr_type_is_bool((_x)->type) +#define fr_box_is_uint8(_x) fr_type_is_uint8((_x)->type) +#define fr_box_is_uint16(_x) fr_type_is_uint16((_x)->type) +#define fr_box_is_uint32(_x) fr_type_is_uint32((_x)->type) +#define fr_box_is_uint64(_x) fr_type_is_uint64((_x)->type) +#define fr_box_is_int8(_x) fr_type_is_int8((_x)->type) +#define fr_box_is_int16(_x) fr_type_is_int16((_x)->type) +#define fr_box_is_int32(_x) fr_type_is_int32((_x)->type) +#define fr_box_is_int64(_x) fr_type_is_int64((_x)->type) +#define fr_box_is_float32(_x) fr_type_is_float32((_x)->type) +#define fr_box_is_float64(_x) fr_type_is_float64((_x)->type) +#define fr_box_is_date(_x) fr_type_is_date((_x)->type) +#define fr_box_is_time_delta(_x) fr_type_is_time_delta((_x)->type) +#define fr_box_is_size(_x) fr_type_is_size((_x)->type) +#define fr_box_is_tlv(_x) fr_type_is_tlv((_x)->type) +#define fr_box_is_struct(_x) fr_type_is_struct((_x)->type) +#define fr_box_is_vsa(_x) fr_type_is_vsa((_x)->type) +#define fr_box_is_vendor(_x) fr_type_is_vendor((_x)->type) +#define fr_box_is_group(_x) fr_type_is_group((_x)->type) +#define fr_box_is_value_box(_x) fr_type_is_value_box((_x)->type) +#define fr_box_is_void(_x) fr_type_is_void((_x)->type) + +#define fr_box_is_integer_except_bool(_x) fr_type_is_integer_except_bool((_x)->type) +#define fr_box_is_integer(_x) fr_type_is_integer((_x)->type) +#define fr_box_is_numeric(_x) fr_type_is_numeric((_x)->type) + +#define fr_box_is_ip(_x) fr_type_is_ip((_x)->type) + +#define fr_box_is_fixed_size(_x) fr_type_is_fixed_size((_x)->type) +#define fr_box_is_variable_size(_x) fr_type_is_variable_size((_x)->type) +#define fr_box_is_value(_x) fr_type_is_value((_x)->type) +#define fr_box_is_quoted(_x) fr_type_is_quoted((_x)->type) + +#define fr_box_is_structural_except_vsa(_x) fr_type_is_structural_except_vsa((_x)->type) +#define fr_box_is_structural(_x) fr_type_is_structural((_x)->type) +#define fr_box_is_non_value(_x) fr_type_is_non_value((_x)->type) +/** @} */ + /** @name Convenience functions * * These macros and inline functions simplify working diff --git a/src/modules/rlm_csv/rlm_csv.c b/src/modules/rlm_csv/rlm_csv.c index ea641cb947..fe51b3a753 100644 --- a/src/modules/rlm_csv/rlm_csv.c +++ b/src/modules/rlm_csv/rlm_csv.c @@ -436,14 +436,14 @@ static int csv_map_verify(map_t *map, void *instance) return -1; } - if ((type == FR_TYPE_NULL) || (offset < 0)) break; + if (fr_type_is_null(type) || (offset < 0)) break; /* * Try to set the data type of the field. But if * they map the same field to two different data * types, that's an error. */ - if (inst->field_types[offset] == FR_TYPE_NULL) { + if (fr_type_is_null(inst->field_types[offset])) { inst->field_types[offset] = type; break; } @@ -541,7 +541,7 @@ static int mod_bootstrap(void *instance, CONF_SECTION *conf) if (inst->key) { inst->key_data_type = tmpl_expanded_type(inst->key); switch (inst->key_data_type) { - case FR_TYPE_VALUE: + case FR_TYPE_VALUES: break; case FR_TYPE_NULL: diff --git a/src/modules/rlm_isc_dhcp/rlm_isc_dhcp.c b/src/modules/rlm_isc_dhcp/rlm_isc_dhcp.c index f1b79aaa49..efc8cd8480 100644 --- a/src/modules/rlm_isc_dhcp/rlm_isc_dhcp.c +++ b/src/modules/rlm_isc_dhcp/rlm_isc_dhcp.c @@ -950,7 +950,7 @@ static int parse_option_definition(rlm_isc_dhcp_info_t *parent, rlm_isc_dhcp_tok } type = isc2fr_type(state); - if (type == FR_TYPE_NULL) goto error; + if (fr_type_is_null(type)) goto error; /* * Now that we've parsed everything, look up the name. diff --git a/src/modules/rlm_unpack/rlm_unpack.c b/src/modules/rlm_unpack/rlm_unpack.c index 00848b5425..5329f605ae 100644 --- a/src/modules/rlm_unpack/rlm_unpack.c +++ b/src/modules/rlm_unpack/rlm_unpack.c @@ -161,7 +161,7 @@ static ssize_t unpack_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen, } type = fr_table_value_by_str(fr_value_box_type_table, data_type, FR_TYPE_NULL); - if (type == FR_TYPE_NULL) { + if (fr_type_is_null(type)) { REDEBUG("Invalid data type '%s'", data_type); goto nothing; } diff --git a/src/protocols/internal/encode.c b/src/protocols/internal/encode.c index 80ed88ed20..c4b00cb9bc 100644 --- a/src/protocols/internal/encode.c +++ b/src/protocols/internal/encode.c @@ -77,7 +77,7 @@ static ssize_t internal_encode(fr_dbuff_t *dbuff, /* * Only leaf attributes can be tainted */ - case FR_TYPE_VALUE: + case FR_TYPE_VALUES: if (vp->vp_tainted) enc_byte |= FR_INTERNAL_FLAG_TAINTED; break; @@ -117,7 +117,7 @@ static ssize_t internal_encode(fr_dbuff_t *dbuff, fr_dbuff_marker(&value_field, &value_dbuff); switch (da->type) { - case FR_TYPE_VALUE: + case FR_TYPE_VALUES: slen = fr_value_box_to_network(&value_dbuff, &vp->data); if (slen < 0) return PAIR_ENCODE_FATAL_ERROR; FR_PROTO_HEX_DUMP(fr_dbuff_start(&value_dbuff), slen, "value %s", diff --git a/src/protocols/radius/decode.c b/src/protocols/radius/decode.c index 0cb4189d0f..546b8db507 100644 --- a/src/protocols/radius/decode.c +++ b/src/protocols/radius/decode.c @@ -1236,7 +1236,7 @@ ssize_t fr_radius_decode_pair_value(TALLOC_CTX *ctx, fr_dcursor_t *cursor, fr_di } switch (parent->type) { - case FR_TYPE_VALUE: + case FR_TYPE_VALUES: break; case FR_TYPE_COMBO_IP_PREFIX: diff --git a/src/protocols/radius/encode.c b/src/protocols/radius/encode.c index 124184ba4e..ca3396dbe4 100644 --- a/src/protocols/radius/encode.c +++ b/src/protocols/radius/encode.c @@ -957,7 +957,7 @@ static ssize_t encode_rfc_hdr_internal(fr_dbuff_t *dbuff, return PAIR_ENCODE_FATAL_ERROR; case FR_TYPE_STRUCT: - case FR_TYPE_VALUE: + case FR_TYPE_VALUES: if (((fr_dict_vendor_num_by_da(da_stack->da[depth]) == 0) && (da_stack->da[depth]->attr == 0)) || (da_stack->da[depth]->attr > 255)) { fr_strerror_printf("%s: Called with non-standard attribute %u", __FUNCTION__,