]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add fr_dict_enum_by_name_substr()
authorAlan T. DeKok <aland@freeradius.org>
Fri, 14 Jan 2022 20:51:01 +0000 (15:51 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Sat, 15 Jan 2022 12:36:50 +0000 (07:36 -0500)
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
src/lib/util/dict_ext.h
src/lib/util/dict_util.c

index 47aa9385519381a527e99d2c80ec0a4d10031f0d..21a3e3b3a1b70430f8ef735b5c5477e1007586f0 100644 (file)
@@ -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
index 7a84e31fa9f6457417ca03a548278edbbea352cb..1535e2effcb1f6791470fb06f953341ce833d402 100644 (file)
@@ -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;
index 85913c9d218737369a2d0b3632f4ca5bd80ed47d..b90c8278b017341e81c07fc2d0c7fb596507351b 100644 (file)
@@ -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;