2 * evaluate.c Evaluate a policy language
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2004 Alan DeKok <aland@ox.org>
21 * Copyright 2006 The FreeRADIUS server project
24 #include <freeradius-devel/ident.h>
27 #include "rlm_policy.h"
33 #define debug_evaluate if (0) printf
36 * Print stuff we've parsed
38 static void policy_print(const policy_item_t *item, int indent)
41 if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
42 fprintf(fr_log_fp, "[NULL]\n");
49 if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
50 fprintf(fr_log_fp, "[BAD STATEMENT]");
53 case POLICY_TYPE_PRINT:
54 if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
56 const policy_print_t *this;
58 this = (const policy_print_t *) item;
60 if (this->rhs_type == POLICY_LEX_BARE_WORD) {
61 fprintf(fr_log_fp, "print %s\n", this->rhs);
63 fprintf(fr_log_fp, "print \"%s\"\n", this->rhs);
68 case POLICY_TYPE_ASSIGNMENT:
70 const policy_assignment_t *assign;
72 assign = (const policy_assignment_t *) item;
73 if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
75 fprintf(fr_log_fp, "\t%s %s ", assign->lhs,
76 fr_int2str(rlm_policy_tokens,
77 assign->assign, "?"));
78 if (assign->rhs_type == POLICY_LEX_BARE_WORD) {
79 fprintf(fr_log_fp, "%s\n", assign->rhs);
84 fprintf(fr_log_fp, "\"%s\"\n", assign->rhs);
89 case POLICY_TYPE_CONDITIONAL: /* no indentation here */
91 const policy_condition_t *condition;
93 condition = (const policy_condition_t *) item;
95 fprintf(fr_log_fp, "(");
97 if (condition->sense) {
98 fprintf(fr_log_fp, "!");
104 if (condition->compare == POLICY_LEX_L_BRACKET) {
105 policy_print(condition->child, indent);
106 fprintf(fr_log_fp, ")");
110 if (condition->compare == POLICY_LEX_L_NOT) {
111 fprintf(fr_log_fp, "!");
112 policy_print(condition->child, indent);
113 fprintf(fr_log_fp, ")");
117 if (condition->compare == POLICY_LEX_CMP_TRUE) {
118 fprintf(fr_log_fp, "%s)", condition->lhs);
122 if (condition->lhs_type == POLICY_LEX_FUNCTION) {
123 fprintf(fr_log_fp, "%s()", condition->lhs);
127 * and move all of this logic
130 fprintf(fr_log_fp, "\"%s\"", condition->lhs);
134 * We always print this condition.
136 fprintf(fr_log_fp, " %s ", fr_int2str(rlm_policy_tokens,
139 if (condition->rhs_type == POLICY_LEX_BARE_WORD) {
140 fprintf(fr_log_fp, "%s", condition->rhs);
144 * and move all of this logic
147 fprintf(fr_log_fp, "\"%s\"", condition->rhs);
149 fprintf(fr_log_fp, ")");
151 if ((condition->child_condition != POLICY_LEX_BAD) &&
152 (condition->child_condition != POLICY_LEX_BARE_WORD)) {
153 fprintf(fr_log_fp, " %s ", fr_int2str(rlm_policy_tokens, condition->child_condition, "?"));
154 policy_print(condition->child, indent);
161 const policy_if_t *statement;
163 statement = (const policy_if_t *) item;
165 if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
166 fprintf(fr_log_fp, "if ");
167 policy_print(statement->condition, indent);
168 fprintf(fr_log_fp, " {\n");
169 policy_print(statement->if_true, indent + 1);
170 if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
171 if (statement->if_false) {
172 fprintf(fr_log_fp, "} else ");
173 if (statement->if_false->type == POLICY_TYPE_ASSIGNMENT) {
174 fprintf(fr_log_fp, " { ");
175 policy_print(statement->if_false, indent + 1);
176 if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
177 fprintf(fr_log_fp, " }");
179 policy_print(statement->if_false, indent + 1);
182 fprintf(fr_log_fp, "}\n");
187 case POLICY_TYPE_ATTRIBUTE_LIST:
189 const policy_attributes_t *this;
191 this = (const policy_attributes_t *) item;
193 if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
194 fprintf(fr_log_fp, "%s %s {\n",
195 fr_int2str(policy_reserved_words,
197 fr_int2str(rlm_policy_tokens,
199 policy_print(this->attributes, indent + 1);
200 if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
201 fprintf(fr_log_fp, "}\n");
205 case POLICY_TYPE_NAMED_POLICY:
207 const policy_named_t *this;
209 this = (const policy_named_t *) item;
210 if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
211 fprintf(fr_log_fp, "policy %s {\n", this->name);
212 policy_print(this->policy, indent + 1);
213 if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
214 fprintf(fr_log_fp, "}\n");
218 case POLICY_TYPE_CALL:
220 const policy_call_t *this;
222 this = (const policy_call_t *) item;
223 if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
224 fprintf(fr_log_fp, "call %s\n", this->name);
228 case POLICY_TYPE_RETURN:
230 const policy_return_t *this;
232 this = (const policy_return_t *) item;
233 if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
234 fprintf(fr_log_fp, "return %s\n",
235 fr_int2str(policy_return_codes,
236 this->rcode, "???"));
240 case POLICY_TYPE_MODULE:
242 const policy_module_t *this;
244 this = (const policy_module_t *) item;
245 if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
246 fprintf(fr_log_fp, "module %s <stuff>\n",
247 fr_int2str(policy_component_names,
248 this->component, "???"));
253 if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
254 fprintf(fr_log_fp, "[HUH?]\n");
264 void rlm_policy_print(const policy_item_t *item)
266 if (!fr_log_fp) return;
268 fprintf(fr_log_fp, "# rlm_policy \n");
269 policy_print(item, 0);
273 * Internal stack of things to do. This lets us have function
276 * Yes, we should learn lex, yacc, etc.
278 #define POLICY_MAX_STACK 16
279 typedef struct policy_state_t {
281 REQUEST *request; /* so it's not passed on the C stack */
282 int rcode; /* for functions, etc. */
283 int component; /* for calling other modules */
285 const policy_item_t *stack[POLICY_MAX_STACK];
289 static int policy_evaluate_name(policy_state_t *state, const char *name);
292 * Push an item onto the state.
294 static int policy_stack_push(policy_state_t *state, const policy_item_t *item)
296 rad_assert(state->depth >= 0);
299 * Asked to push nothing. Don't push it.
304 * State is full. Die.
306 if (state->depth >= POLICY_MAX_STACK) {
311 * Walk back up the stack, looking for previous ocurrances
312 * of this name. If found, we have infinite recursion,
313 * which we stop dead in the water!
315 * This isn't strictly necessary right now, as we look up
316 * policies by name when they're first referenced. This
317 * means that ALL references are backwards (to the start
318 * of the file), which means that there are no circular
321 if (item->type == POLICY_TYPE_NAMED_POLICY) {
324 for (i = 0; i < state->depth; i++) {
326 * Check for circular references, by seeing
327 * if the function is already on the stack.
329 * Hmmm... do we want to do this for any type?
331 if (state->stack[i] == item) {
332 debug_evaluate("Circular call to policy %s\n",
333 ((const policy_named_t *) item)->name);
339 debug_evaluate("push %d %p\n", state->depth, item);
341 state->stack[state->depth] = item;
342 state->depth++; /* points to unused entry */
349 * Pop an item from the state.
351 static int policy_stack_pop(policy_state_t *state, const policy_item_t **pitem)
353 rad_assert(pitem != NULL);
354 rad_assert(state->depth >= 0);
357 if (state->depth == 0) {
362 *pitem = state->stack[state->depth - 1];
365 * Named policies are on the stack for catching recursion.
367 if ((*pitem)->type == POLICY_TYPE_NAMED_POLICY) {
373 * Process the whole item list.
375 if ((*pitem)->next) {
376 state->stack[state->depth - 1] = (*pitem)->next;
377 debug_evaluate("pop/push %d %p\n", state->depth - 1, *pitem);
379 state->depth--; /* points to unused entry */
380 debug_evaluate("pop %d %p\n", state->depth, *pitem);
388 * Evaluate a print statement
390 static int evaluate_print(policy_state_t *state, const policy_item_t *item)
392 const policy_print_t *this;
394 if (!fr_log_fp) return 1;
396 this = (const policy_print_t *) item;
398 if (this->rhs_type == POLICY_LEX_BARE_WORD) {
399 fprintf(fr_log_fp, "%s\n", this->rhs);
403 radius_xlat(buffer, sizeof(buffer), this->rhs,
404 state->request, NULL);
405 fprintf(fr_log_fp, "%s", buffer);
406 if (!strchr(buffer, '\n')) fprintf(fr_log_fp, "\n");
410 * Doesn't change state->rcode
417 * Return a VALUE_PAIR, given an attribute name.
419 * FIXME: Have it return the N'th one, too, like
422 * The amount of duplicated code is getting annoying...
424 static VALUE_PAIR *find_vp(REQUEST *request, const char *name)
427 const DICT_ATTR *dattr;
431 vps = request->packet->vps;;
434 * FIXME: use names from reserved word list?
436 if (strncasecmp(name, "request:", 8) == 0) {
438 } else if (strncasecmp(name, "reply:", 6) == 0) {
440 vps = request->reply->vps;
442 } else if (strncasecmp(name, "proxy-request:", 14) == 0) {
444 if (request->proxy) {
445 vps = request->proxy->vps;
447 } else if (strncasecmp(name, "proxy-reply:", 12) == 0) {
449 if (request->proxy_reply) {
450 vps = request->proxy_reply->vps;
453 } else if (strncasecmp(name, "control:", 8) == 0) {
455 vps = request->config_items;
456 } /* else it must be a bare attribute name */
462 dattr = dict_attrbyname(p);
464 fprintf(stderr, "No such attribute %s\n", p);
465 return NULL; /* no such attribute */
468 return pairfind(vps, dattr->attr, dattr->vendor);
473 * Evaluate an assignment
475 * Not really used much...
477 static int evaluate_assignment(UNUSED policy_state_t *state, const policy_item_t *item)
479 const policy_assignment_t *this;
481 const DICT_ATTR *dattr;
484 this = (const policy_assignment_t *) item;
486 rad_assert(this->lhs != NULL);
487 rad_assert(this->rhs != NULL);
490 dattr = dict_attrbyname(this->lhs);
492 fprintf(stderr, "HUH?\n");
502 * Evaluate a condition
504 static int evaluate_condition(policy_state_t *state, const policy_item_t *item)
507 const policy_condition_t *this;
508 VALUE_PAIR *vp = NULL;
509 const char *data = NULL;
515 char lhs_buffer[2048];
517 this = (const policy_condition_t *) item;
521 * FIXME: Don't always do this...
523 if (this->compare != POLICY_LEX_L_BRACKET) {
524 if (this->lhs_type == POLICY_LEX_FUNCTION) {
526 * We can't call evaluate_call here,
527 * because that just pushes stuff onto
528 * the stack, and we want to actually
529 * evaluate all of it...
531 rcode = policy_evaluate_name(state, this->lhs);
532 data = fr_int2str(policy_return_codes, rcode, "???");
533 strlcpy(lhs_buffer, data, sizeof(lhs_buffer)); /* FIXME: yuck */
534 } else if (this->lhs_type == POLICY_LEX_DOUBLE_QUOTED_STRING) {
535 if (radius_xlat(lhs_buffer, sizeof(lhs_buffer), this->lhs,
536 state->request, NULL) > 0) {
542 switch (this->compare) {
543 case POLICY_LEX_L_BRACKET: /* nested brackets are a special case */
544 rcode = evaluate_condition(state, this->child);
547 case POLICY_LEX_L_NOT:
548 rcode = evaluate_condition(state, this->child);
549 rcode = (rcode == FALSE); /* reverse sense of test */
552 case POLICY_LEX_CMP_FALSE: /* non-existence */
553 if (this->lhs_type == POLICY_LEX_BARE_WORD) {
554 vp = find_vp(state->request, this->lhs);
555 rcode = (vp == NULL);
557 rcode = (data == NULL);
561 case POLICY_LEX_CMP_TRUE: /* existence */
562 if (this->lhs_type == POLICY_LEX_BARE_WORD) {
563 vp = find_vp(state->request, this->lhs);
564 rcode = (vp != NULL);
566 rcode = (data != NULL);
570 default: /* process other comparisons */
571 if ((this->compare != POLICY_LEX_CMP_EQUALS) &&
573 (this->compare != POLICY_LEX_RX_EQUALS) &&
574 (this->compare != POLICY_LEX_RX_NOT_EQUALS) &&
576 (this->compare != POLICY_LEX_LT) &&
577 (this->compare != POLICY_LEX_GT) &&
578 (this->compare != POLICY_LEX_LE) &&
579 (this->compare != POLICY_LEX_GE) &&
580 (this->compare != POLICY_LEX_CMP_NOT_EQUALS)) {
581 fprintf(stderr, "%d: bad comparison\n",
586 if (this->lhs_type == POLICY_LEX_BARE_WORD) {
589 vp = find_vp(state->request, this->lhs);
592 * A op B is FALSE if A doesn't
601 * FIXME: Move sanity checks to
602 * post-parse code, so we don't do
603 * it on every packet.
605 vp_prints_value(buffer, sizeof(buffer), vp, 0);
606 myvp = pairmake(vp->name, this->rhs, T_OP_EQ);
607 if (!myvp) return FALSE; /* memory failure */
611 * FIXME: What to do about comparisons
612 * where vp doesn't exist? Right now,
613 * "simplepaircmp" returns -1, which is
614 * probably a bad idea. it should
615 * instead take an operator, a pointer to
616 * the comparison result, and return
617 * "true/false" for "comparions
618 * succeeded/failed", which are different
619 * error codes than "comparison is less
620 * than, equal to, or greater than zero".
622 compare = radius_callback_compare(state->request,
623 vp, myvp, NULL, NULL);
628 * FIXME: Do something for RHS type?
630 fr_printf_log("CMP %s %s\n", lhs_buffer, this->rhs);
631 compare = strcmp(lhs_buffer, this->rhs);
634 debug_evaluate("CONDITION COMPARE %d\n", compare);
636 switch (this->compare) {
637 case POLICY_LEX_CMP_EQUALS:
638 rcode = (compare == 0);
641 case POLICY_LEX_CMP_NOT_EQUALS:
642 rcode = (compare != 0);
646 rcode = (compare < 0);
650 rcode = (compare > 0);
654 rcode =(compare <= 0);
658 rcode = (compare >= 0);
662 case POLICY_LEX_RX_EQUALS:
663 { /* FIXME: copied from src/main/valuepair.c */
665 regmatch_t rxmatch[REQUEST_MAX_REGEX + 1];
668 * Include substring matches.
670 if (regcomp(®, this->rhs,
671 REG_EXTENDED) != 0) {
672 /* FIXME: print error */
675 rad_assert(data != NULL);
676 rcode = regexec(®, data,
677 REQUEST_MAX_REGEX + 1,
679 rcode = (rcode == 0);
683 * Add %{0}, %{1}, etc.
685 for (i = 0; i <= REQUEST_MAX_REGEX; i++) {
690 * Didn't match: delete old
691 * match, if it existed.
694 (rxmatch[i].rm_so == -1)) {
695 p = request_data_get(state->request, state->request,
696 REQUEST_DATA_REGEX | i);
710 * Copy substring into buffer.
713 data + rxmatch[i].rm_so,
714 rxmatch[i].rm_eo - rxmatch[i].rm_so);
715 rxbuffer[rxmatch[i].rm_eo - rxmatch[i].rm_so] = '\0';
718 * Copy substring, and add it to
721 * Note that we don't check
722 * for out of memory, which is
723 * the only error we can get...
725 p = strdup(rxbuffer);
726 request_data_add(state->request,
728 REQUEST_DATA_REGEX | i,
735 case POLICY_LEX_RX_NOT_EQUALS:
736 regcomp(®, this->rhs, REG_EXTENDED|REG_NOSUB);
737 rad_assert(data != NULL);
738 rcode = regexec(®, data,
740 rcode = (rcode != 0);
743 #endif /* HAVE_REGEX_H */
747 } /* switch over comparison operators */
748 break; /* default from first switch over compare */
751 if (this->sense) rcode = (rcode == FALSE); /* reverse sense of test */
756 switch (this->child_condition) {
760 case POLICY_LEX_L_AND:
761 if (!rcode) return rcode; /* FALSE && x == FALSE */
764 case POLICY_LEX_L_OR:
765 if (rcode) return rcode; /* TRUE && x == TRUE */
772 this = (const policy_condition_t *) this->child;
775 return 1; /* should never reach here */
780 * Evaluate an 'if' statement
782 static int evaluate_if(policy_state_t *state, const policy_item_t *item)
785 const policy_if_t *this;
787 this = (const policy_if_t *) item;
790 * evaluate_condition calls itself recursively.
791 * We should probably allocate a new state, instead.
793 rcode = evaluate_condition(state, this->condition);
794 debug_evaluate("IF condition returned %s\n",
795 rcode ? "true" : "false");
797 rcode = policy_stack_push(state, this->if_true);
798 if (!rcode) return rcode;
799 } else if (this->if_false) {
800 rcode = policy_stack_push(state, this->if_false);
801 if (!rcode) return rcode;
805 * 'if' can fail, if the block it's processing fails.
812 * Make a VALUE_PAIR from a policy_assignment_t*
814 * The assignment operator has to be '='.
816 static VALUE_PAIR *assign2vp(REQUEST *request,
817 const policy_assignment_t *assign)
820 FR_TOKEN operator = T_OP_EQ;
821 const char *value = assign->rhs;
824 if ((assign->rhs_type == POLICY_LEX_DOUBLE_QUOTED_STRING) &&
825 (strchr(assign->rhs, '%') != NULL)) {
826 radius_xlat(buffer, sizeof(buffer), assign->rhs,
832 * This is crappy.. fix it.
834 switch (assign->assign) {
835 case POLICY_LEX_ASSIGN:
839 case POLICY_LEX_SET_EQUALS:
843 case POLICY_LEX_PLUS_EQUALS:
848 fprintf(stderr, "Expected '=' for operator, not '%s' at line %d\n",
849 fr_int2str(rlm_policy_tokens,
850 assign->assign, "?"),
851 assign->item.lineno);
855 vp = pairmake(assign->lhs, value, operator);
857 fprintf(stderr, "Failed creating pair: %s %s\n", value, fr_strerror());
865 * Evaluate a 'packet .= {attrs}' statement
867 static int evaluate_attr_list(policy_state_t *state, const policy_item_t *item)
869 const policy_attributes_t *this;
870 VALUE_PAIR **vps = NULL;
871 VALUE_PAIR *vp, *head, **tail;
872 const policy_item_t *attr;
873 policy_lex_t this_how;
875 this = (const policy_attributes_t *) item;
877 switch (this->where) {
878 case POLICY_RESERVED_CONTROL:
879 vps = &(state->request->config_items);
882 case POLICY_RESERVED_REQUEST:
883 vps = &(state->request->packet->vps);
886 case POLICY_RESERVED_REPLY:
887 vps = &(state->request->reply->vps);
891 case POLICY_RESERVED_PROXY_REQUEST:
892 if (!state->request->proxy) return 0; /* FIXME: print error */
893 vps = &(state->request->proxy->vps);
896 case POLICY_RESERVED_PROXY_REPLY:
897 if (!state->request->proxy_reply) return 0; /* FIXME: print error */
898 vps = &(state->request->proxy_reply->vps);
909 for (attr = this->attributes; attr != NULL; attr = attr->next) {
910 if (attr->type != POLICY_TYPE_ASSIGNMENT) {
911 fprintf(stderr, "bad assignment in attribute list at line %d\n", attr->lineno);
916 vp = assign2vp(state->request, (const policy_assignment_t *) attr);
918 fprintf(stderr, "Failed to allocate VP\n");
926 this_how = this->how;
929 case POLICY_LEX_SET_EQUALS: /* dangerous: removes all previous things! */
934 case POLICY_LEX_AFTER_TAIL_ASSIGN:
935 pairmove(vps, &head);
939 case POLICY_LEX_ASSIGN: /* 'union' */
940 pairmove(vps, &head);
944 case POLICY_LEX_BEFORE_HEAD_ASSIGN:
945 pairmove(&head, vps);
950 case POLICY_LEX_AFTER_TAIL_EQUALS:
951 case POLICY_LEX_CONCAT_EQUALS:
955 case POLICY_LEX_BEFORE_HEAD_EQUALS:
956 pairadd(&head, *vps);
960 case POLICY_LEX_BEFORE_WHERE_EQUALS:
961 case POLICY_LEX_AFTER_WHERE_EQUALS:
962 case POLICY_LEX_BEFORE_WHERE_ASSIGN:
963 case POLICY_LEX_AFTER_WHERE_ASSIGN:
966 VALUE_PAIR *vpprev = NULL, *vpnext = NULL, *lvp;
968 for(lvp = *vps; lvp; vpprev = lvp, lvp = lvp->next) {
971 if (evaluate_condition(state, this->where_loc))
978 case POLICY_LEX_BEFORE_WHERE_EQUALS:
979 case POLICY_LEX_BEFORE_WHERE_ASSIGN:
986 default: /* always reached */
991 case POLICY_LEX_BEFORE_WHERE_EQUALS:
997 case POLICY_LEX_AFTER_WHERE_EQUALS:
1000 case POLICY_LEX_BEFORE_WHERE_ASSIGN:
1002 pairmove(&lvp, &head);
1008 case POLICY_LEX_AFTER_WHERE_ASSIGN:
1009 pairmove(&lvp, &head);
1012 default:/*never reached*/
1015 for( ; lvp && lvp->next; lvp = lvp->next);
1022 case POLICY_LEX_BEFORE_WHERE_EQUALS:
1023 this_how = POLICY_LEX_BEFORE_HEAD_EQUALS;
1025 case POLICY_LEX_AFTER_WHERE_EQUALS:
1026 this_how = POLICY_LEX_AFTER_TAIL_EQUALS;
1028 case POLICY_LEX_BEFORE_WHERE_ASSIGN:
1029 this_how = POLICY_LEX_BEFORE_HEAD_ASSIGN;
1031 case POLICY_LEX_AFTER_WHERE_ASSIGN:
1032 this_how = POLICY_LEX_AFTER_TAIL_ASSIGN;
1034 default: /*never reached*/
1042 fprintf(stderr, "HUH?\n");
1047 state->rcode = RLM_MODULE_UPDATED; /* we did stuff */
1054 * Evaluate a reference call to a module.
1056 static int evaluate_call(policy_state_t *state, const policy_item_t *item)
1059 const policy_call_t *this;
1060 const policy_named_t *policy;
1062 this = (const policy_call_t *) item;
1064 policy = rlm_policy_find(state->inst->policies, this->name);
1065 if (!policy) return 0; /* not found... */
1067 DEBUG2("rlm_policy: Evaluating policy %s", this->name);
1069 rad_assert(policy->policy->type != POLICY_TYPE_BAD);
1070 rad_assert(policy->policy->type < POLICY_TYPE_NUM_TYPES);
1073 * Push the name of the function onto the stack,
1074 * so that we can catch recursive calls.
1076 * The "pop" function will skip over it when it sees it.
1078 rcode = policy_stack_push(state, (const policy_item_t *) policy);
1084 * Push it onto the stack. Other code will take care of
1087 rcode = policy_stack_push(state, policy->policy);
1097 * Evaluate a return statement
1099 static int evaluate_return(policy_state_t *state, const policy_item_t *item)
1101 const policy_return_t *this;
1103 this = (const policy_return_t *) item;
1104 state->rcode = this->rcode;
1106 return 1; /* we succeeded */
1111 * Evaluate a module statement
1113 static int evaluate_module(policy_state_t *state, const policy_item_t *item)
1115 const policy_module_t *this;
1117 this = (const policy_module_t *) item;
1120 * Just to be paranoid. Maybe we want to loosen this
1121 * restriction in the future?
1123 if (this->component != state->component) {
1124 DEBUG2("rlm_policy: Cannot mix & match components");
1128 DEBUG2("rlm_policy: begin nested call");
1129 state->rcode = modcall(this->component, this->mc, state->request);
1130 DEBUG2("rlm_policy: end nested call");
1132 return 1; /* we succeeded */
1137 * State machine stuff.
1139 typedef int (*policy_evaluate_type_t)(policy_state_t *, const policy_item_t *);
1143 * MUST be kept in sync with policy_type_t
1145 static policy_evaluate_type_t evaluate_functions[POLICY_TYPE_NUM_TYPES] = {
1146 NULL, /* POLICY_TYPE_BAD */
1149 evaluate_assignment,
1152 NULL, /* define a named policy.. */
1160 * Evaluate a policy, keyed by name.
1162 static int policy_evaluate_name(policy_state_t *state, const char *name)
1165 const policy_item_t *this;
1166 policy_named_t mypolicy, *policy;
1168 mypolicy.name = name;
1169 policy = rbtree_finddata(state->inst->policies, &mypolicy);
1170 if (!policy) return RLM_MODULE_FAIL;
1172 DEBUG2("rlm_policy: Evaluating policy %s", name);
1174 rad_assert(policy->item.type != POLICY_TYPE_BAD);
1175 rad_assert(policy->item.type < POLICY_TYPE_NUM_TYPES);
1177 rcode = policy_stack_push(state, policy->policy);
1179 return RLM_MODULE_FAIL;
1183 * FIXME: Look for magic keywords like "return",
1184 * where the packet gets accepted/rejected/whatever
1186 while (policy_stack_pop(state, &this)) {
1187 rad_assert(this != NULL);
1188 rad_assert(this->type != POLICY_TYPE_BAD);
1189 rad_assert(this->type < POLICY_TYPE_NUM_TYPES);
1191 debug_evaluate("Evaluating at line %d\n",
1193 rcode = (*evaluate_functions[this->type])(state,
1196 return RLM_MODULE_FAIL;
1198 } /* loop until the stack is empty */
1200 return state->rcode;
1205 * Evaluate, which is pretty close to print, but we look at what
1208 int rlm_policy_evaluate(rlm_policy_t *inst, REQUEST *request, const char *name)
1211 policy_state_t *state;
1213 state = rad_malloc(sizeof(*state));
1214 memset(state, 0, sizeof(*state));
1215 state->request = request;
1217 state->rcode = RLM_MODULE_OK;
1218 state->component = fr_str2int(policy_component_names, name,
1219 RLM_COMPONENT_COUNT);
1221 rcode = policy_evaluate_name(state, name);
1225 return rcode; /* evaluated OK. */