* Named policies are on the stack for catching recursion.
*/
if ((*pitem)->type == POLICY_TYPE_NAMED_POLICY) {
+ state->depth--;
goto redo;
}
{
int rcode;
const policy_condition_t *this;
- VALUE_PAIR *vp;
+ VALUE_PAIR *vp = NULL;
const char *data = NULL;
int compare;
#ifdef HAVE_REGEX_H
rcode = (rcode == FALSE); /* reverse sense of test */
break;
+ case POLICY_LEX_CMP_FALSE: /* non-existence */
+ if (this->lhs_type == POLICY_LEX_BARE_WORD) {
+ vp = find_vp(state->request, this->lhs);
+ rcode = (vp == NULL);
+ } else {
+ rcode = (data == NULL);
+ }
+ break;
+
case POLICY_LEX_CMP_TRUE: /* existence */
if (this->lhs_type == POLICY_LEX_BARE_WORD) {
vp = find_vp(state->request, this->lhs);
if (this->lhs_type == POLICY_LEX_BARE_WORD) {
VALUE_PAIR *myvp;
-
vp = find_vp(state->request, this->lhs);
+
+ /*
+ * A op B always returns FALSE if A doesn't
+ * exist.
+ */
+ if (!vp) return FALSE; /* not in the request */
+
/*
* FIXME: Move sanity checks to
* post-parse code, so we don't do
* it on every packet.
*/
- if (vp) {
- vp_prints_value(buffer, sizeof(buffer), vp, 0);
- myvp = pairmake(vp->name, this->rhs, T_OP_EQ);
- } else {
- buffer[0] = '\0';
- myvp = pairmake(this->lhs, this->rhs, T_OP_EQ);
- }
+ vp_prints_value(buffer, sizeof(buffer), vp, 0);
+ myvp = pairmake(vp->name, this->rhs, T_OP_EQ);
data = buffer;
- if (!myvp) {
- return FALSE;
- }
/*
* FIXME: What to do about comparisons
{ "=", POLICY_LEX_ASSIGN },
{ "==", POLICY_LEX_CMP_EQUALS },
{ "!=", POLICY_LEX_CMP_NOT_EQUALS },
+ { "=*", POLICY_LEX_CMP_TRUE },
+ { "!*", POLICY_LEX_CMP_FALSE },
{ "<", POLICY_LEX_LT },
{ ">", POLICY_LEX_GT },
{ "<=", POLICY_LEX_LE },
lrad_int2str(rlm_policy_tokens, token, "?"));
return 0;
}
- goto check;
} /* else it's a comparison? */
+ goto check;
case POLICY_LEX_DOUBLE_QUOTED_STRING:
this->lhs_type = token;
case POLICY_LEX_CMP_NOT_EQUALS:
case POLICY_LEX_RX_EQUALS:
case POLICY_LEX_RX_NOT_EQUALS:
+ case POLICY_LEX_CMP_TRUE:
+ case POLICY_LEX_CMP_FALSE:
case POLICY_LEX_LT:
case POLICY_LEX_GT:
case POLICY_LEX_LE: