VALUE Event-Id DS0s-Out-of-Service 78
VALUE Event-Id T1/T1PRI/E1PRI-Call-Event 79
VALUE Event-Id Psu-Incompatible 80
-VALUE Event-Id T1,T1-E1/PRI-Call-Arrive-Event 81
-VALUE Event-Id T1,T1-E1/PRI-Call-Connect-Event 82
-VALUE Event-Id T1,T1-E1/PRI-Call-Termina-Event 83
-VALUE Event-Id T1,T1-E1/PRI-Call-Failed-Event 84
+VALUE Event-Id T1/T1-E1/PRI-Call-Arrive-Event 81
+VALUE Event-Id T1/T1-E1/PRI-Call-Connect-Event 82
+VALUE Event-Id T1/T1-E1/PRI-Call-Termina-Event 83
+VALUE Event-Id T1/T1-E1/PRI-Call-Failed-Event 84
VALUE Event-Id DNS-Contact-Lost 85
VALUE Event-Id NTP-Contact-Lost 86
VALUE Event-Id NTP-Contact-Restored 87
VALUE Request-Type Reserved 255
VALUE Speed-Of-Connection Auto 0
-VALUE Speed-Of-Connection 56 1
-VALUE Speed-Of-Connection 64 2
+VALUE Speed-Of-Connection 56K 1
+VALUE Speed-Of-Connection 64K 2
VALUE Speed-Of-Connection Voice 3
VALUE Expansion-Algorithm Constant 1
{
fr_dict_attr_t *da;
fr_value_box_t value;
+ fr_slen_t enum_len;
fr_dict_attr_t const *parent = ctx->stack[ctx->stack_depth].da;
if (argc != 3) {
}
da = ctx->value_attr;
+ /*
+ * Verify the enum name matches the expected from.
+ */
+ enum_len = (fr_slen_t)strlen(argv[1]);
+ if (fr_dict_enum_name_from_substr(NULL, &FR_SBUFF_IN(argv[1], enum_len), NULL) != enum_len) {
+ fr_strerror_printf_push("Invalid VALUE name '%s' for attribute '%s'", argv[1], da->name);
+ return -1;
+ }
+
/*
* Remember which attribute is associated with this
* value. This allows us to define enum
}
/*
- * Only a few data types can have VALUEs defined.
+ * Only a leaf types can have values defined.
*/
- switch (da->type) {
- case FR_TYPE_STRUCTURAL:
- case FR_TYPE_NULL:
- case FR_TYPE_MAX:
+ if (!fr_type_is_leaf(da->type)) {
fr_strerror_printf_push("Cannot define VALUE for attribute '%s' of data type '%s'", da->name,
fr_table_str_by_value(fr_value_box_type_table, da->type, "<INVALID>"));
return -1;
-
- default:
- break;
}
if (fr_value_box_from_str(NULL, &value, da->type, NULL,
['z'] = true
};
+/** Characters allowed in enumeration value names
+ *
+ */
+bool const fr_dict_enum_allowed_chars[UINT8_MAX + 1] = {
+ ['+'] = true, ['-'] = true, ['.'] = true, ['/'] = true, ['_'] = true,
+ ['0'] = true, ['1'] = true, ['2'] = true, ['3'] = true, ['4'] = true,
+ ['5'] = true, ['6'] = true, ['7'] = true, ['8'] = true, ['9'] = true,
+ ['A'] = true, ['B'] = true, ['C'] = true, ['D'] = true, ['E'] = true,
+ ['F'] = true, ['G'] = true, ['H'] = true, ['I'] = true, ['J'] = true,
+ ['K'] = true, ['L'] = true, ['M'] = true, ['N'] = true, ['O'] = true,
+ ['P'] = true, ['Q'] = true, ['R'] = true, ['S'] = true, ['T'] = true,
+ ['U'] = true, ['V'] = true, ['W'] = true, ['X'] = true, ['Y'] = true,
+ ['Z'] = true,
+ ['a'] = true, ['b'] = true, ['c'] = true, ['d'] = true, ['e'] = true,
+ ['f'] = true, ['g'] = true, ['h'] = true, ['i'] = true, ['j'] = true,
+ ['k'] = true, ['l'] = true, ['m'] = true, ['n'] = true, ['o'] = true,
+ ['p'] = true, ['q'] = true, ['r'] = true, ['s'] = true, ['t'] = true,
+ ['u'] = true, ['v'] = true, ['w'] = true, ['x'] = true, ['y'] = true,
+ ['z'] = true
+};
+
/*
* Create the hash of the name.
*
return 0;
}
+/** Extract an enumeration name from a string
+ *
+ * This function defines the canonical format for an enumeration name.
+ *
+ * An enumeration name is made up of one or more fr_dict_attr_allowed_chars
+ * with at least one character in the sequence not being a special character
+ * i.e. [-+/_] or a number.
+ *
+ * This disambiguates enumeration identifiers from mathematical expressions.
+ *
+ * If we allowed enumeration names consisting of sequences of numbers separated
+ * by special characters it would not be possible to determine if the special
+ * character were an operator in a subexpression.
+ *
+ * For example take:
+ *
+ * &My-Enum-Attr == 01234-5678
+ *
+ * Without having access to the enumeration values of My-Enum-Attr (which we
+ * might not have during tokenisation), we cannot tell if this is:
+ *
+ * (&My-Enum-Attr == 01234-5678)
+ *
+ * OR
+ *
+ * ((&My-Enum-Attr == 01234) - 5678)
+ *
+ * If an alpha character occurs anywhere in the string i.e:
+ *
+ * (&My-Enum-Attr == 01234-A5678)
+ *
+ * we know 01234-A5678 can't be a mathematical sub-expression because the
+ * second potential operand can no longer be parsed as an integer constant.
+ *
+ * @param[out] out The name string we managed to extract.
+ * May be NULL in which case only the length of the name
+ * will be returned.
+ * @param[in] in The string containing the enum identifier.
+ * @param[in] tt If non-null verify that a terminal sequence occurs
+ * after the enumeration name.
+ * @return
+ * - <0 the offset at which the parse error occurred.
+ * - >1 the number of bytes parsed.
+ */
+fr_slen_t fr_dict_enum_name_from_substr(fr_sbuff_t *out, fr_sbuff_t *in, fr_sbuff_term_t const *tt)
+{
+ fr_sbuff_t our_in = FR_SBUFF(in);
+ bool seen_alpha = false;
+
+ while (fr_sbuff_is_in_charset(&our_in, fr_dict_enum_allowed_chars)) {
+ if (fr_sbuff_is_alpha(&our_in)) seen_alpha = true;
+ fr_sbuff_next(&our_in);
+ }
+
+ if (!seen_alpha) {
+ if (fr_sbuff_used(&our_in) == 0) {
+ fr_strerror_const("VALUE name empty");
+ return -1;
+ }
+
+ fr_strerror_const("VALUE name must contain at least one alpha character");
+ return -1;
+ }
+
+ /*
+ * Check that the sequence is correctly terminated
+ */
+ if (tt && !fr_sbuff_is_terminal(&our_in, tt)) {
+ fr_strerror_const("VALUE name has trailing text");
+ return fr_sbuff_error(&our_in);
+ }
+
+ if (out) return fr_sbuff_out_bstrncpy_exact(out, in, fr_sbuff_used(&our_in));
+
+ return fr_sbuff_set(in, &our_in);
+}
+
int dict_dlopen(fr_dict_t *dict, char const *name)
{
char *module_name;