]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
allow cloning of struct MEMBERs
authorAlan T. DeKok <aland@freeradius.org>
Tue, 8 Dec 2020 18:23:10 +0000 (13:23 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Tue, 8 Dec 2020 18:25:29 +0000 (13:25 -0500)
share/dictionary/dhcpv6/dictionary.rfc3315
src/lib/util/dict_tokenize.c
src/tests/unit/protocols/dhcpv6/server.txt

index 8c24d9ea4ed0a93b67208cd2bd19777df84170c6..b4fb1b1bbaa42910b157017ee9d6dfe815db9b31 100644 (file)
@@ -32,15 +32,17 @@ MEMBER              Enterprise-Number                       uint32
 MEMBER         Identifier                              octets
 
 STRUCT LL                              DUID                    3
-MEMBER         Hardware-Type                           uint16 key
-
-#  Sub-struct of Client-ID.LL.Hardware-Type
-STRUCT Ethernet                        Hardware-Type           1
-MEMBER         Address                                 ether
+MEMBER         Hardware-Type                           uint16 key,clone=Client-ID.DUID.LLT.Hardware-Type
 
 #
 #  Server-ID is a clone of Client-ID
 #
+#  Note that the cloning happens after all of the DHCPv6 dictionaries
+#  have been loaded.  This delay allows multiple dictionaries to
+#  define sub-structures for Client-ID.  Once all of the
+#  sub-structures have been defined, the Server-ID option can clone
+#  all of those sub-structures.
+#
 ATTRIBUTE      Server-ID                               2       struct clone=Client-ID
 
 ATTRIBUTE      IA-NA                                   3       struct
index d0b70f0b79d96eca15031bf1835984182d802133..0970a1fc0c189b019977f04da8dba4d8e9ce9c70 100644 (file)
@@ -511,7 +511,7 @@ static int dict_process_flag_field(dict_tokenize_ctx_t *ctx, char *name, fr_type
                                return -1;
                        }
 
-                       *ref = talloc_strdup(ctx->dict->pool, value);
+                       *ref = talloc_strdup(ctx->fixup_pool, value);
                        flags->extra = true;
                        flags->subtype = FLAG_HAS_REF;
 
@@ -521,13 +521,14 @@ static int dict_process_flag_field(dict_tokenize_ctx_t *ctx, char *name, fr_type
                                return -1;
                        }
 
-                       if ((type != FR_TYPE_TLV) && (type != FR_TYPE_STRUCT)) {
+                       if ((type != FR_TYPE_TLV) && (type != FR_TYPE_STRUCT) &&
+                           !(flags->extra && (flags->subtype == FLAG_KEY_FIELD))) {
                                fr_strerror_printf("The 'clone' flag cannot be used for type '%s'",
                                                   fr_table_str_by_value(fr_value_box_type_table, type, "<UNKNOWN>"));
                                return -1;
                        }
 
-                       *ref = talloc_strdup(ctx->dict->pool, value);
+                       *ref = talloc_strdup(ctx->fixup_pool, value);
 
                } else if (ctx->dict->subtype_table) {
                        int subtype;
@@ -941,6 +942,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;
 
        if ((argc < 2) || (argc > 3)) {
                fr_strerror_printf("Invalid MEMBER syntax");
@@ -968,7 +970,13 @@ static int dict_read_process_member(dict_tokenize_ctx_t *ctx, char **argv, int a
         *      Parse options.
         */
        if (argc >= 3) {
-               if (dict_process_flag_field(ctx, argv[2], type, &flags, NULL) < 0) return -1;
+               if (dict_process_flag_field(ctx, argv[2], type, &flags, &ref) < 0) return -1;
+
+               if (ref && (type != FR_TYPE_TLV) && !(flags.extra && (flags.subtype == FLAG_KEY_FIELD))) {
+                       fr_strerror_printf("Only MEMBERs of type 'tlv' or with 'key' flags can have references");\
+                       return -1;
+               }
+
        } else {
                if (!dict_attr_flags_valid(ctx->dict, ctx->stack[ctx->stack_depth].da, argv[2], NULL, type, &flags)) return -1;
        }
@@ -1093,6 +1101,21 @@ static int dict_read_process_member(dict_tokenize_ctx_t *ctx, char **argv, int a
                }
        }
 
+       if (ref) {
+               dict_fixup_t *fixup;
+
+               fixup = dict_fixup_alloc(ctx, DICT_FIXUP_CLONE);
+               if (!fixup) {
+                       talloc_free(ref);
+                       return -1;
+               }
+
+               fixup->parent = ctx->stack[ctx->stack_depth].da;
+               fixup->da = dict_attr_child_by_num(ctx->stack[ctx->stack_depth].da,
+                                                  ctx->stack[ctx->stack_depth].member_num);
+               fixup->ref = ref;
+       }
+
        return 0;
 }
 
index c8a0e730f6263ae6cc1089e58d26444c86ad285b..e68a3409e74ce12e2a4f471cfe6d185c76370d75 100644 (file)
@@ -8,6 +8,9 @@
 proto dhcpv6
 proto-dictionary dhcpv6
 
+#
+#  Sub-structures are children of the "key" field.  Sorry.  :(
+#
 encode-pair Client-ID.DUID = UUID, Client-ID.DUID.UUID.Value = 0x000100012750f52702420a0000090000
 match 00 01 00 12 00 04 00 01 00 01 27 50 f5 27 02 42 0a 00 00 09 00 00
 
@@ -20,5 +23,29 @@ match 00 02 00 12 00 04 00 01 00 01 27 50 f5 27 02 42 0a 00 00 09 00 00
 decode-pair -
 match Server-ID.DUID = UUID, Server-ID.DUID.UUID.Value = 0x000100012750f52702420a0000090000
 
+#
+#  We SHOULD be adding a sub-struct with Client-ID.DUID.LLT.Hardware-Type.Ethernet.Address,
+#  but for some reason we don't.  @todo - fixme!
+#
+encode-pair Client-ID.DUID = LLT, Client-ID.DUID.LLT.Hardware-Type = Ethernet, Client-ID.DUID.LLT.Time = "Jan  1 2000 00:00:00 UTC"
+match 00 01 00 08 00 01 00 01 00 00 00 00
+
+encode-pair Client-ID.DUID = LLT, Client-ID.DUID.LLT.Hardware-Type = Ethernet, Client-ID.DUID.LLT.Time = "Jan  1 2000 00:00:02 UTC", Client-ID.DUID.LLT.Hardware-Type.Ethernet.Address = 00:01:02:03:04:05
+match 00 01 00 0e 00 01 00 01 00 00 00 02 00 01 02 03 04 05
+
+decode-pair -
+match Client-ID.DUID = LLT, Client-ID.DUID.LLT.Hardware-Type = Ethernet, Client-ID.DUID.LLT.Time = "Jan  1 2000 00:00:02 UTC", Client-ID.DUID.LLT.Hardware-Type.Ethernet.Address = 00:01:02:03:04:05
+
+#
+#  sub-struct LL is LLT, but without the T
+#
+#  Note that the "Hardware-Type" sub-structure is cloned from Client-ID.DUID.LLT.Hardware-Type
+#
+encode-pair Client-ID.DUID = LL, Client-ID.DUID.LL.Hardware-Type = Ethernet, Client-ID.DUID.LL.Hardware-Type.Ethernet.Address = 00:01:02:03:04:05
+match 00 01 00 0a 00 03 00 01 00 01 02 03 04 05
+
+decode-pair -
+match Client-ID.DUID = LL, Client-ID.DUID.LL.Hardware-Type = Ethernet, Client-ID.DUID.LL.Hardware-Type.Ethernet.Address = 00:01:02:03:04:05
+
 count
-match 10
+match 20