break;
}
- if (condition->lhs_type == POLICY_LEX_BARE_WORD) {
- printf("%s", condition->lhs);
+ if (condition->lhs_type == POLICY_LEX_FUNCTION) {
+ printf("%s()", condition->lhs);
} else {
/*
* FIXME: escape ",
printf("\"%s\"", condition->lhs);
}
- if (condition->compare == POLICY_LEX_BARE_WORD) {
- printf("()");
+ /*
+ * We always print this condition.
+ */
+ printf(" %s ", lrad_int2str(rlm_policy_tokens,
+ condition->compare,
+ "?"));
+ if (condition->rhs_type == POLICY_LEX_BARE_WORD) {
+ printf("%s", condition->rhs);
} else {
/*
- * We always print this condition.
+ * FIXME: escape ",
+ * and move all of this logic
+ * to a function.
*/
- printf(" %s ", lrad_int2str(rlm_policy_tokens,
- condition->compare,
- "?"));
- if (condition->rhs_type == POLICY_LEX_BARE_WORD) {
- printf("%s", condition->rhs);
- } else {
- /*
- * FIXME: escape ",
- * and move all of this logic
- * to a function.
- */
- printf("\"%s\"", condition->rhs);
- }
+ printf("\"%s\"", condition->rhs);
}
printf(")");
}
break;
+ case POLICY_TYPE_RETURN:
+ {
+ const policy_return_t *this;
+
+ this = (const policy_return_t *) item;
+ if (indent) printf("%*s", indent, " ");
+ printf("return %s\n",
+ lrad_int2str(policy_return_codes,
+ this->rcode, "???"));
+ }
+ break;
+
default:
if (indent) printf("%*s", indent, " ");
printf("[HUH?]\n");
typedef struct policy_state_t {
rlm_policy_t *inst;
REQUEST *request; /* so it's not passed on the C stack */
+ int rcode; /* for functions, etc. */
int depth;
const policy_item_t *stack[POLICY_MAX_STACK];
} policy_state_t;
printf("%s", buffer);
}
+ /*
+ * Doesn't change state->rcode
+ */
+
return 1;
}
int rcode;
const policy_condition_t *this;
VALUE_PAIR *vp;
- char *data = NULL;
+ const char *data = NULL;
int compare;
#ifdef HAVE_REGEX_H
regex_t reg;
/*
* FIXME: Don't always do this...
*/
- if ((this->compare != POLICY_LEX_L_BRACKET) &&
- (this->lhs_type == POLICY_LEX_DOUBLE_QUOTED_STRING)) {
- if (radius_xlat(lhs_buffer, sizeof(lhs_buffer), this->lhs,
- state->request, NULL) > 0) {
- data = lhs_buffer;
+ if (this->compare != POLICY_LEX_L_BRACKET) {
+ if (this->lhs_type == POLICY_LEX_FUNCTION) {
+ /*
+ * We can't call evaluate_call here,
+ * because that just pushes stuff onto
+ * the stack, and we want to actually
+ * evaluate all of it...
+ */
+ rcode = policy_evaluate_name(state, this->lhs);
+ data = lrad_int2str(policy_return_codes, rcode, "???");
+ strNcpy(lhs_buffer, data, sizeof(lhs_buffer)); /* FIXME: yuck */
+ } else if (this->lhs_type == POLICY_LEX_DOUBLE_QUOTED_STRING) {
+ if (radius_xlat(lhs_buffer, sizeof(lhs_buffer), this->lhs,
+ state->request, NULL) > 0) {
+ data = lhs_buffer;
+ }
}
}
rcode = (rcode == FALSE); /* reverse sense of test */
break;
- case POLICY_LEX_BARE_WORD:
- /*
- * We can't call evaluate_call here, because that just
- * pushes stuff onto the stack, and we want to actually
- * evaluate all of it...
- *
- * Hmm.... why are these things different?
- */
- rcode = policy_evaluate_name(state,
- ((const policy_named_t *) this->child)->name);
- break;
-
case POLICY_LEX_CMP_TRUE: /* existence */
if (this->lhs_type == POLICY_LEX_BARE_WORD) {
vp = find_vp(state->request, this->lhs);
return 0;
}
+ state->rcode = RLM_MODULE_UPDATED; /* we did stuff */
+
return 1;
}
/*
- * Evaluate an 'call foo' statement
+ * Evaluate a reference call to a module.
*/
static int evaluate_call(policy_state_t *state, const policy_item_t *item)
{
rad_assert(policy->policy->type != POLICY_TYPE_BAD);
rad_assert(policy->policy->type < POLICY_TYPE_NUM_TYPES);
+ /*
+ * Push the name of the function onto the stack,
+ * so that we can catch recursive calls.
+ *
+ * The "pop" function will skip over it when it sees it.
+ */
rcode = policy_stack_push(state, (const policy_item_t *) policy);
if (!rcode) {
return rcode;
/*
+ * Evaluate a return statement
+ */
+static int evaluate_return(policy_state_t *state, const policy_item_t *item)
+{
+ const policy_return_t *this;
+
+ this = (const policy_return_t *) item;
+ state->rcode = this->rcode;
+
+ return 1; /* we succeeded */
+}
+
+
+/*
* State machine stuff.
*/
typedef int (*policy_evaluate_type_t)(policy_state_t *, const policy_item_t *);
evaluate_attr_list,
evaluate_print,
NULL, /* define a named policy.. */
- evaluate_call
+ evaluate_call,
+ evaluate_return
};
}
} /* loop until the stack is empty */
- return RLM_MODULE_OK;
+ return state->rcode;
}
memset(state, 0, sizeof(*state));
state->request = request;
state->inst = inst;
+ state->rcode = RLM_MODULE_OK;
rcode = policy_evaluate_name(state, name);
#include <dirent.h>
#endif
+#include <modules.h>
+
+const LRAD_NAME_NUMBER policy_return_codes[] = {
+ { "reject", RLM_MODULE_REJECT },
+ { "fail", RLM_MODULE_FAIL },
+ { "ok", RLM_MODULE_OK },
+ { "handled", RLM_MODULE_HANDLED },
+ { "invalid", RLM_MODULE_INVALID },
+ { "userlock", RLM_MODULE_USERLOCK },
+ { "notfound", RLM_MODULE_NOTFOUND },
+ { "noop", RLM_MODULE_NOOP },
+ { "updated", RLM_MODULE_UPDATED },
+ { NULL, RLM_MODULE_NUMCODES }
+};
+
/*
* Explanations of what the lexical tokens are.
*/
#define debug_tokens if (lexer->debug & POLICY_DEBUG_PRINT_TOKENS) printf
-static int parse_call(policy_lex_file_t *lexer, policy_item_t **tail,
- const char *name);
/*
* Function to return a token saying what it read, and possibly
{ "proxy-request", POLICY_RESERVED_PROXY_REQUEST },
{ "proxy-reply", POLICY_RESERVED_PROXY_REPLY },
{ "include", POLICY_RESERVED_INCLUDE },
+ { "return", POLICY_RESERVED_RETURN },
{ NULL, POLICY_RESERVED_UNKNOWN }
};
}
- this->lhs = strdup(lhs);
- this->lhs_type = POLICY_LEX_BARE_WORD;
- this->compare = POLICY_LEX_BARE_WORD;
- this->child_condition = POLICY_LEX_BARE_WORD;
+ /*
+ * this->lhs set up below, after "check"
+ */
+ this->lhs_type = POLICY_LEX_FUNCTION;
- if (!parse_call(lexer, &this->child, lhs)) {
+ /*
+ * Copied from parse_call
+ */
+ token = policy_lex_file(lexer, 0, NULL, 0);
+ if (token != POLICY_LEX_L_BRACKET) {
+ fprintf(stderr, "%s[%d]: Expected left bracket, got \"%s\"\n",
+ lexer->filename, lexer->lineno,
+ lrad_int2str(rlm_policy_tokens, token, "?"));
return 0;
}
- break;
+
+ token = policy_lex_file(lexer, 0, NULL, 0);
+ if (token != POLICY_LEX_R_BRACKET) {
+ fprintf(stderr, "%s[%d]: Expected right bracket, got \"%s\"\n",
+ lexer->filename, lexer->lineno,
+ lrad_int2str(rlm_policy_tokens, token, "?"));
+ return 0;
+ }
+ goto check;
} /* else it's a comparison? */
case POLICY_LEX_DOUBLE_QUOTED_STRING:
/*
* Got word. May just be test for existence.
*/
+ check:
token = policy_lex_file(lexer, POLICY_LEX_FLAG_PEEK, NULL, 0);
if (token == POLICY_LEX_R_BRACKET) {
debug_tokens("[TEST %s] ", lhs);
/*
+ * Parse a return statement.
+ */
+static int parse_return(policy_lex_file_t *lexer, policy_item_t **tail)
+{
+ int rcode;
+ policy_lex_t token;
+ char buffer[32];
+ policy_return_t *this;
+
+ token = policy_lex_file(lexer, 0, buffer, sizeof(buffer));
+ if (token != POLICY_LEX_BARE_WORD) {
+ fprintf(stderr, "%s[%d]: Unexpected token %s\n",
+ lexer->filename, lexer->lineno,
+ lrad_int2str(rlm_policy_tokens, token, "?"));
+ return 0;
+ }
+
+ rcode = lrad_str2int(policy_return_codes, buffer, RLM_MODULE_NUMCODES);
+ if (rcode == RLM_MODULE_NUMCODES) {
+ fprintf(stderr, "%s[%d]: Invalid return code %s\n",
+ lexer->filename, lexer->lineno, buffer);
+ return 0;
+ }
+
+ /*
+ * Look for more sutff
+ */
+ token = policy_lex_file(lexer, POLICY_LEX_FLAG_PEEK,
+ NULL, sizeof(0));
+ if (token != POLICY_LEX_RC_BRACKET) {
+ fprintf(stderr, "%s[%d]: return statement must be the last statement in a policy.\n",
+ lexer->filename, lexer->lineno);
+ return 0;
+ }
+
+ this = rad_malloc(sizeof(*this));
+ memset(this, 0, sizeof(*this));
+
+ this->item.type = POLICY_TYPE_RETURN;
+ this->item.lineno = lexer->lineno;
+ this->rcode = rcode;
+
+ *tail = (policy_item_t *) this;
+
+ return 1;
+}
+
+/*
* Parse one statement. 'foo = bar', or 'if (...) {...}', or '{...}',
* and so on.
*/
return 0;
break;
+ case POLICY_RESERVED_RETURN:
+ if (parse_return(lexer, tail)) {
+ return 1;
+ }
+ return 0;
+ break;
+
case POLICY_RESERVED_UNKNOWN: /* wasn't a reserved word */
/*
* Is a named policy, parse the reference to it.
* For now, policy names aren't scoped, they're global.
*/
if (!rlm_policy_insert(lexer->policies, this)) {
- fprintf(stderr, "Failed to insert %s\n", this->name);
+ fprintf(stderr, "Failed to insert policy \"%s\"\n", this->name);
rlm_policy_free_item((policy_item_t *) this);
return 0;
}
*/
while ((dp = readdir(dir)) != NULL) {
if (dp->d_name[0] == '.') continue;
-
+ if (strchr(dp->d_name, '~') != NULL) continue;
+
strNcpy(p, dp->d_name,
sizeof(buffer) - (p - buffer));
+ debug_tokens("\nreading file %s\n", buffer);
if (!rlm_policy_parse(lexer->policies, buffer)) {
closedir(dir);
return 0;
/*
* Handle one include file.
*/
+ debug_tokens("\nreading file %s\n", buffer);
if (!rlm_policy_parse(lexer->policies, buffer)) {
return 0;
}
{
FILE *fp;
policy_lex_t token;
- policy_lex_file_t mylexer, *lexer;
+ policy_lex_file_t mylexer, *lexer = NULL;
char buffer[32];
fp = fopen(filename, "r");