]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add type check macros
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 4 Apr 2021 21:48:10 +0000 (22:48 +0100)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 4 Apr 2021 21:48:27 +0000 (22:48 +0100)
20 files changed:
src/bin/unit_test_attribute.c
src/lib/server/command.c
src/lib/server/cond_eval.c
src/lib/server/cond_tokenize.c
src/lib/server/tmpl_tokenize.c
src/lib/unlang/compile.c
src/lib/unlang/xlat_builtin.c
src/lib/util/dict_tokenize.c
src/lib/util/dict_validate.c
src/lib/util/struct.c
src/lib/util/types.c
src/lib/util/types.h
src/lib/util/value.c
src/lib/util/value.h
src/modules/rlm_csv/rlm_csv.c
src/modules/rlm_isc_dhcp/rlm_isc_dhcp.c
src/modules/rlm_unpack/rlm_unpack.c
src/protocols/internal/encode.c
src/protocols/radius/decode.c
src/protocols/radius/encode.c

index d6cdc296baca08c7a562bf0f094f299c661d6815..875c677617122c716617236c18b6345010af3a69 100644 (file)
@@ -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;
index 9d1a88c21d88b67dfd8bbcf192846d650b9b305b..26ea204514b1b40495aa87086349a4a9bbb0cd5e 100644 (file)
@@ -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;
 
index 0a56604e003e4392daab24b80b017e58482b2064..8a0f2a14421cd3c5439d5d0867b923a4046d6a74 100644 (file)
@@ -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);
index 255862a5813f235495d07396a42264b6e0a1c5d2..2399cb481e773905ae300734081b1222ebe12d0b 100644 (file)
@@ -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:
index e29ed42ea6160186ca7597b341fe7932df4bd619..fd4d0f21f344efd8528edca57e5fd72375e5eb8a 100644 (file)
@@ -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");
                }
 
index 00984c1e557f3cf715ce83d409c738578371d8cb..cea14344f055f0d9db91dafe5afb02f84e38bffa 100644 (file)
@@ -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");
index 3e9a3f1a8a2de00610be826b41b7f798e33e1d25..95437b636238a3d6d16a6ff4cb6064c7a22ef5f7 100644 (file)
@@ -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) {
index 9d56b8666fcc2e262109967cac484721a259e86d..2e5a7d3df63ef25c186291e8006ca420edfe2cbc 100644 (file)
@@ -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, "<UNKNOWN>"),
index 9a9b01284b62e3eec10cf61df64158a667d74b4f..7f5630ed72a516902b3de2b0e96d4cbec58eb5d2 100644 (file)
@@ -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:
index 292d1a5ce26941b59b4b015631c5802fe3e49399..48574bd180e84bdf4737ade830e831dfa891f70d 100644 (file)
@@ -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;
                }
 
index 8769656c28209e7de508307e7779015390429223..ec092bc65c581bb9907ceb87948071a8b60a5321 100644 (file)
@@ -26,6 +26,25 @@ RCSID("$Id$")
 #include <freeradius-devel/util/types.h>
 #include <freeradius-devel/util/value.h>
 
+#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
 
 /*
index 4a75026b8997c742e7a0f65d7d2aa5bad2fe6bb8..07cb450c250a7b8b36d1e4fb02af8e076514f3a5 100644 (file)
@@ -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);
index 303349ef11b02c4bc99ccd27d2ef1678e41034a7..8cd93734a1c8c7a1780ad472f52020f0cd55776f 100644 (file)
@@ -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, "<INVALID>"));
                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;
        }
index 8c12bfdda7bf70f9ac1e1245d83eb09452c6e0fa..27a91c93b2140750d2d123fcaafbe7c722f161e7 100644 (file)
@@ -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
index ea641cb947da7094025e7e5835fdedcf3eafcbc4..fe51b3a753406b6bb1b115ba77e595759c9477f8 100644 (file)
@@ -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:
index f1b79aaa4933750c4c40bfb39f6ae9b09f6f58b2..efc8cd848031ac88c3b2febf5e0a113c28c0d4bb 100644 (file)
@@ -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.
index 00848b54259e7d68af9ec31f47d164f84bb3e83c..5329f605aed794c9d30c1c7e58d96fc7f10f6303 100644 (file)
@@ -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;
        }
index 80ed88ed20a8388c0573b9d512d2c221cced7203..c4b00cb9bcf8d5f1448719950fe559724e40be8f 100644 (file)
@@ -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",
index 0cb4189d0f6c3cefc45a39af6060b291044edc69..546b8db50788ed0c51cadc32c6ee87f71617bc7e 100644 (file)
@@ -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:
index 124184ba4eaff5059cc82953fb933321ca4df66f..ca3396dbe46e2cbdd5ebcfd40a4007e54737a24a 100644 (file)
@@ -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__,