value_pair_map_t *map;
if (c->type == COND_TYPE_EXISTS) {
+
if (c->data.vpt->type == VPT_TYPE_XLAT) {
return pass2_xlat_compile(c->ci, &c->data.vpt, true);
}
rad_assert(c->data.vpt->type != VPT_TYPE_REGEX);
/*
- * FIXME: fix up attribute references, too!
+ * The existence check might have been &Foo-Bar,
+ * where Foo-Bar is defined by a module.
*/
+ if (c->pass2_fixup == PASS2_FIXUP_ATTR) {
+ value_pair_tmpl_t *vpt;
+ vpt = radius_str2tmpl(c, c->data.vpt->name, T_BARE_WORD, REQUEST_CURRENT, PAIR_LIST_REQUEST);
+ if (!vpt) {
+ cf_log_err(c->ci, "Unknown attribute '%s'", c->data.vpt->name + 1);
+ return false;
+ }
+
+ talloc_free(c->data.vpt);
+ c->data.vpt = vpt;
+ c->pass2_fixup = PASS2_FIXUP_NONE;
+ }
return true;
}
c->data.vpt = radius_str2tmpl(c, lhs, lhs_type, REQUEST_CURRENT, PAIR_LIST_REQUEST);
if (!c->data.vpt) {
- return_P("Failed creating exists");
+ /*
+ * If strings are T_BARE_WORD and they start with '&',
+ * then they refer to attributes which have not yet been
+ * defined. Create the template(s) as literals, and
+ * fix them up in pass2.
+ */
+ if ((*lhs != '&') ||
+ (lhs_type != T_BARE_WORD)) {
+ return_P("Failed creating exists");
+ }
+ c->data.vpt = radius_str2tmpl(c, lhs + 1, lhs_type, REQUEST_CURRENT, PAIR_LIST_REQUEST);
+ if (!c->data.vpt) {
+ return_P("Failed creating exists");
+ }
+ rad_const_free(c->data.vpt->name);
+ c->data.vpt->name = talloc_strdup(c->data.vpt, lhs);
+ c->pass2_fixup = PASS2_FIXUP_ATTR;
}
rad_assert(c->data.vpt->type != VPT_TYPE_REGEX);
REQUEST_CURRENT, PAIR_LIST_REQUEST);
if (!c->data.map) {
/*
- * FIXME: if strings are T_BARE_WORD and they start with '&',
+ * If strings are T_BARE_WORD and they start with '&',
* then they refer to attributes which have not yet been
* defined. Create the template(s) as literals, and
* fix them up in pass2.
/*
* FOO =* BAR --> FOO
* FOO !* BAR --> !FOO
+ *
+ * FOO may be a string, or a delayed attribute
+ * reference.
*/
if ((c->data.map->op == T_OP_CMP_TRUE) ||
(c->data.map->op == T_OP_CMP_FALSE)) {
/*
* Existence checks. We short-circuit static strings,
* too.
+ *
+ * FIXME: the data types should be in the template, too.
+ * So that we know where a literal came from.
+ *
+ * "foo" is NOT the same as 'foo' or a bare foo.
*/
if (c->type == COND_TYPE_EXISTS) {
switch (c->data.vpt->type) {
} else if (lhs_type == T_BARE_WORD) {
int rcode;
+ bool zeros = true;
char const *q;
for (q = c->data.vpt->name;
if (!isdigit((int) *q)) {
break;
}
+ if (*q != '0') zeros = false;
}
/*
* 'true'.
*/
if (!*q) {
- c->type = COND_TYPE_TRUE;
+ if (zeros) {
+ c->type = COND_TYPE_TRUE;
+ } else {
+ c->type = COND_TYPE_TRUE;
+ }
TALLOC_FREE(c->data.vpt);
break;
}
+ /*
+ * Allow &Foo-Bar where Foo-Bar is an attribute
+ * defined by a module.
+ */
+ if (c->pass2_fixup == PASS2_FIXUP_ATTR) {
+ break;
+ }
+
rcode = fr_str2int(allowed_return_codes,
c->data.vpt->name, 0);
if (!rcode) {