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
return -1;
}
- *ref = talloc_strdup(ctx->dict->pool, value);
+ *ref = talloc_strdup(ctx->fixup_pool, value);
flags->extra = true;
flags->subtype = FLAG_HAS_REF;
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;
{
fr_type_t type;
fr_dict_attr_flags_t flags;
+ char *ref = NULL;
if ((argc < 2) || (argc > 3)) {
fr_strerror_printf("Invalid MEMBER syntax");
* 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;
}
}
}
+ 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;
}
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
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