]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
allow structs to be children of structs
authorAlan T. DeKok <aland@freeradius.org>
Thu, 17 Mar 2022 22:53:18 +0000 (18:53 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Fri, 18 Mar 2022 13:16:27 +0000 (09:16 -0400)
ATTR foo struct
member bar uint8
member baz struct
member x  # of 'baz' struct!
member y

It looks stupid, but it works.

src/lib/util/dict_tokenize.c

index e22df453b0ddf2a6b00083cb7136e75795ac0c6d..27c1ddd525eeae7d8cb52a9489d656a06635950f 100644 (file)
@@ -1084,6 +1084,7 @@ static int dict_read_process_member(dict_tokenize_ctx_t *ctx, char **argv, int a
        fr_type_t               type;
        fr_dict_attr_flags_t    flags;
        char                    *ref = NULL;
+       fr_dict_attr_t const    *da;
 
        if ((argc < 2) || (argc > 3)) {
                fr_strerror_const("Invalid MEMBER syntax");
@@ -1182,8 +1183,6 @@ static int dict_read_process_member(dict_tokenize_ctx_t *ctx, char **argv, int a
                int i;
 
                for (i = 0; i <= ctx->stack[ctx->stack_depth].member_num; i++) {
-                       fr_dict_attr_t const *da;
-
                        da = dict_attr_child_by_num(ctx->stack[ctx->stack_depth].da, i);
                        if (!da) continue; /* really should be WTF? */
 
@@ -1210,6 +1209,15 @@ static int dict_read_process_member(dict_tokenize_ctx_t *ctx, char **argv, int a
                             ++ctx->stack[ctx->stack_depth].member_num,
                             type, &flags) < 0) return -1;
 
+       /*
+        *      If we need to set the previous attribute, we have to
+        *      look it up by number.  This lets us set the
+        *      *canonical* previous attribute, and not any potential
+        *      duplicate which was just added.
+        */
+       da = dict_attr_child_by_num(ctx->stack[ctx->stack_depth].da, ctx->stack[ctx->stack_depth].member_num);
+       fr_assert(da != NULL);
+
        /*
         *      A 'struct' can have a MEMBER of type 'tlv', but ONLY
         *      as the last entry in the 'struct'.  If we see that,
@@ -1254,6 +1262,14 @@ static int dict_read_process_member(dict_tokenize_ctx_t *ctx, char **argv, int a
                if (ret < 0) return -1;
        }
 
+       /*
+        *      Adding a member of type 'struct' is an implicit BEGIN-STRUCT.
+        */
+       if (type == FR_TYPE_STRUCT) {
+               if (dict_gctx_push(ctx, da) < 0) return -1;
+               ctx->value_attr = NULL;
+       }
+
        return 0;
 }