]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Expand multi type support to all value types
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 5 Jun 2022 05:58:13 +0000 (01:58 -0400)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 5 Jun 2022 05:58:13 +0000 (01:58 -0400)
src/lib/server/cf_parse.c
src/lib/util/types.c
src/lib/util/types.h

index 26b63d3d5c339339c689a2e1a9fb9ea394831f80..7150b86e074125953fbbec73ab2eb06f12a70863 100644 (file)
@@ -445,62 +445,25 @@ static int CC_HINT(nonnull(4,5)) cf_pair_parse_internal(TALLOC_CTX *ctx, void *o
                 */
                else if (type & FR_TYPE_TMPL) {
                        array = (void **)talloc_zero_array(ctx, tmpl_t *, count);
+                       if (unlikely(array == NULL)) {
+                               cf_log_perr(cp, "Failed allocating value array");
+                               return -1;
+                       }
+
                /*
                 *      Allocate an array of values.
                 *
                 *      We don't NULL terminate.  Consumer must use
                 *      talloc_array_length().
                 */
-               } else switch (FR_BASE_TYPE(type)) {
-               case FR_TYPE_BOOL:
-                       array = (void **)talloc_zero_array(ctx, bool, count);
-                       break;
-
-               case FR_TYPE_UINT32:
-                       array = (void **)talloc_zero_array(ctx, uint32_t, count);
-                       break;
-
-               case FR_TYPE_UINT16:
-                       array = (void **)talloc_zero_array(ctx, uint16_t, count);
-                       break;
-
-               case FR_TYPE_UINT64:
-                       array = (void **)talloc_zero_array(ctx, uint64_t, count);
-                       break;
-
-               case FR_TYPE_INT32:
-                       array = (void **)talloc_zero_array(ctx, int32_t, count);
-                       break;
-
-               case FR_TYPE_STRING:
-                       array = (void **)talloc_zero_array(ctx, char *, count);
-                       break;
-
-               case FR_TYPE_IPV4_ADDR:
-               case FR_TYPE_IPV4_PREFIX:
-               case FR_TYPE_IPV6_ADDR:
-               case FR_TYPE_IPV6_PREFIX:
-               case FR_TYPE_COMBO_IP_ADDR:
-               case FR_TYPE_COMBO_IP_PREFIX:
-                       array = (void **)talloc_zero_array(ctx, fr_ipaddr_t, count);
-                       break;
-
-               case FR_TYPE_TIME_DELTA:
-                       array = (void **)talloc_zero_array(ctx, fr_time_delta_t, count);
-                       break;
-
-               case FR_TYPE_VOID:
-                       fr_assert(rule->func);
-                       array = (void **)talloc_zero_array(ctx, void *, count);
-                       break;
-
-               default:
-                       cf_log_err(cp, "Unsupported type %i (%i)", type, FR_BASE_TYPE(type));
-                       fr_assert_fail(NULL);
-                       return -1;      /* Unsupported type */
+               } else {
+                       array = fr_type_array_alloc(ctx, FR_BASE_TYPE(type), count);
+                       if (unlikely(array == NULL)) {
+                               cf_log_perr(cp, "Failed allocating value array");
+                               return -1;
+                       }
                }
 
-               if (!array) return -1;
 
                for (i = 0; i < count; i++, cp = cf_pair_find_next(cs, cp, rule->name)) {
                        int             ret;
index 72f080e740433f4109df4c4d7b359b5cc66cf4ff..0b89fe348f3f1618fe0ff32f80c3b88044177779 100644 (file)
@@ -83,6 +83,87 @@ fr_table_num_ordered_t const fr_type_table[] = {
 };
 size_t fr_type_table_len = NUM_ELEMENTS(fr_type_table);
 
+/** Table of all the direct mappings between types and C types
+ *
+ * Useful for setting talloc types correctly.
+ */
+static size_t const fr_type_to_c_type[] = {
+       [FR_TYPE_STRING]                        = "char *",
+       [FR_TYPE_OCTETS]                        = "uint8_t *",
+
+       [FR_TYPE_IPV4_ADDR]                     = "fr_ipaddr_t",
+       [FR_TYPE_IPV4_PREFIX]                   = "fr_ipaddr_t",
+       [FR_TYPE_IPV6_ADDR]                     = "fr_ipaddr_t",
+       [FR_TYPE_IPV6_PREFIX]                   = "fr_ipaddr_t",
+       [FR_TYPE_COMBO_IP_ADDR]                 = "fr_ipaddr_t",
+       [FR_TYPE_COMBO_IP_PREFIX]               = "fr_ipaddr_t",
+       [FR_TYPE_IFID]                          = "fr_ifid_t",
+       [FR_TYPE_ETHERNET]                      = "fr_ethernet_t",
+
+       [FR_TYPE_BOOL]                          = "bool",
+       [FR_TYPE_UINT8]                         = "uint8_t",
+       [FR_TYPE_UINT16]                        = "uint16_t",
+       [FR_TYPE_UINT32]                        = "uint32_t",
+       [FR_TYPE_UINT64]                        = "uint64_t",
+
+       [FR_TYPE_INT8]                          = "int8_t",
+       [FR_TYPE_INT16]                         = "int16_t",
+       [FR_TYPE_INT32]                         = "int32_t",
+       [FR_TYPE_INT64]                         = "int64_t",
+
+       [FR_TYPE_FLOAT32]                       = "float",
+       [FR_TYPE_FLOAT64]                       = "double",
+
+       [FR_TYPE_DATE]                          = "fr_unix_time_t",
+
+       [FR_TYPE_TIME_DELTA]                    = "fr_time_delta_t",
+       [FR_TYPE_SIZE]                          = "size_t",
+       [FR_TYPE_VALUE_BOX]                     = "fr_value_box_t",
+       [FR_TYPE_VOID]                          = "void *",
+
+       [FR_TYPE_MAX]                           = 0     //!< Ensure array covers all types.
+};
+
+/** Table of all the direct mappings between types and C type sizes
+ *
+ */
+static size_t const fr_type_to_c_size[] = {
+       [FR_TYPE_STRING]                        = sizeof(char *),
+       [FR_TYPE_OCTETS]                        = sizeof(uint8_t *),
+
+       [FR_TYPE_IPV4_ADDR]                     = sizeof(fr_ipaddr_t),
+       [FR_TYPE_IPV4_PREFIX]                   = sizeof(fr_ipaddr_t),
+       [FR_TYPE_IPV6_ADDR]                     = sizeof(fr_ipaddr_t),
+       [FR_TYPE_IPV6_PREFIX]                   = sizeof(fr_ipaddr_t),
+       [FR_TYPE_COMBO_IP_ADDR]                 = sizeof(fr_ipaddr_t),
+       [FR_TYPE_COMBO_IP_PREFIX]               = sizeof(fr_ipaddr_t),
+       [FR_TYPE_IFID]                          = sizeof(fr_ifid_t),
+       [FR_TYPE_ETHERNET]                      = sizeof(fr_ethernet_t),
+
+       [FR_TYPE_BOOL]                          = sizeof(bool),
+       [FR_TYPE_UINT8]                         = sizeof(uint8_t),
+       [FR_TYPE_UINT16]                        = sizeof(uint16_t),
+       [FR_TYPE_UINT32]                        = sizeof(uint32_t),
+       [FR_TYPE_UINT64]                        = sizeof(uint64_t),
+
+       [FR_TYPE_INT8]                          = sizeof(int8_t),
+       [FR_TYPE_INT16]                         = sizeof(int16_t),
+       [FR_TYPE_INT32]                         = sizeof(int32_t),
+       [FR_TYPE_INT64]                         = sizeof(int64_t),
+
+       [FR_TYPE_FLOAT32]                       = sizeof(float),
+       [FR_TYPE_FLOAT64]                       = sizeof(double),
+
+       [FR_TYPE_DATE]                          = sizeof(fr_unix_time_t),
+
+       [FR_TYPE_TIME_DELTA]                    = sizeof(fr_time_delta_t),
+       [FR_TYPE_SIZE]                          = sizeof(size_t),
+       [FR_TYPE_VALUE_BOX]                     = sizeof(fr_value_box_t),
+       [FR_TYPE_VOID]                          = sizeof(void *),
+
+       [FR_TYPE_MAX]                           = 0     //!< Ensure array covers all types.
+};
+
 #define ARRAY_BEG(_type)       { [_type] = true,
 #define ARRAY_MID(_type)       [_type] = true,
 #define ARRAY_END(_type)       [_type] = true }
@@ -515,3 +596,25 @@ fr_type_t fr_type_promote(fr_type_t a, fr_type_t b)
         */
        return type_promote_table[a][b];
 }
+
+/** Allocate an array of a given type
+ *
+ * @param[in] ctx      to allocate array in.
+ * @param[in] type     array to allocate.
+ * @param[in] count    The number of elements to allocate.
+ * @return
+ *     - NULL on error.
+ *     - A new talloc array.
+ */
+void **fr_type_array_alloc(TALLOC_CTX *ctx, fr_type_t type, size_t count)
+{
+       char *c_type;
+
+       c_type = fr_type_to_c_type[type];
+       if (c_type == NULL) {
+               fr_strerror_printf("Type %s does not have a C type equivalent", fr_type_to_str(type));
+               return NULL;
+       }
+
+       return _talloc_array(ctx, fr_type_to_c_size[type], count, c_type);
+ }
index d9d48f7541d3a5e7ed8262aed3136e10cd7dc8dc..31b79b47c8f3b058e414ec1c36b0c6212ce37f1f 100644 (file)
@@ -28,8 +28,9 @@ RCSIDH(types_h, "$Id$")
 extern "C" {
 #endif
 
-#include <stdbool.h>
 #include <freeradius-devel/util/table.h>
+#include <freeradius-devel/util/talloc.h>
+#include <stdbool.h>
 
 /** Internal data types
  */
@@ -384,6 +385,8 @@ static inline fr_type_t fr_type_from_str(char const *type)
 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);
 
+void           **fr_type_array_alloc(TALLOC_CTX *ctx, fr_type_t type, size_t count);
+
 #ifdef __cplusplus
 }
 #endif