]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add "key" flag for integer attributes
authorAlan T. DeKok <aland@freeradius.org>
Wed, 7 Aug 2019 16:52:21 +0000 (12:52 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 7 Aug 2019 17:10:43 +0000 (13:10 -0400)
in preparation for allowing nested structs, decoded with a key

src/lib/util/dict.c

index 9d4768b5968ef18713c54e55079dfa61336092e1..133f681de8382e59f5467973a9ada799a7df2e5d 100644 (file)
@@ -928,7 +928,7 @@ static bool dict_attr_fields_valid(fr_dict_t *dict, fr_dict_attr_t const *parent
                        return false;
                }
 
-               if (flags->internal || flags->has_tag || flags->array || flags->concat || flags->virtual) {
+               if (flags->internal || flags->has_tag || flags->array || flags->concat || flags->virtual || flags->extra) {
                        fr_strerror_printf("Invalid flag for attribute of type 'struct'");
                        return false;
                }
@@ -958,6 +958,7 @@ static bool dict_attr_fields_valid(fr_dict_t *dict, fr_dict_attr_t const *parent
                }
 
                if (*attr > 1) {
+                       int i;
                        fr_dict_attr_t const *sibling;
 
                        sibling = fr_dict_attr_child_by_num(parent, (*attr) - 1);
@@ -972,6 +973,44 @@ static bool dict_attr_fields_valid(fr_dict_t *dict, fr_dict_attr_t const *parent
                                return false;
                        }
 
+                       /*
+                        *      Check for bad key fields, or multiple key fields.
+                        */
+                       if (flags->extra) {
+                               /*
+                                *      There should really be a
+                                *      separate "validation"
+                                *      function, which is used both
+                                *      here, and by the flag parser.
+                                */
+                               switch (type) {
+                               case FR_TYPE_UINT8:
+                               case FR_TYPE_UINT16:
+                               case FR_TYPE_UINT32:
+                               case FR_TYPE_UINT64:
+                                       break;
+
+                               default:
+                                       fr_strerror_printf("'key' can only be used with unsigned integer data types");
+                                       return -1;
+                               }
+
+                               for (i = 1; i < *attr; i++) {
+                                       sibling = fr_dict_attr_child_by_num(parent, i);
+                                       if (!sibling) {
+                                               fr_strerror_printf("Child %d of 'struct' type attribute %s does not exist.",
+                                                                  i, parent->name);
+                                               return false;
+                                       }
+
+                                       if (!sibling->flags.extra) continue;
+
+                                       fr_strerror_printf("Duplicate key attributes '%s' and '%s' in 'struct' type attribute %s are forbidden",
+                                                          name, sibling->name, parent->name);
+                                       return false;
+                               }
+                       }
+
                } else {
                        /*
                         *      The first child can't be variable length, that's stupid.
@@ -2470,10 +2509,23 @@ do { \
        }
 
        if (flags->extra) {
-               if (type == FR_TYPE_EXTENDED) {
+               switch (type) {
+               case FR_TYPE_EXTENDED:
                        p += snprintf(p, end - p, "long,");
-                       if (p >= end) return -1;
+                       break;
+
+               case FR_TYPE_UINT8:
+               case FR_TYPE_UINT16:
+               case FR_TYPE_UINT32:
+               case FR_TYPE_UINT64:
+                       p += snprintf(p, end - p, "key,");
+                       break;
+
+               default:
+                       break;
                }
+
+               if (p >= end) return -1;
        }
 
        /*
@@ -4006,6 +4058,21 @@ static int dict_process_flag_field(dict_from_file_ctx_t *ctx, char *name, fr_typ
 
                        flags->extra = 1;
 
+               } else if (strcmp(key, "key") == 0) {
+                       switch (type) {
+                       case FR_TYPE_UINT8:
+                       case FR_TYPE_UINT16:
+                       case FR_TYPE_UINT32:
+                       case FR_TYPE_UINT64:
+                               break;
+
+                       default:
+                               fr_strerror_printf("'key' can only be used with unsigned integer data types");
+                               return -1;
+                       }
+
+                       flags->extra = 1;
+
                } else if (ref_p && (strcmp(key, "reference") == 0)) {
                        ref = dict_resolve_reference(ctx->dict, value);
                        if (!ref) return -1;