Enable building #WITHOUT_PROXY
[freeradius.git] / src / modules / rlm_policy / evaluate.c
index ca355de..3c1a000 100644 (file)
@@ -38,50 +38,50 @@ RCSID("$Id$")
 static void policy_print(const policy_item_t *item, int indent)
 {
        if (!item) {
-               if (indent) printf("%*s", indent, " ");
-               printf("[NULL]\n");
+               if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
+               fprintf(fr_log_fp, "[NULL]\n");
                return;
        }
-       
+
        while (item) {
                switch (item->type) {
                case POLICY_TYPE_BAD:
-                       if (indent) printf("%*s", indent, " ");
-                       printf("[BAD STATEMENT]");
+                       if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
+                       fprintf(fr_log_fp, "[BAD STATEMENT]");
                        break;
-                       
+
                case POLICY_TYPE_PRINT:
-                       if (indent) printf("%*s", indent, " ");
+                       if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
                        {
                                const policy_print_t *this;
 
                                this = (const policy_print_t *) item;
-                               
+
                                if (this->rhs_type == POLICY_LEX_BARE_WORD) {
-                                       printf("print %s\n", this->rhs);
+                                       fprintf(fr_log_fp, "print %s\n", this->rhs);
                                } else {
-                                       printf("print \"%s\"\n", this->rhs);
+                                       fprintf(fr_log_fp, "print \"%s\"\n", this->rhs);
                                }
                        }
                        break;
-                       
+
                case POLICY_TYPE_ASSIGNMENT:
                        {
                                const policy_assignment_t *assign;
-                               
+
                                assign = (const policy_assignment_t *) item;
-                               if (indent) printf("%*s", indent, " ");
+                               if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
 
-                               printf("\t%s %s ", assign->lhs,
-                                      lrad_int2str(rlm_policy_tokens,
+                               fprintf(fr_log_fp, "\t%s %s ", assign->lhs,
+                                      fr_int2str(rlm_policy_tokens,
                                                    assign->assign, "?"));
                                if (assign->rhs_type == POLICY_LEX_BARE_WORD) {
-                                       printf("%s\n", assign->rhs);
+                                       fprintf(fr_log_fp, "%s\n", assign->rhs);
                                } else {
                                        /*
                                         *      FIXME: escape "
                                         */
-                                       printf("\"%s\"\n", assign->rhs);
+                                       fprintf(fr_log_fp, "\"%s\"\n", assign->rhs);
                                }
                        }
                        break;
@@ -92,61 +92,65 @@ static void policy_print(const policy_item_t *item, int indent)
 
                                condition = (const policy_condition_t *) item;
 
-                               printf("(");
+                               fprintf(fr_log_fp, "(");
+
+                               if (condition->sense) {
+                                       fprintf(fr_log_fp, "!");
+                               }
 
                                /*
                                 *      Nested conditions.
                                 */
                                if (condition->compare == POLICY_LEX_L_BRACKET) {
                                        policy_print(condition->child, indent);
-                                       printf(")");
+                                       fprintf(fr_log_fp, ")");
                                        break;
                                }
 
                                if (condition->compare == POLICY_LEX_L_NOT) {
-                                       printf("!");
+                                       fprintf(fr_log_fp, "!");
                                        policy_print(condition->child, indent);
-                                       printf(")");
+                                       fprintf(fr_log_fp, ")");
                                        break;
                                }
 
                                if (condition->compare == POLICY_LEX_CMP_TRUE) {
-                                       printf("%s)", condition->lhs);
+                                       fprintf(fr_log_fp, "%s)", condition->lhs);
                                        break;
                                }
 
                                if (condition->lhs_type == POLICY_LEX_FUNCTION) {
-                                       printf("%s()", condition->lhs);
+                                       fprintf(fr_log_fp, "%s()", condition->lhs);
                                } else {
                                        /*
                                         *      FIXME: escape ",
                                         *      and move all of this logic
                                         *      to a function.
                                         */
-                                       printf("\"%s\"", condition->lhs);
+                                       fprintf(fr_log_fp, "\"%s\"", condition->lhs);
                                }
 
                                /*
                                 *      We always print this condition.
                                 */
-                               printf(" %s ", lrad_int2str(rlm_policy_tokens,
+                               fprintf(fr_log_fp, " %s ", fr_int2str(rlm_policy_tokens,
                                                            condition->compare,
                                                            "?"));
                                if (condition->rhs_type == POLICY_LEX_BARE_WORD) {
-                                       printf("%s", condition->rhs);
+                                       fprintf(fr_log_fp, "%s", condition->rhs);
                                } else {
                                        /*
                                         *      FIXME: escape ",
                                         *      and move all of this logic
                                         *      to a function.
                                         */
-                                       printf("\"%s\"", condition->rhs);
+                                       fprintf(fr_log_fp, "\"%s\"", condition->rhs);
                                }
-                               printf(")");
-                               
+                               fprintf(fr_log_fp, ")");
+
                                if ((condition->child_condition != POLICY_LEX_BAD) &&
                                    (condition->child_condition != POLICY_LEX_BARE_WORD)) {
-                                       printf(" %s ", lrad_int2str(rlm_policy_tokens, condition->child_condition, "?"));
+                                       fprintf(fr_log_fp, " %s ", fr_int2str(rlm_policy_tokens, condition->child_condition, "?"));
                                        policy_print(condition->child, indent);
                                }
                        }
@@ -158,24 +162,24 @@ static void policy_print(const policy_item_t *item, int indent)
 
                                statement = (const policy_if_t *) item;
 
-                               if (indent) printf("%*s", indent, " ");
-                               printf("if ");
+                               if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
+                               fprintf(fr_log_fp, "if ");
                                policy_print(statement->condition, indent);
-                               printf(" {\n");
+                               fprintf(fr_log_fp, " {\n");
                                policy_print(statement->if_true, indent + 1);
-                               if (indent) printf("%*s", indent, " ");
+                               if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
                                if (statement->if_false) {
-                                       printf("} else ");
+                                       fprintf(fr_log_fp, "} else ");
                                        if (statement->if_false->type == POLICY_TYPE_ASSIGNMENT) {
-                                               printf(" { ");
+                                               fprintf(fr_log_fp, " { ");
                                                policy_print(statement->if_false, indent + 1);
-                                               if (indent) printf("%*s", indent, " ");
-                                               printf(" }");
+                                               if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
+                                               fprintf(fr_log_fp, " }");
                                        } else {
                                                policy_print(statement->if_false, indent + 1);
                                        }
                                } else {
-                                       printf("}\n");
+                                       fprintf(fr_log_fp, "}\n");
                                }
                        }
                        break;
@@ -186,15 +190,15 @@ static void policy_print(const policy_item_t *item, int indent)
 
                                this = (const policy_attributes_t *) item;
 
-                               if (indent) printf("%*s", indent, " ");
-                               printf("%s %s {\n",
-                                      lrad_int2str(policy_reserved_words,
+                               if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
+                               fprintf(fr_log_fp, "%s %s {\n",
+                                      fr_int2str(policy_reserved_words,
                                                    this->where, "?"),
-                                      lrad_int2str(rlm_policy_tokens,
+                                      fr_int2str(rlm_policy_tokens,
                                                    this->how, "?"));
                                policy_print(this->attributes, indent + 1);
-                               if (indent) printf("%*s", indent, " ");
-                               printf("}\n");
+                               if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
+                               fprintf(fr_log_fp, "}\n");
                        }
                        break;
 
@@ -203,11 +207,11 @@ static void policy_print(const policy_item_t *item, int indent)
                                const policy_named_t *this;
 
                                this = (const policy_named_t *) item;
-                               if (indent) printf("%*s", indent, " ");
-                               printf("policy %s {\n", this->name);
+                               if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
+                               fprintf(fr_log_fp, "policy %s {\n", this->name);
                                policy_print(this->policy, indent + 1);
-                               if (indent) printf("%*s", indent, " ");
-                               printf("}\n");
+                               if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
+                               fprintf(fr_log_fp, "}\n");
                        }
                        break;
 
@@ -216,8 +220,8 @@ static void policy_print(const policy_item_t *item, int indent)
                                const policy_call_t *this;
 
                                this = (const policy_call_t *) item;
-                               if (indent) printf("%*s", indent, " ");
-                               printf("call %s\n", this->name);
+                               if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
+                               fprintf(fr_log_fp, "call %s\n", this->name);
                        }
                        break;
 
@@ -226,9 +230,9 @@ static void policy_print(const policy_item_t *item, int indent)
                                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,
+                               if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
+                               fprintf(fr_log_fp, "return %s\n",
+                                      fr_int2str(policy_return_codes,
                                                    this->rcode, "???"));
                        }
                        break;
@@ -238,18 +242,18 @@ static void policy_print(const policy_item_t *item, int indent)
                                const policy_module_t *this;
 
                                this = (const policy_module_t *) item;
-                               if (indent) printf("%*s", indent, " ");
-                               printf("module %s <stuff>\n",
-                                      lrad_int2str(policy_component_names,
+                               if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
+                               fprintf(fr_log_fp, "module %s <stuff>\n",
+                                      fr_int2str(policy_component_names,
                                                    this->component, "???"));
                        }
                        break;
 
                default:
-                       if (indent) printf("%*s", indent, " ");
-                       printf("[HUH?]\n");
+                       if (indent) fprintf(fr_log_fp, "%*s", indent, " ");
+                       fprintf(fr_log_fp, "[HUH?]\n");
                        break;
-                       
+
                }
 
                item = item->next;
@@ -259,9 +263,10 @@ static void policy_print(const policy_item_t *item, int indent)
 
 void rlm_policy_print(const policy_item_t *item)
 {
-       printf("----------------------------------------------------------\n");
+       if (!fr_log_fp) return;
+
+       fprintf(fr_log_fp, "# rlm_policy \n");
        policy_print(item, 0);
-       printf("----------------------------------------------------------\n");
 }
 
 /*
@@ -386,16 +391,19 @@ static int evaluate_print(policy_state_t *state, const policy_item_t *item)
 {
        const policy_print_t *this;
 
+       if (!fr_log_fp) return 1;
+
        this = (const policy_print_t *) item;
 
        if (this->rhs_type == POLICY_LEX_BARE_WORD) {
-               printf("%s\n", this->rhs);
+               fprintf(fr_log_fp, "%s\n", this->rhs);
        } else {
                char buffer[1024];
 
                radius_xlat(buffer, sizeof(buffer), this->rhs,
                            state->request, NULL);
-               printf("%s", buffer);
+               fprintf(fr_log_fp, "%s", buffer);
+               if (!strchr(buffer, '\n')) fprintf(fr_log_fp, "\n");
        }
 
        /*
@@ -430,6 +438,7 @@ static VALUE_PAIR *find_vp(REQUEST *request, const char *name)
        } else if (strncasecmp(name, "reply:", 6) == 0) {
                p += 6;
                vps = request->reply->vps;
+#ifdef WITH_PROXY
        } else if (strncasecmp(name, "proxy-request:", 14) == 0) {
                p += 14;
                if (request->proxy) {
@@ -440,6 +449,7 @@ static VALUE_PAIR *find_vp(REQUEST *request, const char *name)
                if (request->proxy_reply) {
                        vps = request->proxy_reply->vps;
                }
+#endif
        } else if (strncasecmp(name, "control:", 8) == 0) {
                p += 8;
                vps = request->config_items;
@@ -455,7 +465,7 @@ static VALUE_PAIR *find_vp(REQUEST *request, const char *name)
                return NULL;    /* no such attribute */
        }
 
-       return pairfind(vps, dattr->attr);
+       return pairfind(vps, dattr->attr, dattr->vendor);
 }
 
 
@@ -464,7 +474,7 @@ static VALUE_PAIR *find_vp(REQUEST *request, const char *name)
  *
  *     Not really used much...
  */
-static int evaluate_assignment(policy_state_t *state, const policy_item_t *item)
+static int evaluate_assignment(UNUSED policy_state_t *state, const policy_item_t *item)
 {
        const policy_assignment_t *this;
 #if 0
@@ -519,7 +529,7 @@ static int evaluate_condition(policy_state_t *state, const policy_item_t *item)
                         *      evaluate all of it...
                         */
                        rcode = policy_evaluate_name(state, this->lhs);
-                       data = lrad_int2str(policy_return_codes, rcode, "???");
+                       data = fr_int2str(policy_return_codes, rcode, "???");
                        strlcpy(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,
@@ -528,7 +538,7 @@ static int evaluate_condition(policy_state_t *state, const policy_item_t *item)
                        }
                }
        }
-       
+
        switch (this->compare) {
        case POLICY_LEX_L_BRACKET: /* nested brackets are a special case */
                rcode = evaluate_condition(state, this->child);
@@ -579,10 +589,13 @@ static int evaluate_condition(policy_state_t *state, const policy_item_t *item)
                        vp = find_vp(state->request, this->lhs);
 
                        /*
-                        *      A op B always returns FALSE if A doesn't
+                        *      A op B is FALSE if A doesn't
                         *      exist.
                         */
-                       if (!vp) return FALSE; /* not in the request */
+                       if (!vp) {
+                               rcode = FALSE;
+                               break;
+                       }
 
                        /*
                         *      FIXME: Move sanity checks to
@@ -591,6 +604,7 @@ static int evaluate_condition(policy_state_t *state, const policy_item_t *item)
                         */
                        vp_prints_value(buffer, sizeof(buffer), vp, 0);
                        myvp = pairmake(vp->name, this->rhs, T_OP_EQ);
+                       if (!myvp) return FALSE; /* memory failure */
                        data = buffer;
 
                        /*
@@ -605,56 +619,57 @@ static int evaluate_condition(policy_state_t *state, const policy_item_t *item)
                         *      error codes than "comparison is less
                         *      than, equal to, or greater than zero".
                         */
-                       compare = simplepaircmp(state->request,
-                                               vp, myvp);
+                       compare = radius_callback_compare(state->request,
+                                                         vp, myvp, NULL, NULL);
                        pairfree(&myvp);
-                       
+
                } else {
                        /*
                         *      FIXME: Do something for RHS type?
                         */
-                       printf("CMP %s %s\n", lhs_buffer, this->rhs);
+                       fr_printf_log("CMP %s %s\n", lhs_buffer, this->rhs);
                        compare = strcmp(lhs_buffer, this->rhs);
                }
 
                debug_evaluate("CONDITION COMPARE %d\n", compare);
-               
+
                switch (this->compare) {
                case POLICY_LEX_CMP_EQUALS:
                        rcode = (compare == 0);
                        break;
-                       
+
                case POLICY_LEX_CMP_NOT_EQUALS:
                        rcode = (compare != 0);
                        break;
-                       
+
                case POLICY_LEX_LT:
                        rcode = (compare < 0);
                        break;
-                       
+
                case POLICY_LEX_GT:
                        rcode = (compare > 0);
                        break;
-                       
+
                case POLICY_LEX_LE:
                        rcode =(compare <= 0);
                        break;
-                       
+
                case POLICY_LEX_GE:
                        rcode = (compare >= 0);
                        break;
-                       
+
 #ifdef HAVE_REGEX_H
                case POLICY_LEX_RX_EQUALS:
                { /* FIXME: copied from src/main/valuepair.c */
                        int i;
                        regmatch_t rxmatch[REQUEST_MAX_REGEX + 1];
-                       
+
                        /*
                         *      Include substring matches.
                         */
                        if (regcomp(&reg, this->rhs,
                                    REG_EXTENDED) != 0) {
+                               /* FIXME: print error */
                                return FALSE;
                        }
                        rad_assert(data != NULL);
@@ -663,14 +678,14 @@ static int evaluate_condition(policy_state_t *state, const policy_item_t *item)
                                        rxmatch, 0);
                        rcode = (rcode == 0);
                        regfree(&reg);
-                       
+
                        /*
                         *      Add %{0}, %{1}, etc.
                         */
                        for (i = 0; i <= REQUEST_MAX_REGEX; i++) {
                                char *p;
                                char rxbuffer[256];
-                               
+
                                /*
                                 *      Didn't match: delete old
                                 *      match, if it existed.
@@ -683,14 +698,14 @@ static int evaluate_condition(policy_state_t *state, const policy_item_t *item)
                                                free(p);
                                                continue;
                                        }
-                                               
+
                                        /*
                                         *      No previous match
                                         *      to delete, stop.
                                         */
                                        break;
                                }
-                               
+
                                /*
                                 *      Copy substring into buffer.
                                 */
@@ -698,7 +713,7 @@ static int evaluate_condition(policy_state_t *state, const policy_item_t *item)
                                       data + rxmatch[i].rm_so,
                                       rxmatch[i].rm_eo - rxmatch[i].rm_so);
                                rxbuffer[rxmatch[i].rm_eo - rxmatch[i].rm_so] = '\0';
-                               
+
                                /*
                                 *      Copy substring, and add it to
                                 *      the request.
@@ -713,10 +728,10 @@ static int evaluate_condition(policy_state_t *state, const policy_item_t *item)
                                                 REQUEST_DATA_REGEX | i,
                                                 p, free);
                        }
-                       
+
                }
                break;
-               
+
                case POLICY_LEX_RX_NOT_EQUALS:
                        regcomp(&reg, this->rhs, REG_EXTENDED|REG_NOSUB);
                        rad_assert(data != NULL);
@@ -733,6 +748,8 @@ static int evaluate_condition(policy_state_t *state, const policy_item_t *item)
                break;          /* default from first switch over compare */
        }
 
+       if (this->sense) rcode = (rcode == FALSE); /* reverse sense of test */
+
        /*
         *      No trailing &&, ||
         */
@@ -800,7 +817,7 @@ static VALUE_PAIR *assign2vp(REQUEST *request,
                             const policy_assignment_t *assign)
 {
        VALUE_PAIR *vp;
-       LRAD_TOKEN operator = T_OP_EQ;
+       FR_TOKEN operator = T_OP_EQ;
        const char *value = assign->rhs;
        char buffer[2048];
 
@@ -822,22 +839,22 @@ static VALUE_PAIR *assign2vp(REQUEST *request,
        case POLICY_LEX_SET_EQUALS:
                operator = T_OP_SET;
                break;
-       
+
        case POLICY_LEX_PLUS_EQUALS:
                operator = T_OP_ADD;
                break;
-       
+
        default:
                fprintf(stderr, "Expected '=' for operator, not '%s' at line %d\n",
-                       lrad_int2str(rlm_policy_tokens,
+                       fr_int2str(rlm_policy_tokens,
                                     assign->assign, "?"),
                        assign->item.lineno);
                return NULL;
        }
-       
+
        vp = pairmake(assign->lhs, value, operator);
        if (!vp) {
-               fprintf(stderr, "SHIT: %s %s\n", value, librad_errstr);
+               fprintf(stderr, "Failed creating pair: %s %s\n", value, fr_strerror());
        }
 
        return vp;
@@ -853,6 +870,7 @@ static int evaluate_attr_list(policy_state_t *state, const policy_item_t *item)
        VALUE_PAIR **vps = NULL;
        VALUE_PAIR *vp, *head, **tail;
        const policy_item_t *attr;
+       policy_lex_t this_how;
 
        this = (const policy_attributes_t *) item;
 
@@ -869,6 +887,7 @@ static int evaluate_attr_list(policy_state_t *state, const policy_item_t *item)
                vps = &(state->request->reply->vps);
                break;
 
+#ifdef WITH_PROXY
        case POLICY_RESERVED_PROXY_REQUEST:
                if (!state->request->proxy) return 0; /* FIXME: print error */
                vps = &(state->request->proxy->vps);
@@ -878,6 +897,7 @@ static int evaluate_attr_list(policy_state_t *state, const policy_item_t *item)
                if (!state->request->proxy_reply) return 0; /* FIXME: print error */
                vps = &(state->request->proxy_reply->vps);
                break;
+#endif
 
        default:
                return 0;
@@ -903,21 +923,121 @@ static int evaluate_attr_list(policy_state_t *state, const policy_item_t *item)
                tail = &(vp->next);
        }
 
-       switch (this->how) {
+       this_how = this->how;
+ retry_how:
+       switch (this_how) {
        case POLICY_LEX_SET_EQUALS: /* dangerous: removes all previous things! */
                pairfree(vps);
                *vps = head;
                break;
 
+       case POLICY_LEX_AFTER_TAIL_ASSIGN:
+               pairmove(vps, &head);
+               pairfree(&head);
+               break;
+
        case POLICY_LEX_ASSIGN: /* 'union' */
                pairmove(vps, &head);
                pairfree(&head);
                break;
 
+       case POLICY_LEX_BEFORE_HEAD_ASSIGN:
+               pairmove(&head, vps);
+               pairfree(vps);
+               *vps = head;
+               break;
+
+       case POLICY_LEX_AFTER_TAIL_EQUALS:
        case POLICY_LEX_CONCAT_EQUALS:
                pairadd(vps, head);
                break;
 
+       case POLICY_LEX_BEFORE_HEAD_EQUALS:
+               pairadd(&head, *vps);
+               *vps = head;
+               break;
+
+       case POLICY_LEX_BEFORE_WHERE_EQUALS:
+       case POLICY_LEX_AFTER_WHERE_EQUALS:
+       case POLICY_LEX_BEFORE_WHERE_ASSIGN:
+       case POLICY_LEX_AFTER_WHERE_ASSIGN:
+               /* find location*/
+               {
+                       VALUE_PAIR *vpprev = NULL, *vpnext = NULL, *lvp;
+
+                       for(lvp = *vps; lvp; vpprev = lvp, lvp = lvp->next) {
+                               vpnext = lvp->next;
+                               lvp->next = NULL;
+                               if (evaluate_condition(state, this->where_loc))
+                                       break;
+                               lvp->next = vpnext;
+                       }
+
+                       if (lvp) { 
+                               switch(this_how) {
+                               case POLICY_LEX_BEFORE_WHERE_EQUALS:
+                               case POLICY_LEX_BEFORE_WHERE_ASSIGN:
+                                       if (vpprev) {
+                                               lvp->next = vpnext;
+                                               vpnext = lvp;
+                                               vpprev->next = NULL;
+                                               lvp = vpprev;
+                                       }
+                               default: /* always reached */
+                                       break;
+                               }
+
+                               switch(this_how) {
+                               case POLICY_LEX_BEFORE_WHERE_EQUALS:
+                                       if (vpprev) 
+                                               pairadd(&lvp, head);
+                                       else
+                                               *vps = lvp = head;
+                                       break;
+                               case POLICY_LEX_AFTER_WHERE_EQUALS:
+                                       pairadd(&lvp, head);
+                                       break;
+                               case POLICY_LEX_BEFORE_WHERE_ASSIGN:
+                                       if (vpprev) {
+                                               pairmove(&lvp, &head);
+                                               pairfree(&head);
+                                       }
+                                       else
+                                               *vps = lvp = head;
+                                       break;
+                               case POLICY_LEX_AFTER_WHERE_ASSIGN:
+                                       pairmove(&lvp, &head);
+                                       pairfree(&head);
+                                       break;
+                               default:/*never reached*/
+                                       break;
+                               }       
+                               for( ; lvp && lvp->next; lvp = lvp->next);
+                               if (lvp)
+                                       lvp->next = vpnext;
+                               break;
+                       }
+
+                       switch(this_how) {
+                               case POLICY_LEX_BEFORE_WHERE_EQUALS:
+                                       this_how = POLICY_LEX_BEFORE_HEAD_EQUALS;
+                                       break;
+                               case POLICY_LEX_AFTER_WHERE_EQUALS:
+                                       this_how = POLICY_LEX_AFTER_TAIL_EQUALS;
+                                       break;
+                               case POLICY_LEX_BEFORE_WHERE_ASSIGN:
+                                       this_how = POLICY_LEX_BEFORE_HEAD_ASSIGN;
+                                       break;
+                               case POLICY_LEX_AFTER_WHERE_ASSIGN:
+                                       this_how = POLICY_LEX_AFTER_TAIL_ASSIGN;
+                                       break;
+                               default: /*never reached*/
+                                       break;
+                       }
+                       goto retry_how; 
+               }
+               /* FALL-THROUGH */
+
        default:
                fprintf(stderr, "HUH?\n");
                pairfree(&head);
@@ -943,9 +1063,9 @@ static int evaluate_call(policy_state_t *state, const policy_item_t *item)
 
        policy = rlm_policy_find(state->inst->policies, this->name);
        if (!policy) return 0;  /* not found... */
-       
+
        DEBUG2("rlm_policy: Evaluating policy %s", this->name);
-       
+
        rad_assert(policy->policy->type != POLICY_TYPE_BAD);
        rad_assert(policy->policy->type < POLICY_TYPE_NUM_TYPES);
 
@@ -982,7 +1102,7 @@ static int evaluate_return(policy_state_t *state, const policy_item_t *item)
 
        this = (const policy_return_t *) item;
        state->rcode = this->rcode;
-       
+
        return 1;               /* we succeeded */
 }
 
@@ -1008,7 +1128,7 @@ static int evaluate_module(policy_state_t *state, const policy_item_t *item)
        DEBUG2("rlm_policy: begin nested call");
        state->rcode = modcall(this->component, this->mc, state->request);
        DEBUG2("rlm_policy: end nested call");
-       
+
        return 1;               /* we succeeded */
 }
 
@@ -1044,16 +1164,16 @@ static int policy_evaluate_name(policy_state_t *state, const char *name)
        int rcode;
        const policy_item_t *this;
        policy_named_t mypolicy, *policy;
-       
+
        mypolicy.name = name;
        policy = rbtree_finddata(state->inst->policies, &mypolicy);
        if (!policy) return RLM_MODULE_FAIL;
-       
+
        DEBUG2("rlm_policy: Evaluating policy %s", name);
-       
+
        rad_assert(policy->item.type != POLICY_TYPE_BAD);
        rad_assert(policy->item.type < POLICY_TYPE_NUM_TYPES);
-       
+
        rcode = policy_stack_push(state, policy->policy);
        if (!rcode) {
                return RLM_MODULE_FAIL;
@@ -1067,7 +1187,7 @@ static int policy_evaluate_name(policy_state_t *state, const char *name)
                rad_assert(this != NULL);
                rad_assert(this->type != POLICY_TYPE_BAD);
                rad_assert(this->type < POLICY_TYPE_NUM_TYPES);
-               
+
                debug_evaluate("Evaluating at line %d\n",
                               this->lineno);
                rcode = (*evaluate_functions[this->type])(state,
@@ -1095,7 +1215,7 @@ int rlm_policy_evaluate(rlm_policy_t *inst, REQUEST *request, const char *name)
        state->request = request;
        state->inst = inst;
        state->rcode = RLM_MODULE_OK;
-       state->component = lrad_str2int(policy_component_names, name,
+       state->component = fr_str2int(policy_component_names, name,
                                        RLM_COMPONENT_COUNT);
 
        rcode = policy_evaluate_name(state, name);