Skip to content

Commit

Permalink
Remove level of annoying indirection and copying things from the fr_d…
Browse files Browse the repository at this point in the history
…ict_protocol_t to the dict

From comments this seems mostly to avoid cleaning up all the references to default_type_size and subtype_table.

Load the protocol symbol directly using dlsym, as this'll run every time the library is referenced and not just the first time.

Allocate a dictionary attribute extension for protocol specific data if requested to by the fr_dict_protocol_t
  • Loading branch information
arr2036 committed Oct 10, 2024
1 parent 50986c0 commit aac0742
Show file tree
Hide file tree
Showing 11 changed files with 239 additions and 114 deletions.
85 changes: 73 additions & 12 deletions src/lib/util/dict.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/util/dict_print.c
Original file line number Diff line number Diff line change
Expand Up @@ -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, ',');
}

Expand Down
25 changes: 12 additions & 13 deletions src/lib/util/dict_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);

Expand Down
19 changes: 9 additions & 10 deletions src/lib/util/dict_tokenize.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 */
Expand All @@ -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;
Expand Down Expand Up @@ -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... */
Expand Down Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions src/lib/util/dict_unknown.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down
Loading

0 comments on commit aac0742

Please sign in to comment.