diff --git a/src/lib/util/dict.h b/src/lib/util/dict.h index 39dc6834f9d84..f499579dd0736 100644 --- a/src/lib/util/dict.h +++ b/src/lib/util/dict.h @@ -334,23 +334,84 @@ typedef ssize_t(*fr_dict_attr_encode_func_t)(fr_dbuff_t *dbuff, fr_pair_list_t c typedef int (*fr_dict_protocol_init_t)(void); typedef void (*fr_dict_protocol_free_t)(void); +typedef struct fr_dict_protocol_flag_s fr_dict_protocol_flag_t; + +/** Custom protocol-specific flag parsing function + * + * @note This function should be used to implement table based flag parsing. + * + * @param[in,out] da to manipulate directly. May be used if the flag + * alters a standard field in the fr_dict_attr_t. + * @param[out] out pointer to a field in the protocol_flags structure that's allocated + * as part of the fr_dict_attr_t. + * @param[in] rules How to parse the flag. + */ +typedef int (*fr_dict_protocol_flag_parse_t)(fr_dict_attr_t *da, void *out, fr_dict_protocol_flag_t const *rules); + +/** Protocol specific custom flag definitnion + * + */ +struct fr_dict_protocol_flag_s { + char const *name; //!< Name of the flag + fr_type_t type; //!< Basic output type. Must map to a C type. + size_t offset; //!< Where in the protocol specific output structure to write out the result. + fr_dict_protocol_flag_parse_t func; //!< Custom parsing function to convert a flag value string to a C type value. + void *uctx; //!< Use context to pass to the custom parsing function. +}; + +/** Terminating flag for fr_dict_protocol_flag_t + * + */ +#define FR_DICT_PROTOCOL_FLAG_TERMINATOR { NULL, FR_TYPE_NULL, 0, false } + +/** conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct + * + * @param[in] _name of the CONF_PAIR to search for. + * @param[in] _struct containing the field to write the result to. + * @param[in] _field to write the flag to + */ +# define FR_DICT_PROTOCOL_FLAG(_name, _struct, _field) \ + .name = _name, \ + .type = FR_CTYPE_TO_TYPE((((_struct *)NULL)->_field)), \ + .offset = offsetof(_struct, _field) /** Protocol-specific callbacks in libfreeradius-PROTOCOL * */ typedef struct { - char const *name; //!< name of this protocol - int default_type_size; //!< how many octets are in "type" field - int default_type_length; //!< how many octets are in "length" field - fr_table_num_ordered_t const *subtype_table; //!< for "encrypt=1", etc. - size_t subtype_table_len; //!< length of subtype_table - fr_dict_attr_valid_func_t attr_valid; //!< validation function for new attributes - - fr_dict_protocol_init_t init; //!< initialize the library - fr_dict_protocol_free_t free; //!< free the library - - fr_dict_attr_decode_func_t decode; //!< for decoding attributes - fr_dict_attr_encode_func_t encode; //!< for encoding attributes + char const *name; //!< name of this protocol + + int default_type_size; //!< how many octets are in "type" field + int default_type_length; //!< how many octets are in "length" field + + struct { + /** Custom flags for this protocol + * + * The flags are used to determine how to encode and decode attributes, + * and can either be one of a set of fixed values or a generic type + * like "string". + */ + fr_dict_protocol_flag_t const *flags; //!< Flags for this protocol, an array of + ///< fr_dict_protocol_flag_t terminated + ///< by FR_DICT_PROTOCOL_FLAG_TERMINATOR. + size_t flags_len; //!< ength of protocol_flags structure. + + fr_dict_attr_valid_func_t valid; //!< Validation function to ensure that + ///< new attributes are valid. + } attr; + + fr_table_num_ordered_t const *subtype_table; //!< for "encrypt=1", etc. + + size_t subtype_table_len; //!< length of subtype_table + + + fr_dict_protocol_init_t init; //!< initialize the library + fr_dict_protocol_free_t free; //!< free the library + + fr_dict_attr_decode_func_t decode; //!< for decoding attributes. Used for implementing foreign + ///< protocol attributes. + fr_dict_attr_encode_func_t encode; //!< for encoding attributes. Used for implementing foreign + ///< protocol attributes. } fr_dict_protocol_t; typedef struct fr_dict_gctx_s fr_dict_gctx_t; diff --git a/src/lib/util/dict_print.c b/src/lib/util/dict_print.c index 127c079724f25..9fcfb221413dd 100644 --- a/src/lib/util/dict_print.c +++ b/src/lib/util/dict_print.c @@ -43,7 +43,7 @@ ssize_t fr_dict_attr_flags_print(fr_sbuff_t *out, fr_dict_t const *dict, fr_type FLAG_SET(name_only); if (dict && !flags->extra && flags->subtype) { - FR_SBUFF_IN_STRCPY_RETURN(&our_out, fr_table_str_by_value(dict->subtype_table, flags->subtype, "?")); + FR_SBUFF_IN_STRCPY_RETURN(&our_out, fr_table_str_by_value(dict->proto->subtype_table, flags->subtype, "?")); FR_SBUFF_IN_CHAR_RETURN(&our_out, ','); } diff --git a/src/lib/util/dict_priv.h b/src/lib/util/dict_priv.h index fef203c123662..9adf4aaca5ead 100644 --- a/src/lib/util/dict_priv.h +++ b/src/lib/util/dict_priv.h @@ -98,22 +98,15 @@ struct fr_dict_s { fr_dict_t const *next; //!< for attribute overloading - fr_table_num_ordered_t const *subtype_table; //!< table of subtypes for this protocol - size_t subtype_table_len; //!< length of table of subtypes for this protocol + unsigned int vsa_parent; //!< varies with different protocols. - unsigned int vsa_parent; //!< varies with different protocols - int default_type_size; //!< for TLVs and VSAs - int default_type_length; //!< for TLVs and VSAs + fr_dict_attr_t **fixups; //!< Attributes that need fixing up. + + fr_rb_tree_t *dependents; //!< Which files are using this dictionary. dl_t *dl; //!< for validation fr_dict_protocol_t const *proto; //!< protocol-specific validation functions - - fr_dict_attr_valid_func_t attr_valid; //!< validation function for new attributes - - fr_dict_attr_t **fixups; //!< Attributes that need fixing up. - - fr_rb_tree_t *dependents; //!< Which files are using this dictionary. }; struct fr_dict_gctx_s { @@ -171,14 +164,20 @@ typedef struct { } dict_attr_args_t; int dict_attr_init(fr_dict_attr_t **da_p, + fr_dict_t const *dict, fr_dict_attr_t const *parent, char const *name, int attr, - fr_type_t type, dict_attr_args_t const *args); + fr_type_t type, dict_attr_args_t const *args) CC_HINT(nonnull(1,2)); + +fr_dict_attr_t *dict_attr_alloc_root(TALLOC_CTX *ctx, + fr_dict_t const *dict, + char const *name, int attr, + dict_attr_args_t const *args) CC_HINT(nonnull(2,3)); fr_dict_attr_t *dict_attr_alloc(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, char const *name, int attr, - fr_type_t type, dict_attr_args_t const *args); + fr_type_t type, dict_attr_args_t const *args) CC_HINT(nonnull(2)); fr_dict_attr_t *dict_attr_acopy(TALLOC_CTX *ctx, fr_dict_attr_t const *in, char const *new_name); diff --git a/src/lib/util/dict_tokenize.c b/src/lib/util/dict_tokenize.c index e0dd41378521e..b53c6ee22fc17 100644 --- a/src/lib/util/dict_tokenize.c +++ b/src/lib/util/dict_tokenize.c @@ -172,8 +172,7 @@ static int dict_root_set(fr_dict_t *dict, char const *name, unsigned int proto_n return -1; } - da = dict_attr_alloc(dict->pool, NULL, name, proto_number, FR_TYPE_TLV, - &(dict_attr_args_t){ .flags = &flags }); + da = dict_attr_alloc_root(dict->pool, dict, name, proto_number, &(dict_attr_args_t){ .flags = &flags }); if (unlikely(!da)) return -1; dict->root = da; @@ -319,10 +318,10 @@ static int dict_process_flag_field(dict_tokenize_ctx_t *ctx, char *name, fr_type * Allow for "key1,key2". But is has to be the * last string in the flags field. */ - if (ctx->dict->subtype_table) { + if (ctx->dict->proto->subtype_table) { int subtype; - subtype = fr_table_value_by_str(ctx->dict->subtype_table, key, -1); + subtype = fr_table_value_by_str(ctx->dict->proto->subtype_table, key, -1); if (subtype >= 0) { if (flags->subtype != 0) { fr_strerror_printf("Conflicting flag '%s'", key); @@ -608,7 +607,7 @@ static int dict_process_flag_field(dict_tokenize_ctx_t *ctx, char *name, fr_type } } - } else if (ctx->dict->subtype_table) { + } else if (ctx->dict->proto->subtype_table) { int subtype; if (value) value[-1] = '='; /* hackity hack */ @@ -624,7 +623,7 @@ static int dict_process_flag_field(dict_tokenize_ctx_t *ctx, char *name, fr_type return -1; } - subtype = fr_table_value_by_str(ctx->dict->subtype_table, key, -1); + subtype = fr_table_value_by_str(ctx->dict->proto->subtype_table, key, -1); if (subtype < 0) goto unknown_option; flags->subtype = subtype; @@ -1938,8 +1937,8 @@ static int dict_read_process_protocol(char **argv, int argc) mutable = UNCONST(fr_dict_attr_t *, dict->root); dict->string_based = string_based; if (!type_size) { - mutable->flags.type_size = dict->default_type_size; - mutable->flags.length = dict->default_type_length; + mutable->flags.type_size = dict->proto->default_type_size; + mutable->flags.length = dict->proto->default_type_length; } else { mutable->flags.type_size = type_size; mutable->flags.length = 1; /* who knows... */ @@ -2607,8 +2606,8 @@ static int _dict_from_file(dict_tokenize_ctx_t *ctx, if (!vendor_da) { memset(&flags, 0, sizeof(flags)); - flags.type_size = ctx->dict->default_type_size; - flags.length = ctx->dict->default_type_length; + flags.type_size = ctx->dict->proto->default_type_size; + flags.length = ctx->dict->proto->default_type_length; /* * See if this vendor has diff --git a/src/lib/util/dict_unknown.c b/src/lib/util/dict_unknown.c index 3565d579bb7c7..00adb07e8586f 100644 --- a/src/lib/util/dict_unknown.c +++ b/src/lib/util/dict_unknown.c @@ -212,7 +212,7 @@ static fr_dict_attr_t *dict_unknown_alloc(TALLOC_CTX *ctx, fr_dict_attr_t const /* * Initialize the rest of the fields. */ - dict_attr_init(&n, parent, da->name, da->attr, type, &(dict_attr_args_t){ .flags = &flags }); + dict_attr_init(&n, da->dict, parent, da->name, da->attr, type, &(dict_attr_args_t){ .flags = &flags }); if (type != FR_TYPE_OCTETS) dict_attr_ext_copy_all(&n, da); DA_VERIFY(n); @@ -461,7 +461,7 @@ fr_slen_t fr_dict_unknown_afrom_oid_substr(TALLOC_CTX *ctx, our_parent = ni; continue; } - if (dict_attr_init(&n, our_parent, NULL, num, FR_TYPE_VENDOR, + if (dict_attr_init(&n, our_parent->dict, our_parent, NULL, num, FR_TYPE_VENDOR, &(dict_attr_args_t){ .flags = &flags }) < 0) goto error; } break; @@ -493,7 +493,7 @@ fr_slen_t fr_dict_unknown_afrom_oid_substr(TALLOC_CTX *ctx, fr_type_to_str(our_parent->type)); goto error; } - if (dict_attr_init(&n, our_parent, NULL, num, FR_TYPE_OCTETS, + if (dict_attr_init(&n, our_parent->dict, our_parent, NULL, num, FR_TYPE_OCTETS, &(dict_attr_args_t){ .flags = &flags }) < 0) goto error; break; } diff --git a/src/lib/util/dict_util.c b/src/lib/util/dict_util.c index 742ac9778427c..083d46b5aa894 100644 --- a/src/lib/util/dict_util.c +++ b/src/lib/util/dict_util.c @@ -27,11 +27,13 @@ RCSID("$Id$") #include #include #include +#include #include #include #include #include #include +#include #ifdef HAVE_SYS_STAT_H # include @@ -81,6 +83,18 @@ bool const fr_dict_enum_allowed_chars[UINT8_MAX + 1] = { ['z'] = true }; +/** Default protocol rules set for every dictionary + * + * This is usually overriden by the public symbol from the protocol library + * associated with the dictionary + * e.g. libfreeradius-dhcpv6.so -> libfreeradius_dhcpv6_dict_protocol. + */ +fr_dict_protocol_t dict_proto_default = { + .name = "default", + .default_type_size = 2, + .default_type_length = 2, +}; + /* * Create the hash of the name. * @@ -512,14 +526,19 @@ static inline CC_HINT(always_inline) int dict_attr_namespace_init(fr_dict_attr_t * @note This function can only be used _before_ the attribute is inserted into the dictionary. * * @param[in] da_p to initialise. - * @param[in] parent of the attribute, if none, should be - * the dictionary root. + * @param[in] dict the attribute will be used in. + * @param[in] parent of the attribute, if none, this attribute will + * be initialised as a dictionary root. * @param[in] name of attribute. Pass NULL for auto-generated name. * @param[in] attr number. * @param[in] type of the attribute. * @param[in] args optional initialisation arguments. + * @return + * - 0 on success. + * - <0 on error. */ int dict_attr_init(fr_dict_attr_t **da_p, + fr_dict_t const *dict, fr_dict_attr_t const *parent, char const *name, int attr, fr_type_t type, dict_attr_args_t const *args) @@ -536,6 +555,14 @@ int dict_attr_init(fr_dict_attr_t **da_p, .parent = parent, }; + /* + * Allocate room for the protocol specific flags + */ + if (dict->proto && dict->proto->attr.flags_len > 0) { + if (unlikely(dict_attr_ext_alloc_size(da_p, FR_DICT_ATTR_EXT_PROTOCOL_SPECIFIC, + dict->proto->attr.flags_len) == NULL)) return -1; + } + /* * Record the parent */ @@ -552,6 +579,9 @@ int dict_attr_init(fr_dict_attr_t **da_p, } else { dict_attr_ext_copy(da_p, parent, FR_DICT_ATTR_EXT_VENDOR); /* Noop if no vendor extension */ } + /* + * This is a root attribute. + */ } else { (*da_p)->depth = 0; } @@ -681,11 +711,41 @@ fr_dict_attr_t *dict_attr_alloc_null(TALLOC_CTX *ctx) return da; } +/** Allocate a dictionary root attribute on the heap + * + * @param[in] ctx to allocate the attribute in. + * @param[in] dict the attribute will be used in. + * @param[in] name of the attribute. If NULL an OID string + * will be created and set as the name. + * @param[in] proto_number number. This should be + * @param[in] args optional initialisation arguments. + * @return + * - A new fr_dict_attr_t on success. + * - NULL on failure. + */ +fr_dict_attr_t *dict_attr_alloc_root(TALLOC_CTX *ctx, + fr_dict_t const *dict, + char const *name, int proto_number, + dict_attr_args_t const *args) +{ + fr_dict_attr_t *n; + + n = dict_attr_alloc_null(ctx); + if (unlikely(!n)) return NULL; + + if (dict_attr_init(&n, dict, NULL, name, proto_number, FR_TYPE_TLV, args) < 0) { + talloc_free(n); + return NULL; + } + + return n; +} + + /** Allocate a dictionary attribute on the heap * * @param[in] ctx to allocate the attribute in. - * @param[in] parent of the attribute, if none, should be - * the dictionary root. + * @param[in] parent of the attribute. * @param[in] name of the attribute. If NULL an OID string * will be created and set as the name. * @param[in] attr number. @@ -705,7 +765,7 @@ fr_dict_attr_t *dict_attr_alloc(TALLOC_CTX *ctx, n = dict_attr_alloc_null(ctx); if (unlikely(!n)) return NULL; - if (dict_attr_init(&n, parent, name, attr, type, args) < 0) { + if (dict_attr_init(&n, parent->dict, parent, name, attr, type, args) < 0) { talloc_free(n); return NULL; } @@ -753,7 +813,7 @@ static fr_dict_attr_t *dict_attr_acopy_dict(TALLOC_CTX *ctx, fr_dict_attr_t *par { fr_dict_attr_t *n; - n = dict_attr_alloc(ctx, parent,in->name, + n = dict_attr_alloc(ctx, parent, in->name, in->attr, in->type, &(dict_attr_args_t){ .flags = &in->flags }); if (unlikely(!n)) return NULL; @@ -3203,29 +3263,70 @@ fr_slen_t fr_dict_enum_name_from_substr(fr_sbuff_t *out, fr_sbuff_parse_error_t int dict_dlopen(fr_dict_t *dict, char const *name) { - char *module_name; - char *p, *q; + char *lib_name; + char *sym_name; + fr_dict_protocol_t *proto; if (!name) return 0; - module_name = talloc_typed_asprintf(NULL, "libfreeradius-%s", name); - for (p = module_name, q = p + talloc_array_length(p) - 1; p < q; p++) *p = tolower((uint8_t) *p); + lib_name = talloc_typed_asprintf(NULL, "libfreeradius-%s", name); + if (unlikely(lib_name == NULL)) { + oom: + fr_strerror_const("Out of memory"); + return -1; + } + talloc_bstr_tolower(lib_name); + + dict->dl = dl_by_name(dict_gctx->dict_loader, lib_name, NULL, false); + if (!dict->dl) { + fr_strerror_printf_push("Failed loading dictionary validation library \"%s\"", lib_name); + talloc_free(lib_name); + return -1; + } + talloc_free(lib_name); /* - * Pass in dict as the uctx so that we can get at it in - * any callbacks. + * The public symbol that contains per-protocol rules + * and extensions. * - * Not all dictionaries have validation functions. It's - * a soft error if they don't exist. + * It ends up being easier to do this using dlsym to + * resolve the symbol and not use the autoloader + * callbacks as theoretically multiple dictionaries + * could use the same protocol library, and then the + * autoloader callback would only run for the first + * dictionary which loaded the protocol. */ - dict->dl = dl_by_name(dict_gctx->dict_loader, module_name, dict, false); - if (!dict->dl) { - fr_strerror_printf_push("Failed loading dictionary validation library \"%s\"", module_name); - talloc_free(module_name); - return -1; + sym_name = talloc_typed_asprintf(NULL, "libfreeradius_%s_dict_protocol", name); + if (unlikely(sym_name == NULL)) { + talloc_free(lib_name); + goto oom; + } + talloc_bstr_tolower(sym_name); + + /* + * De-hyphenate the symbol name + */ + { + char *p, *q; + + for (p = sym_name, q = p + (talloc_array_length(sym_name) - 1); p < q; p++) *p = *p == '-' ? '_' : *p; } - talloc_free(module_name); + proto = dlsym(dict->dl->handle, sym_name); + talloc_free(sym_name); + + /* + * Soft failure, not all protocol libraires provide + * custom validation functions or flats. + */ + if (!proto) return 0; + + /* + * Replace the default protocol with the custom one + * if we have it... + */ + dict->proto = proto; + return 0; } @@ -3437,7 +3538,7 @@ static int _dict_free(fr_dict_t *dict) if (dict_has_dependents(dict)) { fr_rb_iter_inorder_t iter; - fr_dict_dependent_t *dep; + fr_dict_dependent_t *dep; fr_strerror_printf("Refusing to free dictionary \"%s\", still has dependents", dict->root->name); @@ -3542,10 +3643,10 @@ fr_dict_t *dict_alloc(TALLOC_CTX *ctx) dict->dependents = fr_rb_inline_alloc(dict, fr_dict_dependent_t, node, _dict_dependent_cmp, NULL); /* - * Set default type size and length. + * Set the default dictionary protocol, this can + * be overriden by the protocol library. */ - dict->default_type_size = 1; - dict->default_type_length = 1; + dict->proto = &dict_proto_default; return dict; } @@ -3577,18 +3678,12 @@ fr_dict_t *fr_dict_protocol_alloc(fr_dict_t const *parent) dict = dict_alloc(UNCONST(fr_dict_t *, parent)); if (!dict) return NULL; - /* - * Allow for 64k local attributes. - */ - dict->default_type_size = 2; - dict->default_type_length = 2; - /* * Allocate the root attribute. This dictionary is * always protocol "local", and number "0". */ - da = dict_attr_alloc(dict->pool, NULL, "local", 0, FR_TYPE_TLV, - &(dict_attr_args_t){ .flags = &flags }); + da = dict_attr_alloc_root(dict->pool, parent, "local", 0, + &(dict_attr_args_t){ .flags = &flags }); if (unlikely(!da)) { talloc_free(dict); return NULL; @@ -3917,41 +4012,6 @@ void fr_dl_dict_autofree(UNUSED dl_t const *module, void *symbol, UNUSED void *u fr_dict_autofree(((fr_dict_autoload_t *)symbol)); } -/** Callback to automatically load validation routines for dictionaries. - * - * @param[in] dl the library we just loaded - * @param[in] symbol pointer to a fr_dict_protocol_t table - * @param[in] user_ctx the global context which we don't need - * @return - * - 0 on success. - * - -1 on failure. - */ -static int _dict_validation_onload(dl_t const *dl, void *symbol, UNUSED void *user_ctx) -{ - fr_dict_t *dict = talloc_get_type_abort(dl->uctx, fr_dict_t); - fr_dict_protocol_t const *proto = symbol; - - - /* - * Set the protocol-specific callbacks. - */ - dict->proto = proto; - - /* - * @todo - just use dict->proto->foo, once we get the - * rest of the code cleaned up. - */ -#undef COPY -#define COPY(_x) dict->_x = proto->_x - COPY(default_type_size); - COPY(default_type_length); - COPY(subtype_table); - COPY(subtype_table_len); - COPY(attr_valid); - - return 0; -} - static int _dict_global_free_at_exit(void *uctx) { return talloc_free(uctx); @@ -4069,8 +4129,6 @@ fr_dict_gctx_t *fr_dict_global_ctx_init(TALLOC_CTX *ctx, bool free_at_exit, char new_ctx->dict_loader = dl_loader_init(new_ctx, NULL, false, false); if (!new_ctx->dict_loader) goto error; - if (dl_symbol_init_cb_register(new_ctx->dict_loader, 0, "dict_protocol", - _dict_validation_onload, NULL) < 0) goto error; new_ctx->free_at_exit = free_at_exit; talloc_set_destructor(new_ctx, _dict_global_free); diff --git a/src/lib/util/dict_validate.c b/src/lib/util/dict_validate.c index 9e729c08ef2f7..8fd6da896cd10 100644 --- a/src/lib/util/dict_validate.c +++ b/src/lib/util/dict_validate.c @@ -696,7 +696,7 @@ bool dict_attr_fields_valid(fr_dict_t *dict, fr_dict_attr_t const *parent, * Run protocol-specific validation functions, BEFORE we * do the rest of the checks. */ - if (dict->attr_valid && !dict->attr_valid(dict, parent, name, *attr, type, flags)) return false; + if (dict->proto->attr.valid && !dict->proto->attr.valid(dict, parent, name, *attr, type, flags)) return false; /* * Check the flags, data types, and parent data types and flags. diff --git a/src/protocols/dhcpv4/base.c b/src/protocols/dhcpv4/base.c index 65633123e3e4d..3ed2ad6014ae0 100644 --- a/src/protocols/dhcpv4/base.c +++ b/src/protocols/dhcpv4/base.c @@ -736,7 +736,9 @@ fr_dict_protocol_t libfreeradius_dhcpv4_dict_protocol = { .default_type_length = 1, .subtype_table = subtype_table, .subtype_table_len = NUM_ELEMENTS(subtype_table), - .attr_valid = attr_valid, + .attr = { + .valid = attr_valid + }, .init = fr_dhcpv4_global_init, .free = fr_dhcpv4_global_free, diff --git a/src/protocols/dhcpv6/base.c b/src/protocols/dhcpv6/base.c index 35cc68562350b..1dacbff991dbc 100644 --- a/src/protocols/dhcpv6/base.c +++ b/src/protocols/dhcpv6/base.c @@ -786,7 +786,7 @@ ssize_t fr_dhcpv6_encode(fr_dbuff_t *dbuff, uint8_t const *original, size_t leng fr_pair_dcursor_iter_init(&cursor, vps, fr_dhcpv6_next_encodable, dict_dhcpv6); while ((fr_dbuff_extend(&frame_dbuff) > 0) && (fr_dcursor_current(&cursor) != NULL)) { - slen = fr_dhcpv6_encode_option(&frame_dbuff, &cursor, &packet_ctx); + slen = fr_dhcpv6_encode_option(&frame_dbuff, &cursor, &packet_ctx); if (slen < 0) return slen - fr_dbuff_used(&frame_dbuff); } @@ -988,7 +988,9 @@ fr_dict_protocol_t libfreeradius_dhcpv6_dict_protocol = { .default_type_length = 2, .subtype_table = subtype_table, .subtype_table_len = NUM_ELEMENTS(subtype_table), - .attr_valid = attr_valid, + .attr = { + .valid = attr_valid, + }, .init = fr_dhcpv6_global_init, .free = fr_dhcpv6_global_free, diff --git a/src/protocols/dns/base.c b/src/protocols/dns/base.c index 567634561b4b0..2d6816811fe1e 100644 --- a/src/protocols/dns/base.c +++ b/src/protocols/dns/base.c @@ -472,7 +472,9 @@ fr_dict_protocol_t libfreeradius_dns_dict_protocol = { .default_type_length = 2, .subtype_table = subtype_table, .subtype_table_len = NUM_ELEMENTS(subtype_table), - .attr_valid = attr_valid, + .attr = { + .valid = attr_valid + }, .init = fr_dns_global_init, .free = fr_dns_global_free, diff --git a/src/protocols/radius/base.c b/src/protocols/radius/base.c index 7f3bd29534b5a..227cceba78696 100644 --- a/src/protocols/radius/base.c +++ b/src/protocols/radius/base.c @@ -1382,7 +1382,9 @@ fr_dict_protocol_t libfreeradius_radius_dict_protocol = { .default_type_length = 1, .subtype_table = subtype_table, .subtype_table_len = NUM_ELEMENTS(subtype_table), - .attr_valid = attr_valid, + .attr = { + .valid = attr_valid, + }, .init = fr_radius_global_init, .free = fr_radius_global_free,