static ssize_t command_tmpl_rule_attr_parent(UNUSED TALLOC_CTX *ctx, tmpl_rules_t *rules, fr_sbuff_t *value)
{
- return fr_dict_attr_by_oid_substr(NULL,
+ fr_dict_attr_err_t err;
+ fr_slen_t slen;
+
+ slen = fr_dict_attr_by_oid_substr(&err,
&rules->attr.parent,
rules->attr.dict_def ? fr_dict_root(rules->attr.dict_def) :
fr_dict_root(fr_dict_internal()),
value, NULL);
+ if (err != FR_DICT_ATTR_OK) FR_SBUFF_ERROR_RETURN(value);
+ return slen;
}
static ssize_t command_tmpl_rule_disallow_internal(UNUSED TALLOC_CTX *ctx, tmpl_rules_t *rules, fr_sbuff_t *value)
return 0;
}
-static int cond_forbid_groups(tmpl_t *vpt, fr_sbuff_t *in, fr_sbuff_marker_t *m_lhs)
+static CC_HINT(nonnull) int cond_forbid_groups(tmpl_t *vpt, fr_sbuff_t *in, fr_sbuff_marker_t *m_lhs)
{
if (tmpl_is_list(vpt)) {
fr_strerror_const("Cannot use list references in condition");
return 0;
}
-static ssize_t cond_tokenize_operand(fr_cond_t *c, tmpl_t **out,
- fr_sbuff_marker_t *opd_start, fr_sbuff_t *in,
- tmpl_rules_t const *t_rules, bool simple_parse)
+static fr_slen_t cond_tokenize_operand(fr_cond_t *c, tmpl_t **out,
+ fr_sbuff_marker_t *opd_start, fr_sbuff_t *in,
+ tmpl_rules_t const *t_rules, bool simple_parse)
{
fr_sbuff_term_t const bareword_terminals =
FR_SBUFF_TERMS(
fr_type_t cast = FR_TYPE_NULL;
fr_sbuff_parse_rules_t tmp_p_rules;
fr_sbuff_parse_rules_t const *p_rules;
- ssize_t slen;
+ fr_slen_t slen;
tmpl_rules_t our_t_rules = *t_rules;
*out = NULL;
/*
* Parse (optional) cast
*/
- slen = tmpl_cast_from_substr(&our_t_rules, &our_in);
- if (slen < 0) return slen;
+ if (tmpl_cast_from_substr(&our_t_rules, &our_in) < 0) return fr_sbuff_error(&our_in);
fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX, NULL);
fr_sbuff_marker(&m, &our_in);
}
slen = tmpl_afrom_substr(c, &vpt, &our_in, type, p_rules, &our_t_rules);
- if (!vpt) {
- fr_sbuff_advance(&our_in, slen * -1);
-
+ if (slen < 0) {
error:
talloc_free(vpt);
- return -(fr_sbuff_used_total(&our_in));
+ return fr_sbuff_error(&our_in);
}
if ((type != T_BARE_WORD) && !fr_sbuff_next_if_char(&our_in, fr_token_quote[type])) { /* Quoting */
fr_strerror_const("Unterminated string");
fr_sbuff_set(&our_in, &m);
- fr_sbuff_advance(&our_in, 1);
goto error;
}
goto error;
}
- slen = tmpl_regex_flags_substr(vpt, &our_in, &bareword_terminals);
- if (slen < 0) {
- fr_sbuff_advance(&our_in, slen * -1);
- goto error;
- }
+ if (tmpl_regex_flags_substr(vpt, &our_in, &bareword_terminals) < 0) goto error;
/*
* We've now got the expressions and
* regex.
*/
if (!simple_parse && tmpl_is_regex_uncompiled(vpt)) {
- slen = tmpl_regex_compile(vpt, true);
- if (slen <= 0) {
+ if (tmpl_regex_compile(vpt, true) < 0) {
fr_sbuff_set(&our_in, &m); /* Reset to start of expression */
- fr_sbuff_advance(&our_in, slen * -1);
goto error;
}
}
* - Length of the string skipped.
* - < 0 (the offset to the offending error) on error.
*/
-static ssize_t cond_tokenize(TALLOC_CTX *ctx, fr_cond_t **out,
- CONF_SECTION *cs, fr_sbuff_t *in, int brace,
- tmpl_rules_t const *t_rules, bool simple_parse)
+static fr_slen_t cond_tokenize(TALLOC_CTX *ctx, fr_cond_t **out,
+ CONF_SECTION *cs, fr_sbuff_t *in, int brace,
+ tmpl_rules_t const *t_rules, bool simple_parse)
{
fr_sbuff_t our_in = FR_SBUFF(in);
ssize_t slen;
fr_strerror_const("Empty condition is invalid");
error:
talloc_free(c);
- return -(fr_sbuff_used_total(&our_in));
+ FR_SBUFF_ERROR_RETURN(&our_in);
}
/*
/*
* Children are allocated from the parent.
*/
- slen = cond_tokenize(c, &c->data.child, cs, &our_in, brace + 1, t_rules, simple_parse);
- if (slen <= 0) {
- fr_sbuff_advance(&our_in, slen * -1);
- goto error;
- }
+ if (cond_tokenize(c, &c->data.child, cs, &our_in, brace + 1, t_rules, simple_parse) < 0) goto error;
if (!c->data.child) {
fr_strerror_const("Empty condition is invalid");
* Grab the LHS
*/
fr_sbuff_marker(&m_lhs_cast, &our_in);
- slen = cond_tokenize_operand(c, &lhs, &m_lhs, &our_in, t_rules, simple_parse);
- if (!lhs) {
- fr_sbuff_advance(&our_in, slen * -1);
- goto error;
- }
+ if (cond_tokenize_operand(c, &lhs, &m_lhs, &our_in, t_rules, simple_parse) < 0) goto error;
#ifdef HAVE_REGEX
/*
* Grab the RHS
*/
fr_sbuff_marker(&m_rhs_cast, &our_in);
- slen = cond_tokenize_operand(c, &rhs, &m_rhs, &our_in, t_rules, simple_parse);
- if (!rhs) {
- fr_sbuff_advance(&our_in, slen * -1);
- goto error;
- }
+ if (cond_tokenize_operand(c, &rhs, &m_rhs, &our_in, t_rules, simple_parse) < 0) goto error;
/*
* Groups can't be on the RHS of a comparison, either
* siblings are allocated from their older
* siblings.
*/
- slen = cond_tokenize(child, &child->next, cs, &our_in, brace, t_rules, simple_parse);
- if (slen <= 0) {
- fr_sbuff_advance(&our_in, slen * -1);
- goto error;
- }
-
+ if (cond_tokenize(child, &child->next, cs, &our_in, brace, t_rules, simple_parse) < 0) goto error;
c->next = child;
goto done;
}
* siblings are allocated from their older
* siblings.
*/
- slen = cond_tokenize(c, &c->next, cs, &our_in, brace, t_rules, simple_parse);
- if (slen <= 0) {
- fr_sbuff_advance(&our_in, slen * -1);
- goto error;
- }
+ if (cond_tokenize(c, &c->next, cs, &our_in, brace, t_rules, simple_parse) < 0) goto error;
done:
if (cond_normalise(ctx, lhs ? lhs->quote : T_INVALID, &c) < 0) {
talloc_free(c);
- return 0;
+ fr_sbuff_set_to_start(&our_in);
+ return fr_sbuff_error(&our_in);
}
*out = c;
error_adj:
talloc_free(map);
- FR_SBUFF_ERROR_RETURN_ADJ(&our_in, slen);
+ FR_SBUFF_ERROR_RETURN(&our_in);
}
/*
do { \
char const *ref = _attr_str; \
tmpl_afrom_attr_substr(autofree, NULL, &vpt, &FR_SBUFF_IN(ref, strlen(ref)), NULL, &(tmpl_rules_t){.attr = {.dict_def = test_dict}}); \
+ TEST_CHECK(vpt != NULL); \
+ TEST_MSG("Failed creating tmpl from %s: %s", ref, fr_strerror()); \
*(_out) = tmpl_dcursor_init(&err, NULL, &cc, &cursor, request, vpt); \
} while (0)
unsigned int depth)
{
uint32_t oid = 0;
- ssize_t slen;
tmpl_attr_t *ar = NULL;
fr_dict_attr_t const *da;
fr_sbuff_marker_t m_s;
* No parent means we need to go hunting through all the dictionaries
*/
if (!our_parent) {
- slen = fr_dict_attr_search_by_qualified_name_substr(&dict_err, &da,
- t_rules->dict_def,
- name, p_rules ? p_rules->terminals : NULL,
- !t_rules->disallow_internal,
- t_rules->allow_foreign);
+ (void)fr_dict_attr_search_by_qualified_name_substr(&dict_err, &da,
+ t_rules->dict_def,
+ name, p_rules ? p_rules->terminals : NULL,
+ !t_rules->disallow_internal,
+ t_rules->allow_foreign);
/*
* We can't know which dictionary the
* attribute will be resolved in, so the
* or its reference in the case of group attributes.
*/
} else {
- slen = fr_dict_attr_by_name_substr(&dict_err,
- &da,
- namespace,
- name,
- p_rules ? p_rules->terminals : NULL);
+ (void)fr_dict_attr_by_name_substr(&dict_err,
+ &da,
+ namespace,
+ name,
+ p_rules ? p_rules->terminals : NULL);
/*
* Allow fallback to internal attributes
* if the parent was a group, and we're
switch (dict_err) {
case FR_DICT_ATTR_NO_CHILDREN:
if (our_parent && our_parent->flags.is_unknown) break;
- fr_sbuff_advance(name, slen * -1);
goto error;
case FR_DICT_ATTR_NOT_DESCENDENT:
- fr_sbuff_advance(name, slen * -1);
goto error;
default:
}
MEM(ar = talloc(ctx, tmpl_attr_t));
-
switch (namespace->type) {
case FR_TYPE_VSA:
da_unknown = fr_dict_unknown_vendor_afrom_num(ar, namespace, oid);
fr_sbuff_t our_in = FR_SBUFF(in);
fr_value_box_t tmp;
tmpl_t *vpt;
- fr_slen_t slen;
if (!fr_type_is_leaf(t_rules->cast)) {
fr_strerror_printf("%s is not a valid cast type",
fr_type_to_str(t_rules->cast));
- return 0;
+ return fr_sbuff_error(&our_in);
}
vpt = tmpl_alloc_null(ctx);
- slen = fr_value_box_from_substr(vpt, &tmp,
- t_rules->cast, allow_enum ? t_rules->enumv : NULL,
- &our_in, p_rules, false);
- if (slen < 0) {
+ if (fr_value_box_from_substr(vpt, &tmp,
+ t_rules->cast, allow_enum ? t_rules->enumv : NULL,
+ &our_in, p_rules, false) < 0) {
talloc_free(vpt);
- return slen;
+ return fr_sbuff_error(&our_in);
}
tmpl_init(vpt, TMPL_TYPE_DATA, quote, fr_sbuff_start(&our_in), fr_sbuff_used(&our_in), t_rules);
* @param[in] in sbuff to parse.
* @param[in] p_rules formatting rules.
* @return
- * - 0 sbuff does not contain a boolean value.
+ * - < 0 sbuff does not contain a boolean value.
* - > 0 how many bytes were parsed.
*/
-static ssize_t tmpl_afrom_bool_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in,
- fr_sbuff_parse_rules_t const *p_rules)
+static fr_slen_t tmpl_afrom_bool_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in,
+ fr_sbuff_parse_rules_t const *p_rules)
{
fr_sbuff_t our_in = FR_SBUFF(in);
bool a_bool;
if (!tmpl_substr_terminal_check(&our_in, p_rules)) {
fr_strerror_const("Unexpected text after bool");
- return -fr_sbuff_used(in);
+ return fr_sbuff_error(in);
}
MEM(vpt = tmpl_alloc(ctx, TMPL_TYPE_DATA, T_BARE_WORD, fr_sbuff_start(&our_in), fr_sbuff_used(&our_in)));
* - 0 sbuff does not contain a hex string.
* - > 0 how many bytes were parsed.
*/
-static ssize_t tmpl_afrom_octets_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in,
- fr_sbuff_parse_rules_t const *p_rules)
+static fr_slen_t tmpl_afrom_octets_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in,
+ fr_sbuff_parse_rules_t const *p_rules)
{
fr_sbuff_t our_in = FR_SBUFF(in);
tmpl_t *vpt;
fr_strerror_const("Hex string not even length");
error:
talloc_free(vpt);
- return -fr_sbuff_used(&our_in);
+ return fr_sbuff_error(&our_in);
}
if (len == 0) {
fr_strerror_const("Zero length hex string is invalid");
* @param[in] in sbuff to parse.
* @param[in] p_rules formatting rules.
* @return
- * - 0 sbuff does not contain an IPv4 address or prefix.
+ * - < 0 sbuff does not contain an IPv4 address or prefix.
* - > 0 how many bytes were parsed.
*/
-static ssize_t tmpl_afrom_ipv4_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in,
- fr_sbuff_parse_rules_t const *p_rules)
+static fr_slen_t tmpl_afrom_ipv4_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in,
+ fr_sbuff_parse_rules_t const *p_rules)
{
tmpl_t *vpt;
fr_sbuff_t our_in = FR_SBUFF(in);
fr_sbuff_out(NULL, &octet, &our_in) && fr_sbuff_next_if_char(&our_in, '.') &&
fr_sbuff_out(NULL, &octet, &our_in))) {
error:
- return -fr_sbuff_used(&our_in);
+ return fr_sbuff_error(&our_in);
}
/*
* @param[in] in sbuff to parse.
* @param[in] p_rules formatting rules.
* @return
- * - 0 sbuff does not contain an IPv4 address or prefix.
+ * - < 0 sbuff does not contain an IPv4 address or prefix.
* - > 0 how many bytes were parsed.
*/
-static ssize_t tmpl_afrom_ipv6_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in,
- fr_sbuff_parse_rules_t const *p_rules)
+static fr_slen_t tmpl_afrom_ipv6_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in,
+ fr_sbuff_parse_rules_t const *p_rules)
{
tmpl_t *vpt;
fr_sbuff_t our_in = FR_SBUFF(in);
len = fr_sbuff_adv_past_allowed(&our_in, FR_IPADDR_STRLEN + 1, ipv6_chars, NULL);
if ((len < 2) || (len > FR_IPADDR_STRLEN)) {
error:
- return -fr_sbuff_used(&our_in);
+ return fr_sbuff_error(&our_in);
}
/*
* @param[in] in sbuff to parse.
* @param[in] p_rules formatting rules.
* @return
- * - 0 sbuff does not contain a mac address.
+ * - < 0 sbuff does not contain a mac address.
* - > 0 how many bytes were parsed.
*/
static ssize_t tmpl_afrom_ether_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in,
* @param[in] in sbuff to parse.
* @param[in] p_rules formatting rules.
* @return
- * - 0 sbuff does not contain an integer.
+ * - < 0 sbuff does not contain an integer.
* - > 0 how many bytes were parsed.
*/
-static ssize_t tmpl_afrom_integer_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in,
- fr_sbuff_parse_rules_t const *p_rules)
+static fr_slen_t tmpl_afrom_integer_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in,
+ fr_sbuff_parse_rules_t const *p_rules)
{
tmpl_t *vpt;
fr_sbuff_t our_in = FR_SBUFF(in);
if (!tmpl_substr_terminal_check(&our_in, p_rules)) {
fr_strerror_const("Unexpected text after signed integer");
error:
- return -fr_sbuff_used(&our_in);
+ return fr_sbuff_error(&our_in);
}
MEM(vpt = tmpl_alloc(ctx, TMPL_TYPE_DATA,
*
* @see tmpl_afrom_attr_substr
*/
-ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out,
- fr_sbuff_t *in, fr_token_t quote,
- fr_sbuff_parse_rules_t const *p_rules,
- tmpl_rules_t const *t_rules)
+fr_slen_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out,
+ fr_sbuff_t *in, fr_token_t quote,
+ fr_sbuff_parse_rules_t const *p_rules,
+ tmpl_rules_t const *t_rules)
{
fr_sbuff_t our_in = FR_SBUFF(in);
p_rules, t_rules);
}
- if (!head) return slen;
+ if (slen < 0) return fr_sbuff_error(&our_in);
if (xlat_needs_resolving(head)) UNRESOLVED_SET(&type);
* of bareword, assume it's an enum
* value.
*/
- slen = fr_dict_enum_name_afrom_substr(vpt, &str, &sberr, &our_in, p_rules ? p_rules->terminals : NULL);
- if (slen < 0) {
+ if (fr_dict_enum_name_afrom_substr(vpt, &str, &sberr, &our_in, p_rules ? p_rules->terminals : NULL) < 0) {
/*
* Produce our own errors which make
* more sense in the context of tmpls
}
bareword_error:
talloc_free(vpt);
- return slen;
+ return fr_sbuff_error(&our_in);
}
/*
slen = xlat_tokenize_ephemeral(vpt, &head, t_rules->xlat.runtime_el,
&our_in, p_rules, t_rules);
}
- if (!head) return slen;
+ if (slen < 0) return fr_sbuff_error(&our_in);
/*
* If the string doesn't contain an xlat,
*/
slen = xlat_tokenize_argv(vpt, &head, &our_in, p_rules, t_rules);
if (slen < 0) {
- fr_sbuff_advance(&our_in, slen * -1);
talloc_free(vpt);
- return slen;
+ return fr_sbuff_error(&our_in);
}
if (xlat_needs_resolving(head)) UNRESOLVED_SET(&type);
case T_SOLIDUS_QUOTED_STRING:
{
-
xlat_exp_head_t *head = NULL;
tmpl_type_t type = TMPL_TYPE_REGEX_XLAT;
if (!fr_type_is_null(t_rules->cast)) {
fr_strerror_const("Casts cannot be used with regular expressions");
- return -1;
+ fr_sbuff_set_to_start(&our_in); /* Point to the cast */
+ FR_SBUFF_ERROR_RETURN(&our_in);
}
vpt = tmpl_alloc_null(ctx);
p_rules, t_rules);
}
- if (!head) return slen;
+ if (slen < 0) return fr_sbuff_error(&our_in);
/*
* Check if the string actually contains an xlat
default:
fr_assert(0);
- return 0; /* 0 is an error here too */
+ return fr_sbuff_error(&our_in);
}
TMPL_VERIFY(vpt);
*/
ssize_t tmpl_regex_flags_substr(tmpl_t *vpt, fr_sbuff_t *in, fr_sbuff_term_t const *terminals)
{
- ssize_t slen;
- int err = 0;
+ fr_slen_t slen;
+ int err = 0;
fr_assert(tmpl_is_regex_uncompiled(vpt) || tmpl_is_regex_xlat(vpt) || tmpl_is_regex_xlat_unresolved(vpt));
bool xlat_async_required(xlat_exp_head_t const *xlat);
-ssize_t xlat_tokenize_expression(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in,
+fr_slen_t xlat_tokenize_expression(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in,
fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules);
-ssize_t xlat_tokenize_condition(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in,
+fr_slen_t xlat_tokenize_condition(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in,
fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules);
-ssize_t xlat_tokenize_ephemeral_expression(TALLOC_CTX *ctx, xlat_exp_head_t **head,
+fr_slen_t xlat_tokenize_ephemeral_expression(TALLOC_CTX *ctx, xlat_exp_head_t **head,
fr_event_list_t *el,
fr_sbuff_t *in,
fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules);
-ssize_t xlat_tokenize_ephemeral(TALLOC_CTX *ctx, xlat_exp_head_t **head,
+fr_slen_t xlat_tokenize_ephemeral(TALLOC_CTX *ctx, xlat_exp_head_t **head,
fr_event_list_t *el, fr_sbuff_t *in,
fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules);
-ssize_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in,
+fr_slen_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in,
fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules);
-ssize_t xlat_tokenize(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in,
+fr_slen_t xlat_tokenize(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in,
fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules);
-ssize_t xlat_print(fr_sbuff_t *in, xlat_exp_head_t const *node, fr_sbuff_escape_rules_t const *e_rules);
+fr_slen_t xlat_print(fr_sbuff_t *in, xlat_exp_head_t const *node, fr_sbuff_escape_rules_t const *e_rules);
static inline fr_slen_t xlat_aprint(TALLOC_CTX *ctx, char **out, xlat_exp_head_t const *head,
fr_sbuff_escape_rules_t const *e_rules)
* to parse the next thing we get. Otherwise, parse the thing as
* int64_t.
*/
-static ssize_t tokenize_unary(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_t *in,
- fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules,
- fr_sbuff_parse_rules_t const *bracket_rules, char *out_c, bool cond)
+static fr_slen_t tokenize_unary(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_t *in,
+ fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules,
+ fr_sbuff_parse_rules_t const *bracket_rules, char *out_c, bool cond)
{
- ssize_t slen;
xlat_exp_t *node = NULL, *unary = NULL;
xlat_t *func = NULL;
fr_sbuff_t our_in = FR_SBUFF(in);
check_for_double:
fr_sbuff_skip_whitespace(&our_in);
fr_sbuff_skip_whitespace(&our_in);
- if (fr_sbuff_next_if_char(&our_in, c)) {
+ if (fr_sbuff_is_char(&our_in, c)) {
fr_strerror_const("Double operator is invalid");
- return (-fr_sbuff_used(&our_in) + 1);
+ return fr_sbuff_error(&our_in);
}
}
unary->call.func = func;
unary->flags = func->flags;
- slen = tokenize_field(unary->call.args, &node, &our_in, p_rules, t_rules, bracket_rules, out_c, (c == '!'));
- if (slen < 0) {
+ if (tokenize_field(unary->call.args, &node, &our_in, p_rules, t_rules, bracket_rules, out_c, (c == '!')) < 0) {
talloc_free(unary);
- FR_SBUFF_ERROR_RETURN_ADJ(&our_in, slen);
+ FR_SBUFF_ERROR_RETURN(&our_in);
}
if (!node) {
fr_strerror_const("Empty expression is invalid");
- FR_SBUFF_ERROR_RETURN_ADJ(&our_in, -slen);
+ FR_SBUFF_ERROR_RETURN(&our_in);
}
/*
*/
if (reparse_rcode(head, &node, (c == '!')) < 0) {
talloc_free(unary);
- FR_SBUFF_ERROR_RETURN_ADJ(&our_in, -slen);
+ FR_SBUFF_ERROR_RETURN(&our_in);
}
xlat_func_append_arg(unary, node, (c == '!'));
return cast;
}
-static ssize_t expr_cast_from_substr(fr_type_t *cast, fr_sbuff_t *in)
+static fr_slen_t expr_cast_from_substr(fr_type_t *cast, fr_sbuff_t *in)
{
char close = '\0';
fr_sbuff_t our_in = FR_SBUFF(in);
if (!fr_type_is_leaf(*cast)) {
fr_strerror_printf("Invalid data type '%s' in cast", fr_type_to_str(*cast));
- return -1;
+ return fr_sbuff_error(&our_in)
}
if (!fr_sbuff_next_if_char(&our_in, close)) {
fr_strerror_const("Unterminated cast");
- return -1;
+ return fr_sbuff_error(&our_in)
}
fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX, NULL);
/*
* Tokenize the RHS of a regular expression.
*/
-static ssize_t tokenize_regex_rhs(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_t *in,
- tmpl_rules_t const *t_rules,
- fr_sbuff_parse_rules_t const *bracket_rules)
+static fr_slen_t tokenize_regex_rhs(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_t *in,
+ tmpl_rules_t const *t_rules,
+ fr_sbuff_parse_rules_t const *bracket_rules)
{
ssize_t slen;
xlat_exp_t *node = NULL;
if (!vpt) {
error:
talloc_free(node);
- fr_sbuff_set(&our_in, &opand_m);
- return -fr_sbuff_used(&our_in);
+ return fr_sbuff_error(&our_in);
}
/*
* Remember where the flags start
*/
fr_sbuff_marker(&flag, &our_in);
- slen = tmpl_regex_flags_substr(vpt, &our_in, bracket_rules->terminals);
- if (slen < 0) {
+ if (tmpl_regex_flags_substr(vpt, &our_in, bracket_rules->terminals) < 0) {
talloc_free(node);
- fr_sbuff_set(&our_in, &flag);
- fr_sbuff_advance(&our_in, -slen);
- return -fr_sbuff_used(&our_in);
+ return fr_sbuff_error(&our_in);
}
fr_sbuff_skip_whitespace(&our_in);
/*
* Tokenize a field without unary operators.
*/
-static ssize_t tokenize_field(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_t *in,
- fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules,
- fr_sbuff_parse_rules_t const *bracket_rules, char *out_c, bool cond)
+static fr_slen_t tokenize_field(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_t *in,
+ fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules,
+ fr_sbuff_parse_rules_t const *bracket_rules, char *out_c, bool cond)
{
ssize_t slen;
xlat_exp_t *node = NULL;
* No input rules means "ignore external terminal sequences, as we're expecting a ')' as
* our terminal sequence.
*/
- slen = tokenize_expression(my_head, &node, &our_in, bracket_rules, t_rules, T_INVALID, bracket_rules, NULL, cond);
- if (slen <= 0) {
+ if (tokenize_expression(my_head, &node, &our_in, bracket_rules, t_rules, T_INVALID, bracket_rules, NULL, cond) < 0) {
talloc_free(cast);
- FR_SBUFF_ERROR_RETURN_ADJ(&our_in, slen);
+ FR_SBUFF_ERROR_RETURN(&our_in);
}
if (!fr_sbuff_next_if_char(&our_in, ')')) {
talloc_free(cast);
fr_strerror_printf("Failed to find trailing ')'");
- FR_SBUFF_ERROR_RETURN_ADJ(&our_in, -slen);
+ FR_SBUFF_ERROR_RETURN(&our_in);
}
/*
* our_t_rules, and will try to parse any data there as
* of the correct type.
*/
- slen = tmpl_afrom_substr(node, &vpt, &our_in, quote, p_rules, &our_t_rules);
- if (!vpt) {
- fr_sbuff_advance(&our_in, slen * -1);
-
+ if (tmpl_afrom_substr(node, &vpt, &our_in, quote, p_rules, &our_t_rules) < 0) {
error:
- return -fr_sbuff_used(&our_in);
+ return fr_sbuff_error(&our_in);
}
- /*
- * It would be nice if tmpl_afrom_substr() did this :(
- */
if (quote != T_BARE_WORD) {
if (!fr_sbuff_is_char(&our_in, fr_token_quote[quote])) {
fr_strerror_const("Unterminated string");
- fr_sbuff_advance(&our_in, slen * -1);
+ fr_sbuff_set(&our_in, &opand_m);
goto error;
}
* If "out" is NULL then the expression is added to "head".
* Otherwise, it's returned to the caller.
*/
-static ssize_t tokenize_expression(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_t *in,
- fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules,
- fr_token_t prev, fr_sbuff_parse_rules_t const *bracket_rules,
- fr_sbuff_parse_rules_t const *input_rules, bool cond)
+static fr_slen_t tokenize_expression(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_t *in,
+ fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules,
+ fr_token_t prev, fr_sbuff_parse_rules_t const *bracket_rules,
+ fr_sbuff_parse_rules_t const *input_rules, bool cond)
{
xlat_exp_t *lhs = NULL, *rhs, *node;
xlat_t *func = NULL;
* Get the LHS of the operation.
*/
slen = tokenize_unary(head, &lhs, &our_in, p_rules, t_rules, bracket_rules, &c, cond);
- if (slen < 0) return slen;
+ if (slen < 0) return fr_sbuff_error(&our_in);
if (slen == 0) {
fr_assert(lhs == NULL);
if (!binary_ops[op].str) {
fr_strerror_printf("Invalid operator");
fr_sbuff_set(&our_in, &m_op);
- return -fr_sbuff_used(&our_in);
+ return fr_sbuff_error(&our_in);
}
fr_assert(precedence[op] != 0);
fr_strerror_printf("Operator '%c' is only applied to the left hand side of the '%s' operation, add (..) to evaluate the operation first", c, fr_tokens[op]);
fail_lhs:
fr_sbuff_set(&our_in, &m_lhs);
- return -fr_sbuff_used(&our_in);
+ return fr_sbuff_error(&our_in);
}
fr_sbuff_skip_whitespace(&our_in);
if ((op != T_OP_CMP_EQ) && (op != T_OP_NE)) {
fr_strerror_printf("Invalid operatord '%s' for left hand side structural attribute", fr_tokens[op]);
fr_sbuff_set(&our_in, &m_op);
- return -fr_sbuff_used(&our_in);
+ return fr_sbuff_error(&our_in);
}
fr_assert(0);
} else {
slen = tokenize_expression(head, &rhs, &our_in, p_rules, t_rules, op, bracket_rules, input_rules, cond);
}
- if (slen <= 0) {
+ if (slen < 0) {
talloc_free(lhs);
- FR_SBUFF_ERROR_RETURN_ADJ(&our_in, slen);
+ FR_SBUFF_ERROR_RETURN(&our_in);
}
#ifdef STATIC_ANALYZER
if (reparse_rcode(head, &rhs, true) < 0) {
fail_rhs:
fr_sbuff_set(&our_in, &m_rhs);
- return -fr_sbuff_used(&our_in);
+ return fr_sbuff_error(&our_in);
}
if ((lhs->type == XLAT_FUNC) && (lhs->call.func->token == op)) {
L("~"),
);
-static ssize_t xlat_tokenize_expression_internal(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t *in,
- fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, bool cond)
+static fr_slen_t xlat_tokenize_expression_internal(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t *in,
+ fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, bool cond)
{
ssize_t slen;
fr_sbuff_parse_rules_t *bracket_rules = NULL;
if (slen < 0) {
talloc_free(head);
- return slen;
+ FR_SBUFF_ERROR_RETURN(in);
}
if (!node) {
*/
if (reparse_rcode(head, &node, true) < 0) {
talloc_free(head);
- return 0;
+ return -1;
}
/*
*/
if (xlat_bootstrap(head) < 0) {
talloc_free(head);
- return 0;
+ return -1;
}
*out = head;
return slen;
}
-ssize_t xlat_tokenize_expression(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t *in,
+fr_slen_t xlat_tokenize_expression(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t *in,
fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
{
return xlat_tokenize_expression_internal(ctx, out, in, p_rules, t_rules, false);
}
-ssize_t xlat_tokenize_condition(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t *in,
+fr_slen_t xlat_tokenize_condition(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t *in,
fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
{
return xlat_tokenize_expression_internal(ctx, out, in, p_rules, t_rules, true);
* - 0 and *head != NULL - Zero length expansion
* - <0 the negative offset of the parse failure.
*/
-ssize_t xlat_tokenize_ephemeral_expression(TALLOC_CTX *ctx, xlat_exp_head_t **out,
- fr_event_list_t *el, fr_sbuff_t *in,
- fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
+fr_slen_t xlat_tokenize_ephemeral_expression(TALLOC_CTX *ctx, xlat_exp_head_t **out,
+ fr_event_list_t *el, fr_sbuff_t *in,
+ fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
{
ssize_t slen;
fr_sbuff_parse_rules_t *bracket_rules = NULL;
if (slen < 0) {
talloc_free(head);
- return slen;
+ FR_SBUFF_ERROR_RETURN(in);
}
if (!node) {
*/
if (reparse_rcode(head, &node, true) < 0) {
talloc_free(head);
- return 0;
+ return -1;
}
xlat_exp_insert_tail(head, node);
*/
if (xlat_instantiate_ephemeral(head, el) < 0) {
talloc_free(head);
- return 0;
+ return -1;
}
*out = head;
static inline int xlat_tokenize_attribute(xlat_exp_head_t *head, fr_sbuff_t *in,
fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
{
- ssize_t slen;
tmpl_attr_error_t err;
tmpl_t *vpt = NULL;
xlat_exp_t *node;
fr_sbuff_marker(&m_s, in);
MEM(node = xlat_exp_alloc_null(head));
- slen = tmpl_afrom_attr_substr(node, &err, &vpt, in, p_rules, &our_t_rules);
- if (slen <= 0) {
- fr_sbuff_advance(in, slen * -1);
-
+ if (tmpl_afrom_attr_substr(node, &err, &vpt, in, p_rules, &our_t_rules) < 0) {
/*
* If the parse error occurred before the ':'
* then the error is changed to 'Unknown module',
error:
fr_sbuff_marker_release(&m_s);
talloc_free(node);
- return -1;
+ return fr_sbuff_error(in);
}
/*
* - 0 and *head != NULL - Zero length expansion
* - <0 the negative offset of the parse failure.
*/
-ssize_t xlat_tokenize_ephemeral(TALLOC_CTX *ctx, xlat_exp_head_t **out,
- fr_event_list_t *el, fr_sbuff_t *in,
- fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
+fr_slen_t xlat_tokenize_ephemeral(TALLOC_CTX *ctx, xlat_exp_head_t **out,
+ fr_event_list_t *el, fr_sbuff_t *in,
+ fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
{
fr_sbuff_t our_in = FR_SBUFF(in);
tmpl_rules_t our_t_rules = {};
if (xlat_tokenize_string(head, &our_in,
false, p_rules, &our_t_rules) < 0) {
talloc_free(head);
- return -fr_sbuff_used(&our_in);
+ return fr_sbuff_error(&our_in);
}
/*
* any expansions.
* @param[in] t_rules controlling how attribute references are parsed.
* @return
- * - <=0 on error.
+ * - < 0 on error.
* - >0 on success which is the number of characters parsed.
*/
-ssize_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t *in,
- fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
+fr_slen_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t *in,
+ fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
{
fr_sbuff_t our_in = FR_SBUFF(in);
ssize_t slen;
}
talloc_free(head);
- return -fr_sbuff_used(&our_in); /* error */
+ return fr_sbuff_error(&our_in); /* error */
}
break;
* - 0 and *head != NULL - Zero length expansion
* - < 0 the negative offset of the parse failure.
*/
-ssize_t xlat_tokenize(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t *in,
- fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
+fr_slen_t xlat_tokenize(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t *in,
+ fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
{
fr_sbuff_t our_in = FR_SBUFF(in);
xlat_exp_head_t *head;
if (xlat_tokenize_string(head, &our_in,
false, p_rules, t_rules) < 0) {
talloc_free(head);
- return -fr_sbuff_used(&our_in);
+ return fr_sbuff_error(&our_in);
}
/*
* - >=0 the number of bytes written to out.
* - <0 number of bytes we would have needed to print the next hexit.
*/
-ssize_t fr_base16_encode_nstd(fr_sbuff_t *out, fr_dbuff_t *in, char const alphabet[static UINT8_MAX + 1])
+fr_slen_t fr_base16_encode_nstd(fr_sbuff_t *out, fr_dbuff_t *in, char const alphabet[static UINT8_MAX + 1])
{
fr_sbuff_t our_out = FR_SBUFF(out);
fr_dbuff_t our_in = FR_DBUFF(in);
return alphabet[(uint8_t)c] < 16;
}
-ssize_t fr_base16_encode_nstd(fr_sbuff_t *out, fr_dbuff_t *in, char const alphabet[static UINT8_MAX + 1]);
+fr_slen_t fr_base16_encode_nstd(fr_sbuff_t *out, fr_dbuff_t *in, char const alphabet[static UINT8_MAX + 1]);
#define fr_base16_encode(_out, _in) \
fr_base16_encode_nstd(_out, _in, fr_base16_alphabet_encode_lc)
* - >=0 the number of bytes written to out.
* - <0 number of bytes we would have needed to print the next hexit.
*/
-static inline ssize_t fr_base16_aencode(TALLOC_CTX *ctx, char **out, fr_dbuff_t *in)
+static inline fr_slen_t fr_base16_aencode(TALLOC_CTX *ctx, char **out, fr_dbuff_t *in)
{
fr_sbuff_t sbuff;
fr_sbuff_uctx_talloc_t tctx;
SIZE_MAX);
slen = fr_base16_encode(&sbuff, in);
- if (slen <= 0) {
+ if (slen < 0) {
fr_sbuff_trim_talloc(&sbuff, 0);
*out = sbuff.buff;
- return 0;
+ return slen;
}
*out = sbuff.buff;
return (size_t)slen;
}
-ssize_t fr_base16_decode_nstd(fr_sbuff_parse_error_t *err, fr_dbuff_t *out, fr_sbuff_t *in,
+fr_slen_t fr_base16_decode_nstd(fr_sbuff_parse_error_t *err, fr_dbuff_t *out, fr_sbuff_t *in,
bool no_trailing, uint8_t const alphabet[static UINT8_MAX + 1]);
#define fr_base16_decode(_err, _out, _in, _no_trailing) \
fr_base16_decode_nstd(_err, _out, _in, _no_trailing, fr_base16_alphabet_decode_mc)
unsigned int vendor, unsigned int attr)
CC_HINT(nonnull(2));
-ssize_t fr_dict_unknown_afrom_oid_substr(TALLOC_CTX *ctx,
+fr_slen_t fr_dict_unknown_afrom_oid_substr(TALLOC_CTX *ctx,
fr_dict_attr_err_t *err, fr_dict_attr_t **out,
fr_dict_attr_t const *parent,
fr_sbuff_t *in, fr_sbuff_term_t const *tt)
int fr_dict_oid_component_legacy(unsigned int *out, char const **oid);
-ssize_t fr_dict_attr_flags_print(fr_sbuff_t *out, fr_dict_t const *dict,
+fr_slen_t fr_dict_attr_flags_print(fr_sbuff_t *out, fr_dict_t const *dict,
fr_type_t type, fr_dict_attr_flags_t const *flags);
-ssize_t fr_dict_attr_oid_print(fr_sbuff_t *out,
+fr_slen_t fr_dict_attr_oid_print(fr_sbuff_t *out,
fr_dict_attr_t const *ancestor, fr_dict_attr_t const *da, bool numeric);
#define FR_DICT_ATTR_OID_PRINT_RETURN(...) FR_SBUFF_RETURN(fr_dict_attr_oid_print, ##__VA_ARGS__)
-ssize_t fr_dict_attr_by_oid_legacy(fr_dict_t const *dict, fr_dict_attr_t const **parent,
+fr_slen_t fr_dict_attr_by_oid_legacy(fr_dict_t const *dict, fr_dict_attr_t const **parent,
unsigned int *attr, char const *oid) CC_HINT(nonnull);
-ssize_t fr_dict_oid_component(fr_dict_attr_err_t *err,
+fr_slen_t fr_dict_oid_component(fr_dict_attr_err_t *err,
fr_dict_attr_t const **out, fr_dict_attr_t const *parent,
fr_sbuff_t *in, fr_sbuff_term_t const *tt)
CC_HINT(nonnull(2,3,4));
-ssize_t fr_dict_attr_by_oid_substr(fr_dict_attr_err_t *err,
+fr_slen_t fr_dict_attr_by_oid_substr(fr_dict_attr_err_t *err,
fr_dict_attr_t const **out, fr_dict_attr_t const *parent,
fr_sbuff_t *in, fr_sbuff_term_t const *tt)
CC_HINT(nonnull(2,3,4));
dl_t *fr_dict_dl(fr_dict_t const *dict);
-ssize_t fr_dict_by_protocol_substr(fr_dict_attr_err_t *err,
+fr_slen_t fr_dict_by_protocol_substr(fr_dict_attr_err_t *err,
fr_dict_t const **out, fr_sbuff_t *name, fr_dict_t const *dict_def);
fr_dict_t const *fr_dict_by_protocol_name(char const *name);
fr_dict_attr_t const *fr_dict_vendor_da_by_num(fr_dict_attr_t const *vendor_root, uint32_t vendor_pen);
-ssize_t fr_dict_attr_search_by_qualified_name_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
+fr_slen_t fr_dict_attr_search_by_qualified_name_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
fr_dict_t const *dict_def,
fr_sbuff_t *name, fr_sbuff_term_t const *tt,
bool internal, bool foreign)
CC_HINT(nonnull(2, 4));
-ssize_t fr_dict_attr_search_by_name_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
+fr_slen_t fr_dict_attr_search_by_name_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
fr_dict_t const *dict_def,
fr_sbuff_t *name, fr_sbuff_term_t const *tt,
bool internal, bool foreign)
CC_HINT(nonnull(2, 4));
-ssize_t fr_dict_attr_search_by_qualified_oid_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
+fr_slen_t fr_dict_attr_search_by_qualified_oid_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
fr_dict_t const *dict_def,
fr_sbuff_t *in, fr_sbuff_term_t const *tt,
bool internal, bool foreign)
bool internal, bool foreign)
CC_HINT(nonnull(3));
-ssize_t fr_dict_attr_search_by_oid_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
+fr_slen_t fr_dict_attr_search_by_oid_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
fr_dict_t const *dict_def,
fr_sbuff_t *in, fr_sbuff_term_t const *tt,
bool internal, bool foreign)
CC_HINT(nonnull(2, 4));
-ssize_t fr_dict_attr_by_name_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
+fr_slen_t fr_dict_attr_by_name_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
fr_dict_attr_t const *parent,
fr_sbuff_t *name, fr_sbuff_term_t const *tt)
CC_HINT(nonnull(2,3,4));
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);
+fr_slen_t fr_dict_enum_by_name_substr(fr_dict_enum_value_t **out, fr_dict_attr_t const *da, fr_sbuff_t *in);
fr_slen_t fr_dict_enum_name_from_substr(fr_sbuff_t *out, fr_sbuff_parse_error_t *err,
fr_sbuff_t *in, fr_sbuff_term_t const *tt);
* - The number of bytes parsed on success.
* - <= 0 on failure. Negative offset indicates parse error position.
*/
-ssize_t fr_dict_unknown_afrom_oid_substr(TALLOC_CTX *ctx,
- fr_dict_attr_err_t *err, fr_dict_attr_t **out,
- fr_dict_attr_t const *parent,
- fr_sbuff_t *in, fr_sbuff_term_t const *tt)
+fr_slen_t fr_dict_unknown_afrom_oid_substr(TALLOC_CTX *ctx,
+ fr_dict_attr_err_t *err, fr_dict_attr_t **out,
+ fr_dict_attr_t const *parent,
+ fr_sbuff_t *in, fr_sbuff_term_t const *tt)
{
+ fr_sbuff_t our_in = FR_SBUFF(in);
fr_dict_attr_t const *our_parent;
fr_dict_attr_t *n = NULL;
fr_dict_attr_err_t our_err;
fr_dict_attr_flags_t flags = {
.is_unknown = true
};
- fr_sbuff_marker_t start;
- ssize_t slen;
bool is_raw;
*out = NULL;
- fr_sbuff_marker(&start, in);
-
- is_raw = fr_sbuff_adv_past_str_literal(in, "raw");
+ is_raw = fr_sbuff_adv_past_str_literal(&our_in, "raw");
/*
* Resolve all the known bits first...
*/
- slen = fr_dict_attr_by_oid_substr(&our_err, &our_parent, parent, in, tt);
+ (void)fr_dict_attr_by_oid_substr(&our_err, &our_parent, parent, &our_in, tt);
switch (our_err) {
/*
* Um this is awkward, we were asked to
if (err) *err = FR_DICT_ATTR_OK;
}
- return fr_sbuff_marker_release_behind(&start);
+ return fr_sbuff_set(in, &our_in);
/*
* This is what we want... Everything
*/
default:
if (err) *err = our_err;
- fr_sbuff_marker_release(&start);
- return slen;
+ FR_SBUFF_ERROR_RETURN(&our_in);
}
/*
* fr_dict_attr_by_oid_substr parsed *something*
* we expected the next component to be a '.'.
*/
- if (fr_sbuff_behind(&start) > 0) {
- if (!fr_sbuff_next_if_char(in, '.')) { /* this is likely a logic bug if the test fails ? */
- fr_strerror_printf("Missing OID component separator %s", fr_sbuff_current(in));
+ if (fr_sbuff_ahead(&our_in) > 0) {
+ if (!fr_sbuff_next_if_char(&our_in, '.')) { /* this is likely a logic bug if the test fails ? */
+ fr_strerror_printf("Missing OID component separator %.*s", (int)fr_sbuff_remaining(&our_in), fr_sbuff_current(&our_in));
error:
if (err) *err = FR_DICT_ATTR_PARSE_ERROR;
talloc_free(n);
- return -fr_sbuff_marker_release_reset_behind(&start);
+ FR_SBUFF_ERROR_RETURN(&our_in);
}
- } else if (fr_sbuff_next_if_char(in, '.')) {
+ } else if (fr_sbuff_next_if_char(&our_in, '.')) {
our_parent = fr_dict_root(fr_dict_by_da(parent)); /* From the root */
}
uint32_t num;
fr_sbuff_parse_error_t sberr;
- fr_sbuff_out(&sberr, &num, in);
+ fr_sbuff_out(&sberr, &num, &our_in);
switch (sberr) {
case FR_SBUFF_PARSE_OK:
switch (our_parent->type) {
{
fr_dict_attr_t *ni;
- if (fr_sbuff_next_if_char(in, '.')) {
+ if (fr_sbuff_next_if_char(&our_in, '.')) {
ni = fr_dict_unknown_vendor_afrom_num(n, our_parent, num);
if (!ni) goto error;
our_parent = ni;
{
fr_dict_attr_t *ni;
- if (fr_sbuff_next_if_char(in, '.')) {
+ if (fr_sbuff_next_if_char(&our_in, '.')) {
ni = fr_dict_unknown_tlv_afrom_num(n, our_parent, num);
if (!ni) goto error;
our_parent = ni;
* Leaf type with more components
* is an error.
*/
- if (fr_sbuff_is_char(in, '.')) {
+ if (fr_sbuff_is_char(&our_in, '.')) {
fr_strerror_printf("Interior OID component cannot proceed a %s type",
fr_type_to_str(our_parent->type));
goto error;
{
fr_sbuff_marker_t c_start;
- fr_sbuff_marker(&c_start, in);
- fr_sbuff_adv_past_allowed(in, FR_DICT_ATTR_MAX_NAME_LEN, fr_dict_attr_allowed_chars, NULL);
+ fr_sbuff_marker(&c_start, &our_in);
+ fr_sbuff_adv_past_allowed(&our_in, FR_DICT_ATTR_MAX_NAME_LEN, fr_dict_attr_allowed_chars, NULL);
fr_strerror_printf("Unknown attribute \"%.*s\" for parent \"%s\"",
(int)fr_sbuff_behind(&c_start), fr_sbuff_current(&c_start), our_parent->name);
goto error;
*out = n;
- return fr_sbuff_marker_release_behind(&start);
+ return fr_sbuff_set(in, &our_in);
}
/** Fixup the parent of an unknown attribute using an equivalent known attribute
*/
RCSID("$Id$")
+#define _DICT_PRIVATE 1
+
+#include <freeradius-devel/util/atexit.h>
#include <freeradius-devel/util/conf.h>
+#include <freeradius-devel/util/dict.h>
#include <freeradius-devel/util/dict_fixup_priv.h>
#include <freeradius-devel/util/proto.h>
#include <freeradius-devel/util/rand.h>
+#include <freeradius-devel/util/sbuff.h>
#include <freeradius-devel/util/syserror.h>
-#include <freeradius-devel/util/atexit.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
* @param[in] tt Terminal strings.
* @return
* - >0 the number of bytes consumed.
- * - <= 0 Parse error occurred here.
+ * - <0 Parse error occurred here.
*/
-ssize_t fr_dict_oid_component(fr_dict_attr_err_t *err,
- fr_dict_attr_t const **out, fr_dict_attr_t const *parent,
- fr_sbuff_t *in, fr_sbuff_term_t const *tt)
+fr_slen_t fr_dict_oid_component(fr_dict_attr_err_t *err,
+ fr_dict_attr_t const **out, fr_dict_attr_t const *parent,
+ fr_sbuff_t *in, fr_sbuff_term_t const *tt)
{
- fr_sbuff_marker_t start;
+ fr_sbuff_t our_in = FR_SBUFF(in);
uint32_t num = 0;
fr_sbuff_parse_error_t sberr;
fr_dict_attr_t const *child;
*out = NULL;
- fr_sbuff_marker(&start, in);
-
switch (parent->type) {
case FR_TYPE_STRUCTURAL:
break;
"Error at OID \"%.*s\"",
parent->name,
fr_type_to_str(parent->type),
- (int)fr_sbuff_remaining(in),
- fr_sbuff_current(in));
+ (int)fr_sbuff_remaining(&our_in),
+ fr_sbuff_current(&our_in));
if (err) *err =FR_DICT_ATTR_NO_CHILDREN;
- return -fr_sbuff_marker_release_behind(&start);
+ FR_SBUFF_ERROR_RETURN(&our_in);
}
- fr_sbuff_out(&sberr, &num, in);
+ fr_sbuff_out(&sberr, &num, &our_in);
switch (sberr) {
/*
* Lookup by number
*/
case FR_SBUFF_PARSE_OK:
- if (!fr_sbuff_is_char(in, '.') && !fr_sbuff_is_terminal(in, tt)) {
- fr_sbuff_set(in, &start); /* Reset to the start */
+ if (!fr_sbuff_is_char(&our_in, '.') && !fr_sbuff_is_terminal(&our_in, tt)) {
+ fr_sbuff_set_to_start(&our_in);
goto oid_str;
}
fr_strerror_printf("Failed resolving child %u in context %s",
num, parent->name);
if (err) *err = FR_DICT_ATTR_NOTFOUND;
- fr_sbuff_set(in, &start); /* Reset to start of number */
- fr_sbuff_marker_release(&start);
-
- return 0;
+ FR_SBUFF_ERROR_RETURN(&our_in);
}
break;
case FR_SBUFF_PARSE_ERROR_TRAILING:
{
fr_dict_attr_err_t our_err;
- ssize_t slen;
-
oid_str:
- slen = fr_dict_attr_by_name_substr(&our_err, &child, parent, in, tt);
- if (our_err != FR_DICT_ATTR_OK) {
+ if (fr_dict_attr_by_name_substr(&our_err, &child, parent, &our_in, tt) < 0) {
fr_strerror_printf("Failed resolving \"%.*s\" in context %s",
- (int)fr_sbuff_remaining(in),
- fr_sbuff_current(in),
+ (int)fr_sbuff_remaining(&our_in),
+ fr_sbuff_current(&our_in),
parent->name);
if (err) *err = our_err;
- return slen - fr_sbuff_marker_release_behind(&start);
+ FR_SBUFF_ERROR_RETURN(&our_in);
}
}
break;
default:
fr_strerror_printf("Invalid OID component (%s) \"%.*s\"",
fr_table_str_by_value(sbuff_parse_error_table, sberr, "<INVALID>"),
- (int)fr_sbuff_remaining(in), fr_sbuff_current(in));
+ (int)fr_sbuff_remaining(&our_in), fr_sbuff_current(&our_in));
if (err) *err = FR_DICT_ATTR_PARSE_ERROR;
- return -fr_sbuff_marker_release_behind(&start);
+ FR_SBUFF_ERROR_RETURN(&our_in);
}
child = dict_attr_alias(err, child);
- if (unlikely(!child)) return 0;
+ if (unlikely(!child)) FR_SBUFF_ERROR_RETURN(&our_in);
*out = child;
- return fr_sbuff_marker_release_behind(&start);
+ return fr_sbuff_set(in, &our_in);
}
/** Resolve an attribute using an OID string
*
* @note Will leave the sbuff pointing at the component the error occurred at
* so that the caller can attempt to process the component in another way.
+ * An err pointer should be provided in order to determine if an error
+ * ocurred.
*
* @param[out] err The parsing error that occurred.
* @param[out] out The deepest attribute we resolved.
* @param[in] parent Where to resolve relative attributes from.
* @param[in] in string to parse.
* @param[in] tt Terminal strings.
- * @return
- * - >0 the number of bytes consumed.
- * - <= 0 Parse error occurred here.
+ * @return The number of bytes of name consumed.
*/
-ssize_t fr_dict_attr_by_oid_substr(fr_dict_attr_err_t *err,
- fr_dict_attr_t const **out, fr_dict_attr_t const *parent,
- fr_sbuff_t *in, fr_sbuff_term_t const *tt)
+fr_slen_t fr_dict_attr_by_oid_substr(fr_dict_attr_err_t *err,
+ fr_dict_attr_t const **out, fr_dict_attr_t const *parent,
+ fr_sbuff_t *in, fr_sbuff_term_t const *tt)
{
- fr_sbuff_marker_t start, c_s;
+ fr_sbuff_t our_in = FR_SBUFF(in);
+ fr_sbuff_marker_t m_c;
fr_dict_attr_t const *our_parent = parent;
- fr_sbuff_marker(&start, in);
- fr_sbuff_marker(&c_s, in);
+ fr_sbuff_marker(&m_c, &our_in);
/*
* If the OID doesn't begin with '.' we
* resolve it from the root.
*/
-
#if 0
- if (!fr_sbuff_next_if_char(in, '.')) our_parent = fr_dict_root(fr_dict_by_da(parent));
+ if (!fr_sbuff_next_if_char(&our_in, '.')) our_parent = fr_dict_root(fr_dict_by_da(parent));
#else
- (void) fr_sbuff_next_if_char(in, '.');
+ (void) fr_sbuff_next_if_char(&our_in, '.');
#endif
*out = NULL;
for (;;) {
- ssize_t slen;
fr_dict_attr_t const *child;
- slen = fr_dict_oid_component(err, &child, our_parent, in, tt);
- if ((slen <= 0) || !child) {
- ssize_t ret = slen - fr_sbuff_behind(&start);
-
- fr_sbuff_set(in, &c_s);
- fr_sbuff_marker_release(&start);
-
- return ret;
+ if ((fr_dict_oid_component(err, &child, our_parent, &our_in, tt) < 0) || !child) {
+ fr_sbuff_set(&our_in, &m_c); /* Reset to the start of the last component */
+ break; /* Resolved as much as we can */
}
our_parent = child;
*out = child;
- fr_sbuff_set(&c_s, in);
- if (!fr_sbuff_next_if_char(in, '.')) break;
+ fr_sbuff_set(&m_c, &our_in);
+ if (!fr_sbuff_next_if_char(&our_in, '.')) break;
}
- return fr_sbuff_marker_release_behind(&start);
+ return fr_sbuff_set(in, &our_in);
}
/** Resolve an attribute using an OID string
fr_sbuff_t sbuff = FR_SBUFF_IN(oid, strlen(oid));
fr_dict_attr_t const *da;
- if (fr_dict_attr_by_oid_substr(err, &da, parent, &sbuff, NULL) <= 0) return NULL;
+ fr_dict_attr_by_oid_substr(err, &da, parent, &sbuff, NULL);
+ if (err != FR_DICT_ATTR_OK) return NULL;
return da;
}
return dict->dl;
}
-ssize_t dict_by_protocol_substr(fr_dict_attr_err_t *err,
- fr_dict_t **out, fr_sbuff_t *name, fr_dict_t const *dict_def)
+fr_slen_t dict_by_protocol_substr(fr_dict_attr_err_t *err,
+ fr_dict_t **out, fr_sbuff_t *name, fr_dict_t const *dict_def)
{
fr_dict_attr_t root;
+ fr_sbuff_t our_name = FR_SBUFF(name);
fr_dict_t *dict;
- size_t len;
+ fr_slen_t slen;
char buffer[FR_DICT_ATTR_MAX_NAME_LEN + 1 + 1]; /* +1 \0 +1 for "too long" */
- fr_sbuff_t our_name;
if (!dict_gctx || !name || !out) {
if (err) *err = FR_DICT_ATTR_EINVAL;
- return 0;
+ FR_SBUFF_ERROR_RETURN(&our_name);
}
- our_name = FR_SBUFF(name);
-
memset(&root, 0, sizeof(root));
/*
* Advance p until we get something that's not part of
* the dictionary attribute name.
*/
- len = fr_sbuff_out_bstrncpy_allowed(&FR_SBUFF_OUT(buffer, sizeof(buffer)),
- &our_name, SIZE_MAX,
- fr_dict_attr_allowed_chars);
- if (len == 0) {
+ slen = fr_sbuff_out_bstrncpy_allowed(&FR_SBUFF_OUT(buffer, sizeof(buffer)),
+ &our_name, SIZE_MAX,
+ fr_dict_attr_allowed_chars);
+ if (slen == 0) {
fr_strerror_const("Zero length attribute name");
if (err) *err = FR_DICT_ATTR_PARSE_ERROR;
- return 0;
+ FR_SBUFF_ERROR_RETURN(&our_name);
}
- if (len > FR_DICT_ATTR_MAX_NAME_LEN) {
+ if (slen > FR_DICT_ATTR_MAX_NAME_LEN) {
fr_strerror_const("Attribute name too long");
if (err) *err = FR_DICT_ATTR_PARSE_ERROR;
- return -(FR_DICT_ATTR_MAX_NAME_LEN);
+ FR_SBUFF_ERROR_RETURN(&our_name);
}
/*
if (strcasecmp(root.name, "internal") != 0) {
fr_strerror_printf("Unknown protocol '%s'", root.name);
memcpy(out, &dict_def, sizeof(*out));
- return 0;
+ fr_sbuff_set_to_start(&our_name);
+ FR_SBUFF_ERROR_RETURN(&our_name);
}
dict = dict_gctx->internal;
*out = dict;
- return (size_t)fr_sbuff_set(name, &our_name);
+ return fr_sbuff_set(name, &our_name);
}
/** Look up a protocol name embedded in another string
* @param[in] dict_def The dictionary to return if no dictionary qualifier was found.
* @return
* - 0 and *out != NULL. Couldn't find a dictionary qualifier, so returned dict_def.
- * - <= 0 on error and (*out == NULL) (offset as negative integer)
+ * - < 0 on error and (*out == NULL) (offset as negative integer)
* - > 0 on success (number of bytes parsed).
*/
-ssize_t fr_dict_by_protocol_substr(fr_dict_attr_err_t *err, fr_dict_t const **out, fr_sbuff_t *name, fr_dict_t const *dict_def)
+fr_slen_t fr_dict_by_protocol_substr(fr_dict_attr_err_t *err, fr_dict_t const **out, fr_sbuff_t *name, fr_dict_t const *dict_def)
{
- ssize_t slen;
- fr_dict_t *dict = NULL;
-
- slen = dict_by_protocol_substr(err, &dict, name, dict_def);
- *out = dict;
-
- return slen;
+ return dict_by_protocol_substr(err, UNCONST(fr_dict_t **, out), name, dict_def);
}
/** Internal version of #fr_dict_by_protocol_name
* @param[in] tt Terminal sequences to use to determine the portion
* of in to search.
* @return
- * - <= 0 on failure.
+ * - < 0 on failure.
* - The number of bytes of name consumed on success.
*/
-typedef ssize_t (*dict_attr_resolve_func_t)(fr_dict_attr_err_t *err,
- fr_dict_attr_t const **out, fr_dict_attr_t const *parent,
- fr_sbuff_t *in, fr_sbuff_term_t const *tt);
+typedef fr_slen_t (*dict_attr_resolve_func_t)(fr_dict_attr_err_t *err,
+ fr_dict_attr_t const **out, fr_dict_attr_t const *parent,
+ fr_sbuff_t *in, fr_sbuff_term_t const *tt);
/** Internal function for searching for attributes in multiple dictionaries
*
* - >0 on success.
*/
static inline CC_HINT(always_inline)
-ssize_t dict_attr_search(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
- fr_dict_t const *dict_def,
- fr_sbuff_t *in, fr_sbuff_term_t const *tt,
- bool internal, bool foreign,
- dict_attr_resolve_func_t func)
+fr_slen_t dict_attr_search(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
+ fr_dict_t const *dict_def,
+ fr_sbuff_t *in, fr_sbuff_term_t const *tt,
+ bool internal, bool foreign,
+ dict_attr_resolve_func_t func)
{
fr_dict_attr_err_t our_err = FR_DICT_ATTR_OK;
fr_hash_iter_t iter;
fr_dict_t *dict = NULL;
-
- ssize_t slen = 0;
fr_sbuff_t our_in = FR_SBUFF(in);
if (internal && !dict_gctx->internal) internal = false;
* dict_def search in the specified dictionary
*/
if (dict_def) {
- slen = func(&our_err, out, fr_dict_root(dict_def), &our_in, tt);
+ (void)func(&our_err, out, fr_dict_root(dict_def), &our_in, tt);
switch (our_err) {
case FR_DICT_ATTR_OK:
return fr_sbuff_set(in, &our_in);
* Next in the internal dictionary
*/
if (internal) {
- slen = func(&our_err, out, fr_dict_root(dict_gctx->internal), &our_in, tt);
+ (void)func(&our_err, out, fr_dict_root(dict_gctx->internal), &our_in, tt);
switch (our_err) {
case FR_DICT_ATTR_OK:
return fr_sbuff_set(in, &our_in);
if (err) *err = our_err;
*out = NULL;
- FR_SBUFF_ERROR_RETURN_ADJ(&our_in, slen);
+ FR_SBUFF_ERROR_RETURN(&our_in);
}
/** Internal function for searching for attributes in multiple dictionaries
* the attribute identifier.
*/
static inline CC_HINT(always_inline)
-ssize_t dict_attr_search_qualified(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
- fr_dict_t const *dict_def,
- fr_sbuff_t *in, fr_sbuff_term_t const *tt,
- bool internal, bool foreign,
- dict_attr_resolve_func_t func)
+fr_slen_t dict_attr_search_qualified(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
+ fr_dict_t const *dict_def,
+ fr_sbuff_t *in, fr_sbuff_term_t const *tt,
+ bool internal, bool foreign,
+ dict_attr_resolve_func_t func)
{
fr_sbuff_t our_in = FR_SBUFF(in);
fr_dict_attr_err_t our_err;
fr_dict_t *initial;
- ssize_t slen;
+ fr_slen_t slen;
/*
* Check for dictionary prefix
error:
if (err) *err = our_err;
*out = NULL;
-
- FR_SBUFF_ERROR_RETURN_ADJ(&our_in, slen);
+ FR_SBUFF_ERROR_RETURN(&our_in);
}
/*
*/
if (!fr_sbuff_next_if_char(&our_in, '.')) {
if (err) *err = FR_DICT_ATTR_PARSE_ERROR;
- return 0;
+ FR_SBUFF_ERROR_RETURN(&our_in);
}
internal = foreign = false;
}
- slen = dict_attr_search(&our_err, out, initial, &our_in, tt, internal, foreign, func);
- if (our_err != FR_DICT_ATTR_OK) goto error;
-
+ if (dict_attr_search(&our_err, out, initial, &our_in, tt, internal, foreign, func) < 0) goto error;
if (err) *err = FR_DICT_ATTR_OK;
return fr_sbuff_set(in, &our_in);
* @param[in] internal If true, fallback to the internal dictionary.
* @param[in] foreign If true, fallback to foreign dictionaries.
* @return
- * - <= 0 on failure.
+ * - < 0 on failure.
* - The number of bytes of name consumed on success.
*/
-ssize_t fr_dict_attr_search_by_qualified_name_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
- fr_dict_t const *dict_def,
- fr_sbuff_t *name, fr_sbuff_term_t const *tt,
- bool internal, bool foreign)
+fr_slen_t fr_dict_attr_search_by_qualified_name_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
+ fr_dict_t const *dict_def,
+ fr_sbuff_t *name, fr_sbuff_term_t const *tt,
+ bool internal, bool foreign)
{
return dict_attr_search_qualified(err, out, dict_def, name, tt,
internal, foreign, fr_dict_attr_by_name_substr);
* @param[in] internal If true, fallback to the internal dictionary.
* @param[in] foreign If true, fallback to foreign dictionaries.
* @return
- * - <= 0 on failure.
+ * - < 0 on failure.
* - The number of bytes of name consumed on success.
*/
-ssize_t fr_dict_attr_search_by_name_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
- fr_dict_t const *dict_def,
- fr_sbuff_t *name, fr_sbuff_term_t const *tt,
- bool internal, bool foreign)
+fr_slen_t fr_dict_attr_search_by_name_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
+ fr_dict_t const *dict_def,
+ fr_sbuff_t *name, fr_sbuff_term_t const *tt,
+ bool internal, bool foreign)
{
return dict_attr_search_qualified(err, out, dict_def, name, tt,
internal, foreign, fr_dict_attr_by_name_substr);
* @note If calling this function from the server any list or request qualifiers
* should be stripped first.
*
+ * @note err should be checked to determine if a parse error ocurred.
+ *
* @param[out] err Why parsing failed. May be NULL.
* @see fr_dict_attr_err_t
* @param[out] out Dictionary found attribute.
* @param[in] tt Terminal strings.
* @param[in] internal If true, fallback to the internal dictionary.
* @param[in] foreign If true, fallback to foreign dictionaries.
- * @return
- * - <= 0 on failure.
- * - The number of bytes of name consumed on success.
+ * @return The number of bytes of name consumed.
*/
-ssize_t fr_dict_attr_search_by_qualified_oid_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
- fr_dict_t const *dict_def,
- fr_sbuff_t *in, fr_sbuff_term_t const *tt,
- bool internal, bool foreign)
+fr_slen_t fr_dict_attr_search_by_qualified_oid_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
+ fr_dict_t const *dict_def,
+ fr_sbuff_t *in, fr_sbuff_term_t const *tt,
+ bool internal, bool foreign)
{
return dict_attr_search_qualified(err, out, dict_def, in, tt,
internal, foreign, fr_dict_attr_by_oid_substr);
* @note If calling this function from the server any list or request qualifiers
* should be stripped first.
*
+ * @note err should be checked to determine if a parse error ocurred.
+ *
* @param[out] err Why parsing failed. May be NULL.
* @see fr_dict_attr_err_t
* @param[out] out Dictionary found attribute.
* @param[in] tt Terminal strings.
* @param[in] internal If true, fallback to the internal dictionary.
* @param[in] foreign If true, fallback to foreign dictionaries.
- * @return
- * - <= 0 on failure.
- * - The number of bytes of name consumed on success.
+ * @return The number of bytes of name consumed.
*/
-ssize_t fr_dict_attr_search_by_oid_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
- fr_dict_t const *dict_def,
- fr_sbuff_t *in, fr_sbuff_term_t const *tt,
- bool internal, bool foreign)
+fr_slen_t fr_dict_attr_search_by_oid_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
+ fr_dict_t const *dict_def,
+ fr_sbuff_t *in, fr_sbuff_term_t const *tt,
+ bool internal, bool foreign)
{
return dict_attr_search_qualified(err, out, dict_def, in, tt,
internal, foreign, fr_dict_attr_by_oid_substr);
ssize_t slen;
fr_sbuff_t our_name;
fr_dict_attr_t const *da;
+ fr_dict_attr_err_t our_err;
fr_sbuff_init_in(&our_name, name, strlen(name));
- slen = fr_dict_attr_search_by_qualified_oid_substr(err, &da, dict_def, &our_name, NULL, internal, foreign);
- if (slen <= 0) return NULL;
-
+ slen = fr_dict_attr_search_by_qualified_oid_substr(&our_err, &da, dict_def, &our_name, NULL, internal, foreign);
+ if (our_err != FR_DICT_ATTR_OK) {
+ if (err) *err = our_err;
+ return NULL;
+ }
if ((size_t)slen != fr_sbuff_len(&our_name)) {
fr_strerror_printf("Trailing garbage after attr string \"%s\"", name);
if (err) *err = FR_DICT_ATTR_PARSE_ERROR;
* - <= 0 on failure.
* - The number of bytes of name consumed on success.
*/
-ssize_t fr_dict_attr_by_name_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
- fr_dict_attr_t const *parent, fr_sbuff_t *name, UNUSED fr_sbuff_term_t const *tt)
+fr_slen_t fr_dict_attr_by_name_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
+ fr_dict_attr_t const *parent, fr_sbuff_t *name, UNUSED fr_sbuff_term_t const *tt)
{
fr_dict_attr_t const *da;
size_t len;
if (len == 0) {
fr_strerror_const("Zero length attribute name");
if (err) *err = FR_DICT_ATTR_PARSE_ERROR;
- return 0;
+ FR_SBUFF_ERROR_RETURN(&our_name);
}
if (len > FR_DICT_ATTR_MAX_NAME_LEN) {
fr_strerror_const("Attribute name too long");
if (err) *err = FR_DICT_ATTR_PARSE_ERROR;
- return -(FR_DICT_ATTR_MAX_NAME_LEN);
+ FR_SBUFF_ERROR_RETURN(&our_name);
}
ref = fr_dict_attr_ref(parent);
if (!namespace) {
fr_strerror_printf("Attribute '%s' does not contain a namespace", parent->name);
if (err) *err = FR_DICT_ATTR_NO_CHILDREN;
- return -1;
+ fr_sbuff_set_to_start(&our_name);
+ FR_SBUFF_ERROR_RETURN(&our_name);
}
da = fr_hash_table_find(namespace, &(fr_dict_attr_t){ .name = buffer });
if (!da) {
if (err) *err = FR_DICT_ATTR_NOTFOUND;
fr_strerror_printf("Attribute '%s' not found in namespace '%s'", buffer, parent->name);
- return 0;
+ fr_sbuff_set_to_start(&our_name);
+ FR_SBUFF_ERROR_RETURN(&our_name);
}
da = dict_attr_alias(err, da);
- if (unlikely(!da)) return 0;
+ if (unlikely(!da)) FR_SBUFF_ERROR_RETURN(&our_name);
*out = da;
if (err) *err = FR_DICT_ATTR_OK;
/*
* 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_slen_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);
if (fr_sbuff_used(&our_in) == 0) {
fr_strerror_const("VALUE name is empty");
if (err) *err = FR_SBUFF_PARSE_ERROR_NOT_FOUND;
- return -1;
+ return fr_sbuff_error(&our_in);
}
fr_strerror_const("VALUE name must contain at least one alpha character");
if (err) *err = FR_SBUFF_PARSE_ERROR_FORMAT;
- return -1;
+ fr_sbuff_set_to_start(&our_in); /* Marker should be at the start of the enum */
+ return fr_sbuff_error(&our_in);
}
/*
*
* @copyright 2000,2006,2015 The FreeRADIUS server project
*/
+#include "lib/util/dict.h"
RCSID("$Id$")
#include <freeradius-devel/util/pair.h>
if (strncmp(p, "raw.", 4) == 0) goto do_unknown;
if (*p == '.') {
+ fr_dict_attr_err_t err;
p++;
if (!*relative_vp) {
goto error;
}
- slen = fr_dict_attr_by_oid_substr(NULL, &da, (*relative_vp)->da,
- &FR_SBUFF_IN(p, (end - p)), &bareword_terminals);
- if (slen <= 0) goto error;
+ slen = fr_dict_attr_by_oid_substr(&err, &da, (*relative_vp)->da, &FR_SBUFF_IN(p, (end - p)), &bareword_terminals);
+ if (err != FR_DICT_ATTR_OK) goto error;
my_list = &(*relative_vp)->vp_group;
my_ctx = *relative_vp;
} else {
+ fr_dict_attr_err_t err;
+
/*
* Parse the name.
*/
- slen = fr_dict_attr_by_oid_substr(NULL, &da, parent,
- &FR_SBUFF_IN(p, (end - p)), &bareword_terminals);
- if ((slen <= 0) && internal) {
- slen = fr_dict_attr_by_oid_substr(NULL, &da, internal,
- &FR_SBUFF_IN(p, (end - p)), &bareword_terminals);
+ slen = fr_dict_attr_by_oid_substr(&err, &da, parent, &FR_SBUFF_IN(p, (end - p)), &bareword_terminals);
+ if ((err != FR_DICT_ATTR_OK) && internal) {
+ slen = fr_dict_attr_by_oid_substr(&err, &da, internal,
+ &FR_SBUFF_IN(p, (end - p)), &bareword_terminals);
}
- if (slen <= 0) {
+ if (err != FR_DICT_ATTR_OK) {
do_unknown:
slen = fr_dict_unknown_afrom_oid_substr(ctx, NULL, &da_unknown, parent,
&FR_SBUFF_IN(p, (end - p)), &bareword_terminals);
- if (slen <= 0) {
+ if (slen < 0) {
p += -slen;
error:
*/
static inline fr_slen_t _fr_sbuff_error(fr_sbuff_t *sbuff, char const *err)
{
- fr_sbuff_t *parent = sbuff->parent;
+ fr_sbuff_t *parent = sbuff->parent;
+ fr_slen_t slen;
if (sbuff->err) err = sbuff->err;
if (parent) parent->err = err;
- return -((err - fr_sbuff_start(sbuff)) + 1);
+ slen = -((err - fr_sbuff_start(sbuff)) + 1);
+
+#ifdef __clang_analyzer__
+ /*
+ * Convince clang that the return value
+ * is always negative. It never can be
+ * else the sbuff code is very broken.
+ */
+ if (slen >= 0) return -1;
+#endif
+
+ return slen;
}
/** Return the current position as an error marker
*/
#define FR_SBUFF_ERROR_RETURN(_sbuff_or_marker) return fr_sbuff_error(_sbuff_or_marker)
-/** Return the current adjusted position in the sbuff as a negative offset
- *
- */
-#define FR_SBUFF_ERROR_RETURN_ADJ(_sbuff, _slen) return -((fr_sbuff_used(_sbuff) + ((_slen) * -1)))
-
/** Check if _len bytes are available in the sbuff, and if not return the number of bytes we'd need
*
*/
match ERROR offset 2: No operand found. Expected &ref, literal, 'quoted literal', "%{expansion}", or enum value
condition ((ok || handled) foo)
-match ERROR offset 17: Unexpected text after condition
+match ERROR offset 18: Unexpected text after condition
# escapes in names are illegal
condition (ok\ foo || handled)
match ERROR offset 18: enum values must contain at least one alpha character
condition (ok FOO handled)
-match ERROR offset 4: Invalid operator
+match ERROR offset 5: Invalid operator
condition (ok !x handled)
-match ERROR offset 4: Invalid operator
+match ERROR offset 5: Invalid operator
condition (ok =x handled)
-match ERROR offset 4: Invalid operator
+match ERROR offset 5: Invalid operator
#
# Re-enable when we have proper bareword xlat tokenization
match !ok
condition !!ok
-match ERROR offset 1: Double negation is invalid
+match ERROR offset 2: Double negation is invalid
condition !(!ok)
match ok
match !(&User-Name == &User-Password) || (&Filter-Id == &Reply-Message)
condition ((a == b) || (c == d)))
-match ERROR offset 22: Unexpected closing brace
+match ERROR offset 23: Unexpected closing brace
condition (handled && (&Packet-Type == Access-Challenge))
match handled && (&Packet-Type == Access-Challenge)
match handled && &Packet-Type == Access-Challenge
condition &reply == &request
-match ERROR offset 0: Cannot use list references in condition
+match ERROR offset 1: Cannot use list references in condition
condition &reply == "hello"
-match ERROR offset 0: Cannot use list references in condition
+match ERROR offset 1: Cannot use list references in condition
condition "hello" == &reply
-match ERROR offset 11: Cannot use list references in condition
+match ERROR offset 12: Cannot use list references in condition
#
match &User-Name == &User-Password
condition <ipv6addr>::1
-match ERROR offset 0: Invalid cast from ipv6addr to bool. Unsupported
+match ERROR offset 1: Invalid cast from ipv6addr to bool. Unsupported
condition <ipaddr>&Filter-Id == &Framed-IP-Address
match <ipaddr>&Filter-Id == &Framed-IP-Address
# =* and !* are only for attrs / lists
condition "foo" !* bar
-match ERROR offset 6: Invalid operator !*
+match ERROR offset 7: Invalid operator !*
condition "foo" =* bar
-match ERROR offset 6: Invalid operator =*
+match ERROR offset 7: Invalid operator =*
# existence checks don't need the RHS
condition &User-Name =* bar
-match ERROR offset 11: Invalid operator =*
+match ERROR offset 12: Invalid operator =*
condition &User-Name !* bar
-match ERROR offset 11: Invalid operator !*
+match ERROR offset 12: Invalid operator !*
condition !&User-Name =* bar
-match ERROR offset 12: Invalid operator =*
+match ERROR offset 13: Invalid operator =*
condition !&User-Name !* bar
-match ERROR offset 12: Invalid operator !*
+match ERROR offset 13: Invalid operator !*
# redundant casts get squashed
condition <ipaddr>&Framed-IP-Address == 127.0.0.1
match ERROR offset 10: Failed parsing string as type 'uint32'
condition &NAS-Port == X
-match ERROR offset 13: Failed parsing string as type 'uint32'
+match ERROR offset 14: Failed parsing string as type 'uint32'
#
# The RHS is a static string, so this gets mashed to a literal,
match true
condition (/foo/)
-match ERROR offset 1: Unexpected regular expression
+match ERROR offset 2: Unexpected regular expression
#
# Tests for (FOO).
match true
condition (a)
-match ERROR offset 1: Expected a module return code
+match ERROR offset 2: Expected a module return code
#
# Module return codes are OK
match !&User-Name =~ /^foo\nbar$/
condition (ok =~ handled)
-match ERROR offset 7: Expected regular expression
+match ERROR offset 8: Expected regular expression
condition (ok == /foo/)
-match ERROR offset 7: Unexpected regular expression
+match ERROR offset 8: Unexpected regular expression
#
# bare words are cast to strings
# Cannot add a bad cast
#
condition <integer>&Tmp-String-0 =~ /foo/
-match ERROR offset 9: Casts cannot be used with regular expressions
+match ERROR offset 10: Casts cannot be used with regular expressions
condition &Tmp-String-0 =~ <integer>/foo/
match ERROR offset 28: Casts cannot be used with regular expressions
match %{1}
xlat %{33}
-match ERROR offset 2: Invalid regex reference. Must be in range 0-32
+match ERROR offset 3: Invalid regex reference. Must be in range 0-32
condition &User-Name == /foo/
-match ERROR offset 14: Unexpected regular expression
+match ERROR offset 15: Unexpected regular expression
count
match 43
match %{32}
xlat %{33}
-match ERROR offset 2: Invalid regex reference. Must be in range 0-32
+match ERROR offset 3: Invalid regex reference. Must be in range 0-32
xlat %{3a}
-match ERROR offset 2: Unexpected text after attribute reference
+match ERROR offset 3: Unexpected text after attribute reference
xlat %{-3}
-match ERROR offset 2: Unresolved attributes not allowed in expansions here
+match ERROR offset 3: Unresolved attributes not allowed in expansions here
xlat %{3
-match ERROR offset 3: Missing closing brace
+match ERROR offset 4: Missing closing brace
#
# Tests for xlat expansion
match %(length:)
xlat %(length:
-match ERROR offset 9: Missing closing brace
+match ERROR offset 10: Missing closing brace
xlat %(length:1 + 2
-match ERROR offset 14: Missing closing brace
+match ERROR offset 15: Missing closing brace
xlat \"%t\tfoo\"
match \"%t\tfoo\"
# Alternations
#
xlat %{%{foo}:-%{bar}}
-match ERROR offset 4: Unresolved attributes not allowed in expansions here
+match ERROR offset 5: Unresolved attributes not allowed in expansions here
xlat %{%{User-Name}:-%{bar}}
-match ERROR offset 18: Unresolved attributes not allowed in expansions here
+match ERROR offset 19: Unresolved attributes not allowed in expansions here
xlat %{%{User-Name}:-bar}
match %{%{User-Name}:-bar}
match %{%{%{User-Name}:-foo}:-%{%{test:bar}:-%{User-Name}}}
xlat %{:-}
-match ERROR offset 2: First item in alternation cannot be empty
+match ERROR offset 3: First item in alternation cannot be empty
xlat %{:-%{User-Name}}
-match ERROR offset 2: First item in alternation cannot be empty
+match ERROR offset 3: First item in alternation cannot be empty
xlat %{%{}:-}
-match ERROR offset 4: Empty expression is invalid
+match ERROR offset 5: Empty expression is invalid
xlat %{%{}:-foo}
-match ERROR offset 4: Empty expression is invalid
+match ERROR offset 5: Empty expression is invalid
xlat %{%{User-Name}:-
-match ERROR offset 16: Missing closing brace
+match ERROR offset 17: Missing closing brace
# Discuss - Not sure the offset/message is correct here, but not sure if we can determine the correct offset either
xlat %{%{User-Name}:-foo
-match ERROR offset 19: Missing closing brace
+match ERROR offset 20: Missing closing brace
xlat %{%{User-Name}:}
-match ERROR offset 14: Expected ':-' after first expansion
+match ERROR offset 15: Expected ':-' after first expansion
xlat %{%{User-Name}}
-match ERROR offset 14: Expected ':-' after first expansion
+match ERROR offset 15: Expected ':-' after first expansion
#
# Empty and malformed expansions
#
xlat %{
-match ERROR offset 2: Missing closing brace
+match ERROR offset 3: Missing closing brace
xlat %{}
-match ERROR offset 2: Empty expression is invalid
+match ERROR offset 3: Empty expression is invalid
xlat %{:}
-match ERROR offset 2: Missing expansion function
+match ERROR offset 3: Missing expansion function
xlat %{:bar}
-match ERROR offset 2: Missing expansion function
+match ERROR offset 3: Missing expansion function
xlat %{foo: bar}
-match ERROR offset 2: Unresolved expansion functions are not allowed here
+match ERROR offset 3: Unresolved expansion functions are not allowed here
xlat %{[}
-match ERROR offset 2: Missing attribute name
+match ERROR offset 3: Missing attribute name
xlat %{[baz}
-match ERROR offset 2: Missing attribute name
+match ERROR offset 3: Missing attribute name
xlat %{ }
-match ERROR offset 2: Invalid char ' ' in expression
+match ERROR offset 3: Invalid char ' ' in expression
xlat %{\t}
match ERROR offset 3: Invalid attribute name
match ERROR offset 3: Invalid attribute name
xlat %{foo }
-match ERROR offset 5: Invalid char ' ' in expression
+match ERROR offset 6: Invalid char ' ' in expression
xlat %{foo bar}
-match ERROR offset 5: Invalid char ' ' in expression
+match ERROR offset 6: Invalid char ' ' in expression
xlat %{test:
-match ERROR offset 7: Missing closing brace
+match ERROR offset 8: Missing closing brace
xlat %{test:%{User-Name
-match ERROR offset 18: Missing closing brace
+match ERROR offset 19: Missing closing brace
# Discuss - Not sure the offset/message is correct here, but not sure if we can determine the correct offset either
xlat %{test:%{User-Name}
-match ERROR offset 19: Missing closing brace
+match ERROR offset 20: Missing closing brace
xlat %{myfirstxlat
-match ERROR offset 13: Missing closing brace
+match ERROR offset 14: Missing closing brace
# Issue seen in the wild that caused an SEGV during pass2
xlat %{%{control.IP-Pool.Name}:%{reply.IP-Pool.Range}
-match ERROR offset 25: Expected ':-' after first expansion
+match ERROR offset 26: Expected ':-' after first expansion
#
# API to split xlat strings into argv-style arguments.
# and errors
xlat_argv /bin/sh "foo bar" "%{User-Name} %{Filter-Id"
-match ERROR offset 44: Missing closing brace
+match ERROR offset 45: Missing closing brace
# and text immediately after a variable expansion
xlat_argv echo hello %{Tmp-String-0}:1234 world
# so the "offset 23" is wrong. It also doesn't say *which* string is wrong. We'll fix that later.
#
xlat %(rpad:&User-Name foo x)
-match ERROR offset 23: Failed parsing argument 1 as type 'uint64'
+match ERROR offset 24: Failed parsing argument 1 as type 'uint64'
count
match 187
match ERROR offset 5: Invalid operator
xlat_purify (ok =x handled)
-match ERROR offset 4: Invalid operator
+match ERROR offset 5: Invalid operator
#
# Re-enable when we have proper bareword xlat tokenization
#match !ok
xlat_purify !!true
-match ERROR offset 1: Double operator is invalid
+match ERROR offset 2: Double operator is invalid
#xlat_purify !(!ok)
#match ok
# '!' is higher precedence that '==', so the '!' applies just to the User-Name
#
xlat_purify (!&User-Name == &User-Password || &Filter-Id == &Reply-Message)
-match ERROR offset 1: Operator '!' is only applied to the left hand side of the '==' operation, add (..) to evaluate the operation first
+match ERROR offset 2: Operator '!' is only applied to the left hand side of the '==' operation, add (..) to evaluate the operation first
#
# LHS is a boolean, which we then compare to a string
#
xlat_purify (!"foo" == "bar")
-match ERROR offset 1: Operator '!' is only applied to the left hand side of the '==' operation, add (..) to evaluate the operation first
+match ERROR offset 2: Operator '!' is only applied to the left hand side of the '==' operation, add (..) to evaluate the operation first
xlat_purify ((!"foo") == "bar")
match NULL
match (&Packet-Type == Access-Challenge)
xlat_purify &reply == &request
-match ERROR offset 0: Cannot use list references in condition
+match ERROR offset 1: Cannot use list references in condition
xlat_purify &reply == "hello"
-match ERROR offset 0: Cannot use list references in condition
+match ERROR offset 1: Cannot use list references in condition
xlat_purify "hello" == &reply
-match ERROR offset 11: Cannot use list references in condition
+match ERROR offset 12: Cannot use list references in condition
#
match (&User-Name != &User-Password)
xlat_purify !&User-Name != &User-Password
-match ERROR offset 0: Operator '!' is only applied to the left hand side of the '!=' operation, add (..) to evaluate the operation first
+match ERROR offset 1: Operator '!' is only applied to the left hand side of the '!=' operation, add (..) to evaluate the operation first
#
# We allow a cast for the existence check. Why not?
# string the RHS is.
#
xlat_purify &NAS-Port == X
-match ERROR offset 0: Failed parsing string as type 'uint32'
+match ERROR offset 1: Failed parsing string as type 'uint32'
#match ERROR offset 13: Failed parsing string as type 'uint32'
#
match true
xlat_purify (/foo/)
-match ERROR offset 1: Unexpected regular expression
+match ERROR offset 2: Unexpected regular expression
#
# Tests for (FOO).
match ((&User-Name == "bob") && (&User-Password == "bob") && %{rcode:'handled'})
xlat_purify handledx
-match ERROR offset 0: Unexpected text - attribute names must prefixed with '&'
+match ERROR offset 1: Unexpected text - attribute names must prefixed with '&'
xlat_purify handled
match %{rcode:'handled'}
match (&User-Name !~ /^foo\nbar$/i)
xlat_purify (&User-Name =~ "handled")
-match ERROR offset 15: Expected regular expression
+match ERROR offset 16: Expected regular expression
xlat_purify (&User-Name == /foo/)
-match ERROR offset 15: Unexpected regular expression
+match ERROR offset 16: Unexpected regular expression
# @todo - this should be allowed?
xlat_purify &User-Name =~ &Filter-Id
-match ERROR offset 14: Expected regular expression
+match ERROR offset 15: Expected regular expression
xlat_expr &User-Name =~ (/foo/)
-match ERROR offset 14: Expected regular expression
+match ERROR offset 15: Expected regular expression
#
# Flags
match ((uint32)&Tmp-String-0 =~ /foo/)
xlat_purify &Tmp-String-0 =~ <integer>/foo/
-match ERROR offset 17: Expected regular expression
+match ERROR offset 18: Expected regular expression
xlat_expr %{33}
-match ERROR offset 2: Invalid regex reference. Must be in range 0-32
+match ERROR offset 3: Invalid regex reference. Must be in range 0-32
xlat_purify &User-Name == /foo/
-match ERROR offset 14: Unexpected regular expression
+match ERROR offset 15: Unexpected regular expression
#
# single-quoted strings in regexes!
xlat_purify !true
match false
+# Offset 6 is wrong... but the code is structured strangely here
xlat_purify -fail
-match ERROR offset 9: Invalid operation on module return code
+match ERROR offset 6: Invalid operation on module return code
xlat_purify ~fail
-match ERROR offset 9: Invalid operation on module return code
+match ERROR offset 6: Invalid operation on module return code
xlat_purify !fail
match !%{rcode:'fail'}