From 747b00763eee64955f6709b9f5835e7a3d32bd65 Mon Sep 17 00:00:00 2001 From: "Alan T. DeKok" Date: Fri, 14 Jan 2022 15:51:01 -0500 Subject: [PATCH] add fr_dict_enum_by_name_substr() which parses an enumv by name, but doesn't take a "terminals" argument. Because the enums are named, and if we see a correct name, then it's correct, no matter what the terminals are. --- src/lib/util/dict.h | 2 ++ src/lib/util/dict_ext.h | 1 + src/lib/util/dict_util.c | 58 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/lib/util/dict.h b/src/lib/util/dict.h index 47aa938551..21a3e3b3a1 100644 --- a/src/lib/util/dict.h +++ b/src/lib/util/dict.h @@ -559,6 +559,8 @@ fr_dict_enum_value_t *fr_dict_enum_by_value(fr_dict_attr_t const *da, fr_value_ char const *fr_dict_enum_name_by_value(fr_dict_attr_t const *da, fr_value_box_t const *value); fr_dict_enum_value_t *fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len); + +ssize_t fr_dict_enum_by_name_substr(fr_dict_enum_value_t **out, fr_dict_attr_t const *da, fr_sbuff_t *in); /** @} */ /** @name Dictionary and protocol loading diff --git a/src/lib/util/dict_ext.h b/src/lib/util/dict_ext.h index 7a84e31fa9..1535e2effc 100644 --- a/src/lib/util/dict_ext.h +++ b/src/lib/util/dict_ext.h @@ -84,6 +84,7 @@ typedef struct { * */ typedef struct { + size_t max_name_len; //!< maximum length of a name fr_hash_table_t *value_by_name; //!< Lookup an enumeration value by name fr_hash_table_t *name_by_value; //!< Lookup a name by value } fr_dict_attr_ext_enumv_t; diff --git a/src/lib/util/dict_util.c b/src/lib/util/dict_util.c index 85913c9d21..b90c8278b0 100644 --- a/src/lib/util/dict_util.c +++ b/src/lib/util/dict_util.c @@ -1270,7 +1270,7 @@ int dict_attr_enum_add_name(fr_dict_attr_t *da, char const *name, fr_dict_attr_t const *child_struct) { size_t len; - fr_dict_enum_value_t *enumv = NULL; + fr_dict_enum_value_t *enumv = NULL; fr_value_box_t *enum_value = NULL; fr_dict_attr_ext_enumv_t *ext; @@ -1337,7 +1337,7 @@ int dict_attr_enum_add_name(fr_dict_attr_t *da, char const *name, talloc_set_type(enumv, fr_dict_enum_value_t); enumv->name = talloc_typed_strdup(enumv, name); - enumv->name_len = strlen(name); + enumv->name_len = len; if (child_struct) enumv->child_struct[0] = child_struct; enum_value = fr_value_box_alloc(enumv, da->type, NULL, false); @@ -1398,6 +1398,8 @@ int dict_attr_enum_add_name(fr_dict_attr_t *da, char const *name, talloc_free(enumv); return -1; } + + if (enumv->name_len > ext->max_name_len) ext->max_name_len = enumv->name_len; } /* @@ -2872,6 +2874,58 @@ fr_dict_enum_value_t *fr_dict_enum_by_name(fr_dict_attr_t const *da, char const return fr_hash_table_find(ext->value_by_name, &(fr_dict_enum_value_t){ .name = name, .name_len = len}); } +/* + * Get a value by its name, keyed off of an attribute, from an sbuff + */ +ssize_t fr_dict_enum_by_name_substr(fr_dict_enum_value_t **out, fr_dict_attr_t const *da, fr_sbuff_t *in) +{ + fr_dict_attr_ext_enumv_t *ext; + fr_sbuff_t our_in = FR_SBUFF(in); + fr_dict_enum_value_t *found = NULL; + size_t found_len = 0; + uint8_t *p; + uint8_t name[FR_DICT_ENUM_MAX_NAME_LEN + 1]; + + /* + * No values associated with this attribute, do nothing. + */ + ext = fr_dict_attr_ext(da, FR_DICT_ATTR_EXT_ENUMV); + if (!ext || !ext->value_by_name) return 0; + + /* + * Loop until we exhaust all of the possibilities. + */ + for (p = name; (size_t) (p - name) < ext->max_name_len; p++) { + int len = (p - name) + 1; + fr_dict_enum_value_t *enumv; + + *p = *fr_sbuff_current(&our_in); + if (!fr_dict_attr_allowed_chars[*p]) { + break; + } + fr_sbuff_next(&our_in); + + enumv = fr_hash_table_find(ext->value_by_name, &(fr_dict_enum_value_t){ .name = (char const *) name, + .name_len = len}); + + /* + * Return the LONGEST match, as there may be + * overlaps. e.g. "Framed", and "Framed-User". + */ + if (enumv) { + found = enumv; + found_len = len; + } + } + + if (found) { + *out = found; + return fr_sbuff_set(in, found_len); + } + + return 0; +} + int dict_dlopen(fr_dict_t *dict, char const *name) { char *module_name; -- 2.47.2