Merge pull request #879 from mcnewton/manupdate
[freeradius.git] / src / main / modcall.c
1 /*
2  * @name modcall.c
3  *
4  * Version:     $Id$
5  *
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.
10  *
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.
15  *
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
19  *
20  * Copyright 2000,2006  The FreeRADIUS server project
21  */
22
23 RCSID("$Id$")
24
25 #include <freeradius-devel/radiusd.h>
26 #include <freeradius-devel/modpriv.h>
27 #include <freeradius-devel/modcall.h>
28 #include <freeradius-devel/parser.h>
29 #include <freeradius-devel/rad_assert.h>
30
31
32 /* mutually-recursive static functions need a prototype up front */
33 static modcallable *do_compile_modgroup(modcallable *,
34                                         rlm_components_t, CONF_SECTION *,
35                                         int, int, int);
36
37 /* Actions may be a positive integer (the highest one returned in the group
38  * will be returned), or the keyword "return", represented here by
39  * MOD_ACTION_RETURN, to cause an immediate return.
40  * There's also the keyword "reject", represented here by MOD_ACTION_REJECT
41  * to cause an immediate reject. */
42 #define MOD_ACTION_RETURN  (-1)
43 #define MOD_ACTION_REJECT  (-2)
44
45 /* Here are our basic types: modcallable, modgroup, and modsingle. For an
46  * explanation of what they are all about, see doc/configurable_failover.rst */
47 struct modcallable {
48         modcallable *parent;
49         struct modcallable *next;
50         char const *name;
51         char const *debug_name;
52         enum { MOD_SINGLE = 1, MOD_GROUP, MOD_LOAD_BALANCE, MOD_REDUNDANT_LOAD_BALANCE,
53 #ifdef WITH_UNLANG
54                MOD_IF, MOD_ELSE, MOD_ELSIF, MOD_UPDATE, MOD_SWITCH, MOD_CASE,
55                MOD_FOREACH, MOD_BREAK, MOD_RETURN,
56 #endif
57                MOD_POLICY, MOD_REFERENCE, MOD_XLAT } type;
58         rlm_components_t method;
59         int actions[RLM_MODULE_NUMCODES];
60 };
61
62 #define MOD_LOG_OPEN_BRACE RDEBUG2("%s {", c->debug_name)
63
64 #define MOD_LOG_CLOSE_BRACE RDEBUG2("} # %s = %s", c->debug_name, fr_int2str(mod_rcode_table, result, "<invalid>"))
65
66 typedef struct {
67         modcallable             mc;             /* self */
68         enum {
69                 GROUPTYPE_SIMPLE = 0,
70                 GROUPTYPE_REDUNDANT,
71                 GROUPTYPE_APPEND,
72                 GROUPTYPE_COUNT
73         } grouptype;                            /* after mc */
74         modcallable             *children;
75         modcallable             *tail;          /* of the children list */
76         CONF_SECTION            *cs;
77         value_pair_map_t        *map;           /* update */
78         value_pair_tmpl_t       *vpt;           /* switch */
79         fr_cond_t               *cond;          /* if/elsif */
80         bool                    done_pass2;
81 } modgroup;
82
83 typedef struct {
84         modcallable mc;
85         module_instance_t *modinst;
86 } modsingle;
87
88 typedef struct {
89         modcallable mc;
90         char const *ref_name;
91         CONF_SECTION *ref_cs;
92 } modref;
93
94 typedef struct {
95         modcallable mc;
96         int exec;
97         char *xlat_name;
98 } modxlat;
99
100 /* Simple conversions: modsingle and modgroup are subclasses of modcallable,
101  * so we often want to go back and forth between them. */
102 static modsingle *mod_callabletosingle(modcallable *p)
103 {
104         rad_assert(p->type==MOD_SINGLE);
105         return (modsingle *)p;
106 }
107 static modgroup *mod_callabletogroup(modcallable *p)
108 {
109         rad_assert((p->type > MOD_SINGLE) && (p->type <= MOD_POLICY));
110
111         return (modgroup *)p;
112 }
113 static modcallable *mod_singletocallable(modsingle *p)
114 {
115         return (modcallable *)p;
116 }
117 static modcallable *mod_grouptocallable(modgroup *p)
118 {
119         return (modcallable *)p;
120 }
121
122 static modref *mod_callabletoref(modcallable *p)
123 {
124         rad_assert(p->type==MOD_REFERENCE);
125         return (modref *)p;
126 }
127 static modcallable *mod_reftocallable(modref *p)
128 {
129         return (modcallable *)p;
130 }
131
132 static modxlat *mod_callabletoxlat(modcallable *p)
133 {
134         rad_assert(p->type==MOD_XLAT);
135         return (modxlat *)p;
136 }
137 static modcallable *mod_xlattocallable(modxlat *p)
138 {
139         return (modcallable *)p;
140 }
141
142 /* modgroups are grown by adding a modcallable to the end */
143 static void add_child(modgroup *g, modcallable *c)
144 {
145         if (!c) return;
146
147         (void) talloc_steal(g, c);
148
149         if (!g->children) {
150                 g->children = g->tail = c;
151         } else {
152                 rad_assert(g->tail->next == NULL);
153                 g->tail->next = c;
154                 g->tail = c;
155         }
156
157         c->parent = mod_grouptocallable(g);
158 }
159
160 /* Here's where we recognize all of our keywords: first the rcodes, then the
161  * actions */
162 const FR_NAME_NUMBER mod_rcode_table[] = {
163         { "reject",     RLM_MODULE_REJECT       },
164         { "fail",       RLM_MODULE_FAIL  },
165         { "ok",         RLM_MODULE_OK      },
166         { "handled",    RLM_MODULE_HANDLED      },
167         { "invalid",    RLM_MODULE_INVALID      },
168         { "userlock",   RLM_MODULE_USERLOCK     },
169         { "notfound",   RLM_MODULE_NOTFOUND     },
170         { "noop",       RLM_MODULE_NOOP  },
171         { "updated",    RLM_MODULE_UPDATED      },
172         { NULL, 0 }
173 };
174
175
176 /*
177  *      Compile action && rcode for later use.
178  */
179 static int compile_action(modcallable *c, CONF_PAIR *cp)
180 {
181         int action;
182         char const *attr, *value;
183
184         attr = cf_pair_attr(cp);
185         value = cf_pair_value(cp);
186         if (!value) return 0;
187
188         if (!strcasecmp(value, "return"))
189                 action = MOD_ACTION_RETURN;
190
191         else if (!strcasecmp(value, "break"))
192                 action = MOD_ACTION_RETURN;
193
194         else if (!strcasecmp(value, "reject"))
195                 action = MOD_ACTION_REJECT;
196
197         else if (strspn(value, "0123456789")==strlen(value)) {
198                 action = atoi(value);
199
200                 /*
201                  *      Don't allow priority zero, for future use.
202                  */
203                 if (action == 0) return 0;
204         } else {
205                 cf_log_err_cp(cp, "Unknown action '%s'.\n",
206                            value);
207                 return 0;
208         }
209
210         if (strcasecmp(attr, "default") != 0) {
211                 int rcode;
212
213                 rcode = fr_str2int(mod_rcode_table, attr, -1);
214                 if (rcode < 0) {
215                         cf_log_err_cp(cp,
216                                    "Unknown module rcode '%s'.\n",
217                                    attr);
218                         return 0;
219                 }
220                 c->actions[rcode] = action;
221
222         } else {                /* set all unset values to the default */
223                 int i;
224
225                 for (i = 0; i < RLM_MODULE_NUMCODES; i++) {
226                         if (!c->actions[i]) c->actions[i] = action;
227                 }
228         }
229
230         return 1;
231 }
232
233 /* Some short names for debugging output */
234 static char const * const comp2str[] = {
235         "authenticate",
236         "authorize",
237         "preacct",
238         "accounting",
239         "session",
240         "pre-proxy",
241         "post-proxy",
242         "post-auth"
243 #ifdef WITH_COA
244         ,
245         "recv-coa",
246         "send-coa"
247 #endif
248 };
249
250 #ifdef HAVE_PTHREAD_H
251 /*
252  *      Lock the mutex for the module
253  */
254 static void safe_lock(module_instance_t *instance)
255 {
256         if (instance->mutex)
257                 pthread_mutex_lock(instance->mutex);
258 }
259
260 /*
261  *      Unlock the mutex for the module
262  */
263 static void safe_unlock(module_instance_t *instance)
264 {
265         if (instance->mutex)
266                 pthread_mutex_unlock(instance->mutex);
267 }
268 #else
269 /*
270  *      No threads: these functions become NULL's.
271  */
272 #define safe_lock(foo)
273 #define safe_unlock(foo)
274 #endif
275
276 static rlm_rcode_t CC_HINT(nonnull) call_modsingle(rlm_components_t component, modsingle *sp, REQUEST *request)
277 {
278         int blocked;
279         int indent = request->log.indent;
280
281         /*
282          *      If the request should stop, refuse to do anything.
283          */
284         blocked = (request->master_state == REQUEST_STOP_PROCESSING);
285         if (blocked) return RLM_MODULE_NOOP;
286
287         RDEBUG3("modsingle[%s]: calling %s (%s) for request %d",
288                 comp2str[component], sp->modinst->name,
289                 sp->modinst->entry->name, request->number);
290         request->log.indent = 0;
291
292         if (sp->modinst->force) {
293                 request->rcode = sp->modinst->code;
294                 goto fail;
295         }
296
297         /*
298          *      For logging unresponsive children.
299          */
300         request->module = sp->modinst->name;
301
302         safe_lock(sp->modinst);
303         request->rcode = sp->modinst->entry->module->methods[component](sp->modinst->insthandle, request);
304         safe_unlock(sp->modinst);
305
306         request->module = "";
307
308         /*
309          *      Wasn't blocked, and now is.  Complain!
310          */
311         blocked = (request->master_state == REQUEST_STOP_PROCESSING);
312         if (blocked) {
313                 RWARN("Module %s became unblocked for request %u", sp->modinst->entry->name, request->number);
314         }
315
316  fail:
317         request->log.indent = indent;
318         RDEBUG3("modsingle[%s]: returned from %s (%s) for request %d",
319                comp2str[component], sp->modinst->name,
320                sp->modinst->entry->name, request->number);
321
322         return request->rcode;
323 }
324
325 static int default_component_results[RLM_COMPONENT_COUNT] = {
326         RLM_MODULE_REJECT,      /* AUTH */
327         RLM_MODULE_NOTFOUND,    /* AUTZ */
328         RLM_MODULE_NOOP,        /* PREACCT */
329         RLM_MODULE_NOOP,        /* ACCT */
330         RLM_MODULE_FAIL,        /* SESS */
331         RLM_MODULE_NOOP,        /* PRE_PROXY */
332         RLM_MODULE_NOOP,        /* POST_PROXY */
333         RLM_MODULE_NOOP         /* POST_AUTH */
334 #ifdef WITH_COA
335         ,
336         RLM_MODULE_NOOP,        /* RECV_COA_TYPE */
337         RLM_MODULE_NOOP         /* SEND_COA_TYPE */
338 #endif
339 };
340
341
342 extern char const *unlang_keyword[];
343
344 char const *unlang_keyword[] = {
345         "",
346         "single",
347         "group",
348         "load-balance group",
349         "redundant-load-balance group",
350 #ifdef WITH_UNLANG
351         "if",
352         "else",
353         "elsif",
354         "update",
355         "switch",
356         "case",
357         "foreach",
358         "break",
359         "return",
360 #endif
361         "policy",
362         "reference",
363         "xlat",
364         NULL
365 };
366
367 static char const modcall_spaces[] = "                                                                ";
368
369 #define MODCALL_STACK_MAX (32)
370
371 /*
372  *      Don't call the modules recursively.  Instead, do them
373  *      iteratively, and manage the call stack ourselves.
374  */
375 typedef struct modcall_stack_entry_t {
376         rlm_rcode_t result;
377         int priority;
378         int unwind;             /* unwind to this one if it exists */
379         modcallable *c;
380 } modcall_stack_entry_t;
381
382
383 static bool modcall_recurse(REQUEST *request, rlm_components_t component, int depth,
384                             modcall_stack_entry_t *entry);
385
386 /*
387  *      Call a child of a block.
388  */
389 static void modcall_child(REQUEST *request, rlm_components_t component, int depth,
390                           modcall_stack_entry_t *entry, modcallable *c,
391                           rlm_rcode_t *result)
392 {
393         modcall_stack_entry_t *next;
394
395         if (depth >= MODCALL_STACK_MAX) {
396                 ERROR("Internal sanity check failed: module stack is too deep");
397                 fr_exit(1);
398         }
399
400         /*
401          *      Initialize the childs stack frame.
402          */
403         next = entry + 1;
404         next->c = c;
405         next->result = entry->result;
406         next->priority = 0;
407         next->unwind = 0;
408
409         if (!modcall_recurse(request, component,
410                              depth, next)) {
411                 *result = RLM_MODULE_FAIL;
412                  return;
413         }
414
415         /*
416          *      Unwind back up the stack
417          */
418         if (next->unwind != 0) {
419                 entry->unwind = next->unwind;
420         }
421
422         *result = next->result;
423
424         return;
425 }
426
427
428 /*
429  *      Interpret the various types of blocks.
430  */
431 static bool modcall_recurse(REQUEST *request, rlm_components_t component, int depth,
432                             modcall_stack_entry_t *entry)
433 {
434         bool if_taken, was_if;
435         modcallable *c;
436         int priority;
437         rlm_rcode_t result;
438
439         was_if = if_taken = false;
440         result = RLM_MODULE_UNKNOWN;
441         RINDENT();
442
443 redo:
444         priority = -1;
445         c = entry->c;
446
447         /*
448          *      Nothing more to do.  Return the code and priority
449          *      which was set by the caller.
450          */
451         if (!c) goto finish;
452
453         /*
454          *      We've been asked to stop.  Do so.
455          */
456         if ((request->master_state == REQUEST_STOP_PROCESSING) ||
457             (request->parent &&
458              (request->parent->master_state == REQUEST_STOP_PROCESSING))) {
459                 entry->result = RLM_MODULE_FAIL;
460                 entry->priority = 9999;
461                 goto finish;
462         }
463
464 #ifdef WITH_UNLANG
465         /*
466          *      Handle "if" conditions.
467          */
468         if (c->type == MOD_IF) {
469                 int condition;
470                 modgroup *g;
471
472         mod_if:
473                 g = mod_callabletogroup(c);
474                 rad_assert(g->cond != NULL);
475
476                 RDEBUG2("%s %s{", unlang_keyword[c->type], c->name);
477
478                 condition = radius_evaluate_cond(request, result, 0, g->cond);
479                 if (condition < 0) {
480                         condition = false;
481                         REDEBUG("Failed retrieving values required to evaluate condition");
482                 } else {
483                         RDEBUG2("%s %s -> %s",
484                                 unlang_keyword[c->type],
485                                 c->name, condition ? "TRUE" : "FALSE");
486                 }
487
488                 /*
489                  *      Didn't pass.  Remember that.
490                  */
491                 if (!condition) {
492                         was_if = true;
493                         if_taken = false;
494                         goto next_sibling;
495                 }
496
497                 /*
498                  *      We took the "if".  Go recurse into its' children.
499                  */
500                 was_if = true;
501                 if_taken = true;
502                 goto do_children;
503         } /* MOD_IF */
504
505         /*
506          *      "else" if the previous "if" was taken.
507          *      "if" if the previous if wasn't taken.
508          */
509         if (c->type == MOD_ELSIF) {
510                 if (!was_if) goto elsif_error;
511
512                 /*
513                  *      Like MOD_ELSE, but allow for a later "else"
514                  */
515                 if (if_taken) {
516                         RDEBUG2("... skipping %s for request %d: Preceding \"if\" was taken",
517                                 unlang_keyword[c->type], request->number);
518                         was_if = true;
519                         if_taken = true;
520                         goto next_sibling;
521                 }
522
523                 /*
524                  *      Check the "if" condition.
525                  */
526                 goto mod_if;
527         } /* MOD_ELSIF */
528
529         /*
530          *      "else" for a preceding "if".
531          */
532         if (c->type == MOD_ELSE) {
533                 if (!was_if) { /* error */
534                 elsif_error:
535                         RDEBUG2("... skipping %s for request %d: No preceding \"if\"",
536                                 unlang_keyword[c->type], request->number);
537                         goto next_sibling;
538                 }
539
540                 if (if_taken) {
541                         RDEBUG2("... skipping %s for request %d: Preceding \"if\" was taken",
542                                 unlang_keyword[c->type], request->number);
543                         was_if = false;
544                         if_taken = false;
545                         goto next_sibling;
546                 }
547
548                 /*
549                  *      We need to process it.  Go do that.
550                  */
551                 was_if = false;
552                 if_taken = false;
553                 goto do_children;
554         } /* MOD_ELSE */
555
556         /*
557          *      We're no longer processing if/else/elsif.  Reset the
558          *      trackers for those conditions.
559          */
560         was_if = false;
561         if_taken = false;
562 #endif  /* WITH_UNLANG */
563
564         if (c->type == MOD_SINGLE) {
565                 modsingle *sp;
566
567                 /*
568                  *      Process a stand-alone child, and fall through
569                  *      to dealing with it's parent.
570                  */
571                 sp = mod_callabletosingle(c);
572
573                 result = call_modsingle(c->method, sp, request);
574                 RDEBUG2("[%s] = %s", c->name ? c->name : "",
575                         fr_int2str(mod_rcode_table, result, "<invalid>"));
576                 goto calculate_result;
577         } /* MOD_SINGLE */
578
579 #ifdef WITH_UNLANG
580         /*
581          *      Update attribute(s)
582          */
583         if (c->type == MOD_UPDATE) {
584                 int rcode;
585                 modgroup *g = mod_callabletogroup(c);
586                 value_pair_map_t *map;
587
588                 MOD_LOG_OPEN_BRACE;
589                 RINDENT();
590                 for (map = g->map; map != NULL; map = map->next) {
591                         rcode = map_to_request(request, map, map_to_vp, NULL);
592                         if (rcode < 0) {
593                                 result = (rcode == -2) ? RLM_MODULE_INVALID : RLM_MODULE_FAIL;
594                                 REXDENT();
595                                 MOD_LOG_CLOSE_BRACE;
596                                 goto calculate_result;
597                         }
598                 }
599                 REXDENT();
600                 result = RLM_MODULE_NOOP;
601                 MOD_LOG_CLOSE_BRACE;
602                 goto calculate_result;
603         } /* MOD_IF */
604
605         /*
606          *      Loop over a set of attributes.
607          */
608         if (c->type == MOD_FOREACH) {
609                 int i, foreach_depth = -1;
610                 VALUE_PAIR *vps, *vp;
611                 modcall_stack_entry_t *next = NULL;
612                 vp_cursor_t copy;
613                 modgroup *g = mod_callabletogroup(c);
614
615                 if (depth >= MODCALL_STACK_MAX) {
616                         ERROR("Internal sanity check failed: module stack is too deep");
617                         fr_exit(1);
618                 }
619
620                 /*
621                  *      Figure out how deep we are in nesting by looking at request_data
622                  *      stored previously.
623                  */
624                 for (i = 0; i < 8; i++) {
625                         if (!request_data_reference(request, (void *)radius_get_vp, i)) {
626                                 foreach_depth = i;
627                                 break;
628                         }
629                 }
630
631                 if (foreach_depth < 0) {
632                         REDEBUG("foreach Nesting too deep!");
633                         result = RLM_MODULE_FAIL;
634                         goto calculate_result;
635                 }
636
637                 /*
638                  *      Copy the VPs from the original request, this ensures deterministic
639                  *      behaviour if someone decides to add or remove VPs in the set were
640                  *      iterating over.
641                  */
642                 if (tmpl_copy_vps(request, &vps, request, g->vpt) < 0) {        /* nothing to loop over */
643                         MOD_LOG_OPEN_BRACE;
644                         result = RLM_MODULE_NOOP;
645                         MOD_LOG_CLOSE_BRACE;
646                         goto calculate_result;
647                 }
648
649                 rad_assert(vps != NULL);
650                 fr_cursor_init(&copy, &vps);
651
652                 RDEBUG2("foreach %s ", c->name);
653
654                 /*
655                  *      This is the actual body of the foreach loop
656                  */
657                 for (vp = fr_cursor_first(&copy);
658                      vp != NULL;
659                      vp = fr_cursor_next(&copy)) {
660 #ifndef NDEBUG
661                         if (fr_debug_flag >= 2) {
662                                 char buffer[1024];
663
664                                 vp_prints_value(buffer, sizeof(buffer), vp, '"');
665                                 RDEBUG2("# Foreach-Variable-%d = %s", foreach_depth, buffer);
666                         }
667 #endif
668
669                         /*
670                          *      Add the vp to the request, so that
671                          *      xlat.c, xlat_foreach() can find it.
672                          */
673                         request_data_add(request, (void *)radius_get_vp, foreach_depth, &vp, false);
674
675                         /*
676                          *      Initialize the childs stack frame.
677                          */
678                         next = entry + 1;
679                         next->c = g->children;
680                         next->result = entry->result;
681                         next->priority = 0;
682                         next->unwind = 0;
683
684                         if (!modcall_recurse(request, component, depth + 1, next)) {
685                                 break;
686                         }
687
688                         /*
689                          *      We've unwound to the enclosing
690                          *      "foreach".  Stop the unwinding.
691                          */
692                         if (next->unwind == MOD_FOREACH) {
693                                 break;
694                         }
695
696                         /*
697                          *      Unwind all the way.
698                          */
699                         if (next->unwind == MOD_RETURN) {
700                                 entry->unwind = MOD_RETURN;
701                                 break;
702                         }
703                 } /* loop over VPs */
704
705                 /*
706                  *      Free the copied vps and the request data
707                  *      If we don't remove the request data, something could call
708                  *      the xlat outside of a foreach loop and trigger a segv.
709                  */
710                 pairfree(&vps);
711                 request_data_get(request, (void *)radius_get_vp, foreach_depth);
712
713                 rad_assert(next != NULL);
714                 result = next->result;
715                 priority = next->priority;
716                 MOD_LOG_CLOSE_BRACE;
717                 goto calculate_result;
718         } /* MOD_FOREACH */
719
720         /*
721          *      Break out of a "foreach" loop, or return from a nested
722          *      group.
723          */
724         if ((c->type == MOD_BREAK) || (c->type == MOD_RETURN)) {
725                 int i;
726                 VALUE_PAIR **copy_p;
727
728                 RDEBUG2("%s", unlang_keyword[c->type]);
729
730                 for (i = 8; i >= 0; i--) {
731                         copy_p = request_data_get(request, (void *)radius_get_vp, i);
732                         if (copy_p) {
733                                 if (c->type == MOD_BREAK) {
734                                         RDEBUG2("# break Foreach-Variable-%d", i);
735                                         break;
736                                 }
737                         }
738                 }
739
740                 /*
741                  *      Leave result / priority on the stack, and stop processing the section.
742                  */
743                 entry->unwind = c->type;
744                 goto finish;
745         } /* MOD_BREAK */
746
747 #endif    /* WITH_UNLANG */
748
749         /*
750          *      Child is a group that has children of it's own.
751          */
752         if ((c->type == MOD_GROUP) || (c->type == MOD_POLICY)
753 #ifdef WITH_UNLANG
754             || (c->type == MOD_CASE)
755 #endif
756                 ) {
757                 modgroup *g;
758
759 #ifdef WITH_UNLANG
760         do_children:
761 #endif
762                 g = mod_callabletogroup(c);
763
764                 /*
765                  *      This should really have been caught in the
766                  *      compiler, and the node never generated.  But
767                  *      doing that requires changing it's API so that
768                  *      it returns a flag instead of the compiled
769                  *      MOD_GROUP.
770                  */
771                 if (!g->children) {
772                         RDEBUG2("%s { ... } # empty sub-section is ignored", c->name);
773                         goto next_sibling;
774                 }
775
776                 MOD_LOG_OPEN_BRACE;
777                 modcall_child(request, component,
778                               depth + 1, entry, g->children,
779                               &result);
780                 MOD_LOG_CLOSE_BRACE;
781                 goto calculate_result;
782         } /* MOD_GROUP */
783
784 #ifdef WITH_UNLANG
785         if (c->type == MOD_SWITCH) {
786                 modcallable *this, *found, *null_case;
787                 modgroup *g, *h;
788                 fr_cond_t cond;
789                 value_data_t data;
790                 value_pair_map_t map;
791                 value_pair_tmpl_t vpt;
792
793                 MOD_LOG_OPEN_BRACE;
794
795                 g = mod_callabletogroup(c);
796
797                 memset(&cond, 0, sizeof(cond));
798                 memset(&map, 0, sizeof(map));
799
800                 cond.type = COND_TYPE_MAP;
801                 cond.data.map = &map;
802
803                 map.op = T_OP_CMP_EQ;
804                 map.ci = cf_section_to_item(g->cs);
805
806                 rad_assert(g->vpt != NULL);
807
808                 null_case = found = NULL;
809                 data.ptr = NULL;
810
811                 /*
812                  *      The attribute doesn't exist.  We can skip
813                  *      directly to the default 'case' statement.
814                  */
815                 if ((g->vpt->type == TMPL_TYPE_ATTR) && (tmpl_find_vp(NULL, request, g->vpt) < 0)) {
816                 find_null_case:
817                         for (this = g->children; this; this = this->next) {
818                                 rad_assert(this->type == MOD_CASE);
819
820                                 h = mod_callabletogroup(this);
821                                 if (h->vpt) continue;
822
823                                 found = this;
824                                 break;
825                         }
826
827                         goto do_null_case;
828                 }
829
830                 /*
831                  *      Expand the template if necessary, so that it
832                  *      is evaluated once instead of for each 'case'
833                  *      statement.
834                  */
835                 if ((g->vpt->type == TMPL_TYPE_XLAT_STRUCT) ||
836                     (g->vpt->type == TMPL_TYPE_XLAT) ||
837                     (g->vpt->type == TMPL_TYPE_EXEC)) {
838                         char *p;
839
840                         if (tmpl_aexpand(request, &p, request, g->vpt, NULL, NULL) < 0) goto find_null_case;
841                         data.strvalue = p;
842                         tmpl_init(&vpt, TMPL_TYPE_LITERAL, data.strvalue, talloc_array_length(data.strvalue) - 1);
843                 }
844
845                 /*
846                  *      Find either the exact matching name, or the
847                  *      "case {...}" statement.
848                  */
849                 for (this = g->children; this; this = this->next) {
850                         rad_assert(this->type == MOD_CASE);
851
852                         h = mod_callabletogroup(this);
853
854                         /*
855                          *      Remember the default case
856                          */
857                         if (!h->vpt) {
858                                 if (!null_case) null_case = this;
859                                 continue;
860                         }
861
862                         /*
863                          *      If we're switching over an attribute
864                          *      AND we haven't pre-parsed the data for
865                          *      the case statement, then cast the data
866                          *      to the type of the attribute.
867                          */
868                         if ((g->vpt->type == TMPL_TYPE_ATTR) &&
869                             (h->vpt->type != TMPL_TYPE_DATA)) {
870                                 map.rhs = g->vpt;
871                                 map.lhs = h->vpt;
872                                 cond.cast = g->vpt->tmpl_da;
873
874                                 /*
875                                  *      Remove unnecessary casting.
876                                  */
877                                 if ((h->vpt->type == TMPL_TYPE_ATTR) &&
878                                     (g->vpt->tmpl_da->type == h->vpt->tmpl_da->type)) {
879                                         cond.cast = NULL;
880                                 }
881
882                                 /*
883                                  *      Use the pre-expanded string.
884                                  */
885                         } else if ((g->vpt->type == TMPL_TYPE_XLAT_STRUCT) ||
886                                    (g->vpt->type == TMPL_TYPE_XLAT) ||
887                                    (g->vpt->type == TMPL_TYPE_EXEC)) {
888                                 map.rhs = h->vpt;
889                                 map.lhs = &vpt;
890                                 cond.cast = NULL;
891
892                                 /*
893                                  *      Else evaluate the 'switch' statement.
894                                  */
895                         } else {
896                                 map.rhs = h->vpt;
897                                 map.lhs = g->vpt;
898                                 cond.cast = NULL;
899                         }
900
901                         if (radius_evaluate_map(request, RLM_MODULE_UNKNOWN, 0,
902                                                 &cond) == 1) {
903                                 found = this;
904                                 break;
905                         }
906                 }
907
908                 if (!found) found = null_case;
909
910         do_null_case:
911                 talloc_free(data.ptr);
912                 modcall_child(request, component, depth + 1, entry, found, &result);
913                 MOD_LOG_CLOSE_BRACE;
914                 goto calculate_result;
915         } /* MOD_SWITCH */
916 #endif
917
918         if ((c->type == MOD_LOAD_BALANCE) ||
919             (c->type == MOD_REDUNDANT_LOAD_BALANCE)) {
920                 uint32_t count = 0;
921                 modcallable *this, *found;
922                 modgroup *g;
923
924                 MOD_LOG_OPEN_BRACE;
925
926                 g = mod_callabletogroup(c);
927                 found = g->children;
928                 rad_assert(g->children != NULL);
929
930                 /*
931                  *      Choose a child at random.
932                  */
933                 for (this = g->children; this; this = this->next) {
934                         count++;
935
936                         if ((count * (fr_rand() & 0xffff)) < (uint32_t) 0x10000) {
937                                 found = this;
938                         }
939                 }
940
941                 MOD_LOG_OPEN_BRACE;
942
943                 if (c->type == MOD_LOAD_BALANCE) {
944                         modcall_child(request, component,
945                                       depth + 1, entry, found,
946                                       &result);
947
948                 } else {
949                         this = found;
950
951                         do {
952                                 modcall_child(request, component,
953                                               depth + 1, entry, this,
954                                               &result);
955                                 if (this->actions[result] == MOD_ACTION_RETURN) {
956                                         priority = -1;
957                                         break;
958                                 }
959
960                                 this = this->next;
961                                 if (!this) this = g->children;
962                         } while (this != found);
963                 }
964                 MOD_LOG_CLOSE_BRACE;
965                 goto calculate_result;
966         } /* MOD_LOAD_BALANCE */
967
968         /*
969          *      Reference another virtual server.
970          *
971          *      This should really be deleted, and replaced with a
972          *      more abstracted / functional version.
973          */
974         if (c->type == MOD_REFERENCE) {
975                 modref *mr = mod_callabletoref(c);
976                 char const *server = request->server;
977
978                 if (server == mr->ref_name) {
979                         RWDEBUG("Suppressing recursive call to server %s", server);
980                         goto next_sibling;
981                 }
982
983                 request->server = mr->ref_name;
984                 RDEBUG("server %s { # nested call", mr->ref_name);
985                 result = indexed_modcall(component, 0, request);
986                 RDEBUG("} # server %s with nested call", mr->ref_name);
987                 request->server = server;
988                 goto calculate_result;
989         } /* MOD_REFERENCE */
990
991         /*
992          *      xlat a string without doing anything else
993          *
994          *      This should really be deleted, and replaced with a
995          *      more abstracted / functional version.
996          */
997         if (c->type == MOD_XLAT) {
998                 modxlat *mx = mod_callabletoxlat(c);
999                 char buffer[128];
1000
1001                 if (!mx->exec) {
1002                         radius_xlat(buffer, sizeof(buffer), request, mx->xlat_name, NULL, NULL);
1003                 } else {
1004                         RDEBUG("`%s`", mx->xlat_name);
1005                         radius_exec_program(NULL, 0, NULL, request, mx->xlat_name, request->packet->vps,
1006                                             false, true, EXEC_TIMEOUT);
1007                 }
1008
1009                 goto next_sibling;
1010         } /* MOD_XLAT */
1011
1012         /*
1013          *      Add new module types here.
1014          */
1015
1016 calculate_result:
1017 #if 0
1018         RDEBUG("(%s, %d) ? (%s, %d)",
1019                fr_int2str(mod_rcode_table, result, "<invalid>"),
1020                priority,
1021                fr_int2str(mod_rcode_table, entry->result, "<invalid>"),
1022                entry->priority);
1023 #endif
1024
1025
1026         rad_assert(result != RLM_MODULE_UNKNOWN);
1027
1028         /*
1029          *      The child's action says return.  Do so.
1030          */
1031         if ((c->actions[result] == MOD_ACTION_RETURN) &&
1032             (priority <= 0)) {
1033                 entry->result = result;
1034                 goto finish;
1035         }
1036
1037         /*
1038          *      If "reject", break out of the loop and return
1039          *      reject.
1040          */
1041         if (c->actions[result] == MOD_ACTION_REJECT) {
1042                 entry->result = RLM_MODULE_REJECT;
1043                 goto finish;
1044         }
1045
1046         /*
1047          *      The array holds a default priority for this return
1048          *      code.  Grab it in preference to any unset priority.
1049          */
1050         if (priority < 0) {
1051                 priority = c->actions[result];
1052         }
1053
1054         /*
1055          *      We're higher than any previous priority, remember this
1056          *      return code and priority.
1057          */
1058         if (priority > entry->priority) {
1059                 entry->result = result;
1060                 entry->priority = priority;
1061         }
1062
1063 #ifdef WITH_UNLANG
1064         /*
1065          *      If we're processing a "case" statement, we return once
1066          *      it's done, rather than going to the next "case" statement.
1067          */
1068         if (c->type == MOD_CASE) goto finish;
1069 #endif
1070
1071         /*
1072          *      If we've been told to stop processing
1073          *      it, do so.
1074          */
1075         if (entry->unwind == MOD_BREAK) {
1076                 RDEBUG2("# unwind to enclosing foreach");
1077                 entry->unwind = 0;
1078                 goto finish;
1079         }
1080
1081         if (entry->unwind == MOD_RETURN) {
1082                 goto finish;
1083         }
1084
1085 next_sibling:
1086         entry->c = entry->c->next;
1087
1088         if (entry->c) goto redo;
1089
1090 finish:
1091         /*
1092          *      And we're done!
1093          */
1094         REXDENT();
1095         return true;
1096 }
1097
1098
1099 /** Call a module, iteratively, with a local stack, rather than recursively
1100  *
1101  * What did Paul Graham say about Lisp...?
1102  */
1103 int modcall(rlm_components_t component, modcallable *c, REQUEST *request)
1104 {
1105         modcall_stack_entry_t stack[MODCALL_STACK_MAX];
1106
1107 #ifndef NDEBUG
1108         memset(stack, 0, sizeof(stack));
1109 #endif
1110         /*
1111          *      Set up the initial stack frame.
1112          */
1113         stack[0].c = c;
1114         stack[0].result = default_component_results[component];
1115         stack[0].priority = 0;
1116         stack[0].unwind = 0;
1117
1118         /*
1119          *      Call the main handler.
1120          */
1121         if (!modcall_recurse(request, component, 0, &stack[0])) {
1122                 return RLM_MODULE_FAIL;
1123         }
1124
1125         /*
1126          *      Return the result.
1127          */
1128         return stack[0].result;
1129 }
1130
1131
1132 #if 0
1133 static char const *action2str(int action)
1134 {
1135         static char buf[32];
1136         if(action==MOD_ACTION_RETURN)
1137                 return "return";
1138         if(action==MOD_ACTION_REJECT)
1139                 return "reject";
1140         snprintf(buf, sizeof buf, "%d", action);
1141         return buf;
1142 }
1143
1144 /* If you suspect a bug in the parser, you'll want to use these dump
1145  * functions. dump_tree should reproduce a whole tree exactly as it was found
1146  * in radiusd.conf, but in long form (all actions explicitly defined) */
1147 static void dump_mc(modcallable *c, int indent)
1148 {
1149         int i;
1150
1151         if(c->type==MOD_SINGLE) {
1152                 modsingle *single = mod_callabletosingle(c);
1153                 DEBUG("%.*s%s {", indent, "\t\t\t\t\t\t\t\t\t\t\t",
1154                         single->modinst->name);
1155         } else if ((c->type > MOD_SINGLE) && (c->type <= MOD_POLICY)) {
1156                 modgroup *g = mod_callabletogroup(c);
1157                 modcallable *p;
1158                 DEBUG("%.*s%s {", indent, "\t\t\t\t\t\t\t\t\t\t\t",
1159                       unlang_keyword[c->type]);
1160                 for(p = g->children;p;p = p->next)
1161                         dump_mc(p, indent+1);
1162         } /* else ignore it for now */
1163
1164         for(i = 0; i<RLM_MODULE_NUMCODES; ++i) {
1165                 DEBUG("%.*s%s = %s", indent+1, "\t\t\t\t\t\t\t\t\t\t\t",
1166                       fr_int2str(mod_rcode_table, i, "<invalid>"),
1167                       action2str(c->actions[i]));
1168         }
1169
1170         DEBUG("%.*s}", indent, "\t\t\t\t\t\t\t\t\t\t\t");
1171 }
1172
1173 static void dump_tree(rlm_components_t comp, modcallable *c)
1174 {
1175         DEBUG("[%s]", comp2str[comp]);
1176         dump_mc(c, 0);
1177 }
1178 #else
1179 #define dump_tree(a, b)
1180 #endif
1181
1182 /* These are the default actions. For each component, the group{} block
1183  * behaves like the code from the old module_*() function. redundant{} and
1184  * append{} are based on my guesses of what they will be used for. --Pac. */
1185 static const int
1186 defaultactions[RLM_COMPONENT_COUNT][GROUPTYPE_COUNT][RLM_MODULE_NUMCODES] =
1187 {
1188         /* authenticate */
1189         {
1190                 /* group */
1191                 {
1192                         MOD_ACTION_RETURN,      /* reject   */
1193                         1,                      /* fail     */
1194                         MOD_ACTION_RETURN,      /* ok       */
1195                         MOD_ACTION_RETURN,      /* handled  */
1196                         1,                      /* invalid  */
1197                         MOD_ACTION_RETURN,      /* userlock */
1198                         MOD_ACTION_RETURN,      /* notfound */
1199                         1,                      /* noop     */
1200                         1                       /* updated  */
1201                 },
1202                 /* redundant */
1203                 {
1204                         MOD_ACTION_RETURN,      /* reject   */
1205                         1,                      /* fail     */
1206                         MOD_ACTION_RETURN,      /* ok       */
1207                         MOD_ACTION_RETURN,      /* handled  */
1208                         MOD_ACTION_RETURN,      /* invalid  */
1209                         MOD_ACTION_RETURN,      /* userlock */
1210                         MOD_ACTION_RETURN,      /* notfound */
1211                         MOD_ACTION_RETURN,      /* noop     */
1212                         MOD_ACTION_RETURN       /* updated  */
1213                 },
1214                 /* append */
1215                 {
1216                         MOD_ACTION_RETURN,      /* reject   */
1217                         1,                      /* fail     */
1218                         MOD_ACTION_RETURN,      /* ok       */
1219                         MOD_ACTION_RETURN,      /* handled  */
1220                         MOD_ACTION_RETURN,      /* invalid  */
1221                         MOD_ACTION_RETURN,      /* userlock */
1222                         2,                      /* notfound */
1223                         MOD_ACTION_RETURN,      /* noop     */
1224                         MOD_ACTION_RETURN       /* updated  */
1225                 }
1226         },
1227         /* authorize */
1228         {
1229                 /* group */
1230                 {
1231                         MOD_ACTION_RETURN,      /* reject   */
1232                         MOD_ACTION_RETURN,      /* fail     */
1233                         3,                      /* ok       */
1234                         MOD_ACTION_RETURN,      /* handled  */
1235                         MOD_ACTION_RETURN,      /* invalid  */
1236                         MOD_ACTION_RETURN,      /* userlock */
1237                         1,                      /* notfound */
1238                         2,                      /* noop     */
1239                         4                       /* updated  */
1240                 },
1241                 /* redundant */
1242                 {
1243                         MOD_ACTION_RETURN,      /* reject   */
1244                         1,                      /* fail     */
1245                         MOD_ACTION_RETURN,      /* ok       */
1246                         MOD_ACTION_RETURN,      /* handled  */
1247                         MOD_ACTION_RETURN,      /* invalid  */
1248                         MOD_ACTION_RETURN,      /* userlock */
1249                         MOD_ACTION_RETURN,      /* notfound */
1250                         MOD_ACTION_RETURN,      /* noop     */
1251                         MOD_ACTION_RETURN       /* updated  */
1252                 },
1253                 /* append */
1254                 {
1255                         MOD_ACTION_RETURN,      /* reject   */
1256                         1,                      /* fail     */
1257                         MOD_ACTION_RETURN,      /* ok       */
1258                         MOD_ACTION_RETURN,      /* handled  */
1259                         MOD_ACTION_RETURN,      /* invalid  */
1260                         MOD_ACTION_RETURN,      /* userlock */
1261                         2,                      /* notfound */
1262                         MOD_ACTION_RETURN,      /* noop     */
1263                         MOD_ACTION_RETURN       /* updated  */
1264                 }
1265         },
1266         /* preacct */
1267         {
1268                 /* group */
1269                 {
1270                         MOD_ACTION_RETURN,      /* reject   */
1271                         MOD_ACTION_RETURN,      /* fail     */
1272                         2,                      /* ok       */
1273                         MOD_ACTION_RETURN,      /* handled  */
1274                         MOD_ACTION_RETURN,      /* invalid  */
1275                         MOD_ACTION_RETURN,      /* userlock */
1276                         MOD_ACTION_RETURN,      /* notfound */
1277                         1,                      /* noop     */
1278                         3                       /* updated  */
1279                 },
1280                 /* redundant */
1281                 {
1282                         MOD_ACTION_RETURN,      /* reject   */
1283                         1,                      /* fail     */
1284                         MOD_ACTION_RETURN,      /* ok       */
1285                         MOD_ACTION_RETURN,      /* handled  */
1286                         MOD_ACTION_RETURN,      /* invalid  */
1287                         MOD_ACTION_RETURN,      /* userlock */
1288                         MOD_ACTION_RETURN,      /* notfound */
1289                         MOD_ACTION_RETURN,      /* noop     */
1290                         MOD_ACTION_RETURN       /* updated  */
1291                 },
1292                 /* append */
1293                 {
1294                         MOD_ACTION_RETURN,      /* reject   */
1295                         1,                      /* fail     */
1296                         MOD_ACTION_RETURN,      /* ok       */
1297                         MOD_ACTION_RETURN,      /* handled  */
1298                         MOD_ACTION_RETURN,      /* invalid  */
1299                         MOD_ACTION_RETURN,      /* userlock */
1300                         2,                      /* notfound */
1301                         MOD_ACTION_RETURN,      /* noop     */
1302                         MOD_ACTION_RETURN       /* updated  */
1303                 }
1304         },
1305         /* accounting */
1306         {
1307                 /* group */
1308                 {
1309                         MOD_ACTION_RETURN,      /* reject   */
1310                         MOD_ACTION_RETURN,      /* fail     */
1311                         2,                      /* ok       */
1312                         MOD_ACTION_RETURN,      /* handled  */
1313                         MOD_ACTION_RETURN,      /* invalid  */
1314                         MOD_ACTION_RETURN,      /* userlock */
1315                         MOD_ACTION_RETURN,      /* notfound */
1316                         1,                      /* noop     */
1317                         3                       /* updated  */
1318                 },
1319                 /* redundant */
1320                 {
1321                         1,                      /* reject   */
1322                         1,                      /* fail     */
1323                         MOD_ACTION_RETURN,      /* ok       */
1324                         MOD_ACTION_RETURN,      /* handled  */
1325                         1,                      /* invalid  */
1326                         1,                      /* userlock */
1327                         1,                      /* notfound */
1328                         2,                      /* noop     */
1329                         4                       /* updated  */
1330                 },
1331                 /* append */
1332                 {
1333                         MOD_ACTION_RETURN,      /* reject   */
1334                         1,                      /* fail     */
1335                         MOD_ACTION_RETURN,      /* ok       */
1336                         MOD_ACTION_RETURN,      /* handled  */
1337                         MOD_ACTION_RETURN,      /* invalid  */
1338                         MOD_ACTION_RETURN,      /* userlock */
1339                         2,                      /* notfound */
1340                         MOD_ACTION_RETURN,      /* noop     */
1341                         MOD_ACTION_RETURN       /* updated  */
1342                 }
1343         },
1344         /* checksimul */
1345         {
1346                 /* group */
1347                 {
1348                         MOD_ACTION_RETURN,      /* reject   */
1349                         1,                      /* fail     */
1350                         MOD_ACTION_RETURN,      /* ok       */
1351                         MOD_ACTION_RETURN,      /* handled  */
1352                         MOD_ACTION_RETURN,      /* invalid  */
1353                         MOD_ACTION_RETURN,      /* userlock */
1354                         MOD_ACTION_RETURN,      /* notfound */
1355                         MOD_ACTION_RETURN,      /* noop     */
1356                         MOD_ACTION_RETURN       /* updated  */
1357                 },
1358                 /* redundant */
1359                 {
1360                         MOD_ACTION_RETURN,      /* reject   */
1361                         1,                      /* fail     */
1362                         MOD_ACTION_RETURN,      /* ok       */
1363                         MOD_ACTION_RETURN,      /* handled  */
1364                         MOD_ACTION_RETURN,      /* invalid  */
1365                         MOD_ACTION_RETURN,      /* userlock */
1366                         MOD_ACTION_RETURN,      /* notfound */
1367                         MOD_ACTION_RETURN,      /* noop     */
1368                         MOD_ACTION_RETURN       /* updated  */
1369                 },
1370                 /* append */
1371                 {
1372                         MOD_ACTION_RETURN,      /* reject   */
1373                         1,                      /* fail     */
1374                         MOD_ACTION_RETURN,      /* ok       */
1375                         MOD_ACTION_RETURN,      /* handled  */
1376                         MOD_ACTION_RETURN,      /* invalid  */
1377                         MOD_ACTION_RETURN,      /* userlock */
1378                         MOD_ACTION_RETURN,      /* notfound */
1379                         MOD_ACTION_RETURN,      /* noop     */
1380                         MOD_ACTION_RETURN       /* updated  */
1381                 }
1382         },
1383         /* pre-proxy */
1384         {
1385                 /* group */
1386                 {
1387                         MOD_ACTION_RETURN,      /* reject   */
1388                         MOD_ACTION_RETURN,      /* fail     */
1389                         3,                      /* ok       */
1390                         MOD_ACTION_RETURN,      /* handled  */
1391                         MOD_ACTION_RETURN,      /* invalid  */
1392                         MOD_ACTION_RETURN,      /* userlock */
1393                         1,                      /* notfound */
1394                         2,                      /* noop     */
1395                         4                       /* updated  */
1396                 },
1397                 /* redundant */
1398                 {
1399                         MOD_ACTION_RETURN,      /* reject   */
1400                         1,                      /* fail     */
1401                         MOD_ACTION_RETURN,      /* ok       */
1402                         MOD_ACTION_RETURN,      /* handled  */
1403                         MOD_ACTION_RETURN,      /* invalid  */
1404                         MOD_ACTION_RETURN,      /* userlock */
1405                         MOD_ACTION_RETURN,      /* notfound */
1406                         MOD_ACTION_RETURN,      /* noop     */
1407                         MOD_ACTION_RETURN       /* updated  */
1408                 },
1409                 /* append */
1410                 {
1411                         MOD_ACTION_RETURN,      /* reject   */
1412                         1,                      /* fail     */
1413                         MOD_ACTION_RETURN,      /* ok       */
1414                         MOD_ACTION_RETURN,      /* handled  */
1415                         MOD_ACTION_RETURN,      /* invalid  */
1416                         MOD_ACTION_RETURN,      /* userlock */
1417                         2,                      /* notfound */
1418                         MOD_ACTION_RETURN,      /* noop     */
1419                         MOD_ACTION_RETURN       /* updated  */
1420                 }
1421         },
1422         /* post-proxy */
1423         {
1424                 /* group */
1425                 {
1426                         MOD_ACTION_RETURN,      /* reject   */
1427                         MOD_ACTION_RETURN,      /* fail     */
1428                         3,                      /* ok       */
1429                         MOD_ACTION_RETURN,      /* handled  */
1430                         MOD_ACTION_RETURN,      /* invalid  */
1431                         MOD_ACTION_RETURN,      /* userlock */
1432                         1,                      /* notfound */
1433                         2,                      /* noop     */
1434                         4                       /* updated  */
1435                 },
1436                 /* redundant */
1437                 {
1438                         MOD_ACTION_RETURN,      /* reject   */
1439                         1,                      /* fail     */
1440                         MOD_ACTION_RETURN,      /* ok       */
1441                         MOD_ACTION_RETURN,      /* handled  */
1442                         MOD_ACTION_RETURN,      /* invalid  */
1443                         MOD_ACTION_RETURN,      /* userlock */
1444                         MOD_ACTION_RETURN,      /* notfound */
1445                         MOD_ACTION_RETURN,      /* noop     */
1446                         MOD_ACTION_RETURN       /* updated  */
1447                 },
1448                 /* append */
1449                 {
1450                         MOD_ACTION_RETURN,      /* reject   */
1451                         1,                      /* fail     */
1452                         MOD_ACTION_RETURN,      /* ok       */
1453                         MOD_ACTION_RETURN,      /* handled  */
1454                         MOD_ACTION_RETURN,      /* invalid  */
1455                         MOD_ACTION_RETURN,      /* userlock */
1456                         2,                      /* notfound */
1457                         MOD_ACTION_RETURN,      /* noop     */
1458                         MOD_ACTION_RETURN       /* updated  */
1459                 }
1460         },
1461         /* post-auth */
1462         {
1463                 /* group */
1464                 {
1465                         MOD_ACTION_RETURN,      /* reject   */
1466                         MOD_ACTION_RETURN,      /* fail     */
1467                         3,                      /* ok       */
1468                         MOD_ACTION_RETURN,      /* handled  */
1469                         MOD_ACTION_RETURN,      /* invalid  */
1470                         MOD_ACTION_RETURN,      /* userlock */
1471                         1,                      /* notfound */
1472                         2,                      /* noop     */
1473                         4                       /* updated  */
1474                 },
1475                 /* redundant */
1476                 {
1477                         MOD_ACTION_RETURN,      /* reject   */
1478                         1,                      /* fail     */
1479                         MOD_ACTION_RETURN,      /* ok       */
1480                         MOD_ACTION_RETURN,      /* handled  */
1481                         MOD_ACTION_RETURN,      /* invalid  */
1482                         MOD_ACTION_RETURN,      /* userlock */
1483                         MOD_ACTION_RETURN,      /* notfound */
1484                         MOD_ACTION_RETURN,      /* noop     */
1485                         MOD_ACTION_RETURN       /* updated  */
1486                 },
1487                 /* append */
1488                 {
1489                         MOD_ACTION_RETURN,      /* reject   */
1490                         1,                      /* fail     */
1491                         MOD_ACTION_RETURN,      /* ok       */
1492                         MOD_ACTION_RETURN,      /* handled  */
1493                         MOD_ACTION_RETURN,      /* invalid  */
1494                         MOD_ACTION_RETURN,      /* userlock */
1495                         2,                      /* notfound */
1496                         MOD_ACTION_RETURN,      /* noop     */
1497                         MOD_ACTION_RETURN       /* updated  */
1498                 }
1499         }
1500 #ifdef WITH_COA
1501         ,
1502         /* recv-coa */
1503         {
1504                 /* group */
1505                 {
1506                         MOD_ACTION_RETURN,      /* reject   */
1507                         MOD_ACTION_RETURN,      /* fail     */
1508                         3,                      /* ok       */
1509                         MOD_ACTION_RETURN,      /* handled  */
1510                         MOD_ACTION_RETURN,      /* invalid  */
1511                         MOD_ACTION_RETURN,      /* userlock */
1512                         1,                      /* notfound */
1513                         2,                      /* noop     */
1514                         4                       /* updated  */
1515                 },
1516                 /* redundant */
1517                 {
1518                         MOD_ACTION_RETURN,      /* reject   */
1519                         1,                      /* fail     */
1520                         MOD_ACTION_RETURN,      /* ok       */
1521                         MOD_ACTION_RETURN,      /* handled  */
1522                         MOD_ACTION_RETURN,      /* invalid  */
1523                         MOD_ACTION_RETURN,      /* userlock */
1524                         MOD_ACTION_RETURN,      /* notfound */
1525                         MOD_ACTION_RETURN,      /* noop     */
1526                         MOD_ACTION_RETURN       /* updated  */
1527                 },
1528                 /* append */
1529                 {
1530                         MOD_ACTION_RETURN,      /* reject   */
1531                         1,                      /* fail     */
1532                         MOD_ACTION_RETURN,      /* ok       */
1533                         MOD_ACTION_RETURN,      /* handled  */
1534                         MOD_ACTION_RETURN,      /* invalid  */
1535                         MOD_ACTION_RETURN,      /* userlock */
1536                         2,                      /* notfound */
1537                         MOD_ACTION_RETURN,      /* noop     */
1538                         MOD_ACTION_RETURN       /* updated  */
1539                 }
1540         },
1541         /* send-coa */
1542         {
1543                 /* group */
1544                 {
1545                         MOD_ACTION_RETURN,      /* reject   */
1546                         MOD_ACTION_RETURN,      /* fail     */
1547                         3,                      /* ok       */
1548                         MOD_ACTION_RETURN,      /* handled  */
1549                         MOD_ACTION_RETURN,      /* invalid  */
1550                         MOD_ACTION_RETURN,      /* userlock */
1551                         1,                      /* notfound */
1552                         2,                      /* noop     */
1553                         4                       /* updated  */
1554                 },
1555                 /* redundant */
1556                 {
1557                         MOD_ACTION_RETURN,      /* reject   */
1558                         1,                      /* fail     */
1559                         MOD_ACTION_RETURN,      /* ok       */
1560                         MOD_ACTION_RETURN,      /* handled  */
1561                         MOD_ACTION_RETURN,      /* invalid  */
1562                         MOD_ACTION_RETURN,      /* userlock */
1563                         MOD_ACTION_RETURN,      /* notfound */
1564                         MOD_ACTION_RETURN,      /* noop     */
1565                         MOD_ACTION_RETURN       /* updated  */
1566                 },
1567                 /* append */
1568                 {
1569                         MOD_ACTION_RETURN,      /* reject   */
1570                         1,                      /* fail     */
1571                         MOD_ACTION_RETURN,      /* ok       */
1572                         MOD_ACTION_RETURN,      /* handled  */
1573                         MOD_ACTION_RETURN,      /* invalid  */
1574                         MOD_ACTION_RETURN,      /* userlock */
1575                         2,                      /* notfound */
1576                         MOD_ACTION_RETURN,      /* noop     */
1577                         MOD_ACTION_RETURN       /* updated  */
1578                 }
1579         }
1580 #endif
1581 };
1582
1583 /** Validate and fixup a map that's part of an update section.
1584  *
1585  * @param map to validate.
1586  * @param ctx data to pass to fixup function (currently unused).
1587  * @return 0 if valid else -1.
1588  */
1589 int modcall_fixup_update(value_pair_map_t *map, UNUSED void *ctx)
1590 {
1591         CONF_PAIR *cp = cf_item_to_pair(map->ci);
1592
1593         /*
1594          *      Anal-retentive checks.
1595          */
1596         if (DEBUG_ENABLED3) {
1597                 if ((map->lhs->type == TMPL_TYPE_ATTR) && (map->lhs->name[0] != '&')) {
1598                         WARN("%s[%d]: Please change attribute reference to '&%s %s ...'",
1599                              cf_pair_filename(cp), cf_pair_lineno(cp),
1600                              map->lhs->name, fr_int2str(fr_tokens, map->op, "<INVALID>"));
1601                 }
1602
1603                 if ((map->rhs->type == TMPL_TYPE_ATTR) && (map->rhs->name[0] != '&')) {
1604                         WARN("%s[%d]: Please change attribute reference to '... %s &%s'",
1605                              cf_pair_filename(cp), cf_pair_lineno(cp),
1606                              fr_int2str(fr_tokens, map->op, "<INVALID>"), map->rhs->name);
1607                 }
1608         }
1609
1610         /*
1611          *      Values used by unary operators should be literal ANY
1612          *
1613          *      We then free the template and alloc a NULL one instead.
1614          */
1615         if (map->op == T_OP_CMP_FALSE) {
1616                 if ((map->rhs->type != TMPL_TYPE_LITERAL) || (strcmp(map->rhs->name, "ANY") != 0)) {
1617                         WARN("%s[%d] Wildcard deletion MUST use '!* ANY'",
1618                              cf_pair_filename(cp), cf_pair_lineno(cp));
1619                 }
1620
1621                 tmpl_free(&map->rhs);
1622
1623                 map->rhs = tmpl_alloc(map, TMPL_TYPE_NULL, NULL, 0);
1624         }
1625
1626         /*
1627          *      Lots of sanity checks for insane people...
1628          */
1629
1630         /*
1631          *      What exactly where you expecting to happen here?
1632          */
1633         if ((map->lhs->type == TMPL_TYPE_ATTR) &&
1634             (map->rhs->type == TMPL_TYPE_LIST)) {
1635                 cf_log_err(map->ci, "Can't copy list into an attribute");
1636                 return -1;
1637         }
1638
1639         /*
1640          *      Depending on the attribute type, some operators are disallowed.
1641          */
1642         if (map->lhs->type == TMPL_TYPE_ATTR) {
1643                 switch (map->op) {
1644                 default:
1645                         cf_log_err(map->ci, "Invalid operator for attribute");
1646                         return -1;
1647
1648                 case T_OP_EQ:
1649                 case T_OP_CMP_EQ:
1650                 case T_OP_ADD:
1651                 case T_OP_SUB:
1652                 case T_OP_LE:
1653                 case T_OP_GE:
1654                 case T_OP_CMP_FALSE:
1655                 case T_OP_SET:
1656                         break;
1657                 }
1658         }
1659
1660         if (map->lhs->type == TMPL_TYPE_LIST) {
1661                 /*
1662                  *      Can't copy an xlat expansion or literal into a list,
1663                  *      we don't know what type of attribute we'd need
1664                  *      to create.
1665                  *
1666                  *      The only exception is where were using a unary
1667                  *      operator like !*.
1668                  */
1669                 if (map->op != T_OP_CMP_FALSE) switch (map->rhs->type) {
1670                 case TMPL_TYPE_XLAT:
1671                 case TMPL_TYPE_LITERAL:
1672                         cf_log_err(map->ci, "Can't copy value into list (we don't know which attribute to create)");
1673                         return -1;
1674
1675                 default:
1676                         break;
1677                 }
1678
1679                 /*
1680                  *      Only += and :=, and !* operators are supported
1681                  *      for lists.
1682                  */
1683                 switch (map->op) {
1684                 case T_OP_CMP_FALSE:
1685                         break;
1686
1687                 case T_OP_ADD:
1688                         if ((map->rhs->type != TMPL_TYPE_LIST) &&
1689                             (map->rhs->type != TMPL_TYPE_EXEC)) {
1690                                 cf_log_err(map->ci, "Invalid source for list assignment '%s += ...'", map->lhs->name);
1691                                 return -1;
1692                         }
1693                         break;
1694
1695                 case T_OP_SET:
1696                         if (map->rhs->type == TMPL_TYPE_EXEC) {
1697                                 WARN("%s[%d] Please change ':=' to '=' for list assignment",
1698                                      cf_pair_filename(cp), cf_pair_lineno(cp));
1699                         }
1700
1701                         if (map->rhs->type != TMPL_TYPE_LIST) {
1702                                 cf_log_err(map->ci, "Invalid source for list assignment '%s := ...'", map->lhs->name);
1703                                 return -1;
1704                         }
1705                         break;
1706
1707                 case T_OP_EQ:
1708                         if (map->rhs->type != TMPL_TYPE_EXEC) {
1709                                 cf_log_err(map->ci, "Invalid source for list assignment '%s = ...'", map->lhs->name);
1710                                 return -1;
1711                         }
1712                         break;
1713
1714                 default:
1715                         cf_log_err(map->ci, "Operator \"%s\" not allowed for list assignment",
1716                                    fr_int2str(fr_tokens, map->op, "<INVALID>"));
1717                         return -1;
1718                 }
1719         }
1720
1721         /*
1722          *      If the map has a unary operator there's no further
1723          *      processing we need to, as RHS is unused.
1724          */
1725         if (map->op == T_OP_CMP_FALSE) return 0;
1726
1727         /*
1728          *      If LHS is an attribute, and RHS is a literal, we can
1729          *      preparse the information into a TMPL_TYPE_DATA.
1730          *
1731          *      Unless it's a unary operator in which case we
1732          *      ignore map->rhs.
1733          */
1734         if ((map->lhs->type == TMPL_TYPE_ATTR) && (map->rhs->type == TMPL_TYPE_LITERAL)) {
1735                 /*
1736                  *      It's a literal string, just copy it.
1737                  *      Don't escape anything.
1738                  */
1739                 if (!cf_new_escape &&
1740                     (map->lhs->tmpl_da->type == PW_TYPE_STRING) &&
1741                     (cf_pair_value_type(cp) == T_SINGLE_QUOTED_STRING)) {
1742                         tmpl_cast_in_place_str(map->rhs);
1743                 } else {
1744                         if (!tmpl_cast_in_place(map->rhs, map->lhs->tmpl_da->type, map->lhs->tmpl_da)) {
1745                                 cf_log_err(map->ci, "%s", fr_strerror());
1746                                 return -1;
1747                         }
1748
1749                         /*
1750                          *      Fixup LHS da if it doesn't match the type
1751                          *      of the RHS.
1752                          */
1753                         if (map->lhs->tmpl_da->type != map->rhs->tmpl_data_type) {
1754                                 DICT_ATTR const *da;
1755
1756                                 da = dict_attrbytype(map->lhs->tmpl_da->attr, map->lhs->tmpl_da->vendor,
1757                                                      map->rhs->tmpl_data_type);
1758                                 if (!da) {
1759                                         fr_strerror_printf("Cannot find %s variant of attribute \"%s\"",
1760                                                            fr_int2str(dict_attr_types, map->rhs->tmpl_data_type,
1761                                                            "<INVALID>"), map->lhs->tmpl_da->name);
1762                                         return -1;
1763                                 }
1764                                 map->lhs->tmpl_da = da;
1765                         }
1766                 }
1767         } /* else we can't precompile the data */
1768
1769         return 0;
1770 }
1771
1772
1773 #ifdef WITH_UNLANG
1774 static modcallable *do_compile_modupdate(modcallable *parent, rlm_components_t component,
1775                                          CONF_SECTION *cs, char const *name2)
1776 {
1777         int rcode;
1778         modgroup *g;
1779         modcallable *csingle;
1780
1781         value_pair_map_t *head;
1782
1783         /*
1784          *      This looks at cs->name2 to determine which list to update
1785          */
1786         rcode = map_afrom_cs(&head, cs, PAIR_LIST_REQUEST, PAIR_LIST_REQUEST, modcall_fixup_update, NULL, 128);
1787         if (rcode < 0) return NULL; /* message already printed */
1788         if (!head) {
1789                 cf_log_err_cs(cs, "'update' sections cannot be empty");
1790                 return NULL;
1791         }
1792
1793         g = talloc_zero(parent, modgroup);
1794         csingle = mod_grouptocallable(g);
1795
1796         csingle->parent = parent;
1797         csingle->next = NULL;
1798
1799         if (name2) {
1800                 csingle->name = name2;
1801         } else {
1802                 csingle->name = "";
1803         }
1804         csingle->type = MOD_UPDATE;
1805         csingle->method = component;
1806
1807         memcpy(csingle->actions, defaultactions[component][GROUPTYPE_SIMPLE],
1808                sizeof(csingle->actions));
1809
1810         g->grouptype = GROUPTYPE_SIMPLE;
1811         g->children = NULL;
1812         g->cs = cs;
1813         g->map = talloc_steal(g, head);
1814
1815         return csingle;
1816 }
1817
1818
1819 static modcallable *do_compile_modswitch (modcallable *parent, rlm_components_t component, CONF_SECTION *cs)
1820 {
1821         CONF_ITEM *ci;
1822         FR_TOKEN type;
1823         char const *name2;
1824         bool had_seen_default = false;
1825         modcallable *csingle;
1826         modgroup *g;
1827         ssize_t slen;
1828         value_pair_tmpl_t *vpt;
1829
1830         name2 = cf_section_name2(cs);
1831         if (!name2) {
1832                 cf_log_err_cs(cs, "You must specify a variable to switch over for 'switch'");
1833                 return NULL;
1834         }
1835
1836         if (!cf_item_find_next(cs, NULL)) {
1837                 cf_log_err_cs(cs, "'switch' statements cannot be empty");
1838                 return NULL;
1839         }
1840
1841         /*
1842          *      Create the template.  If we fail, AND it's a bare word
1843          *      with &Foo-Bar, it MAY be an attribute defined by a
1844          *      module.  Allow it for now.  The pass2 checks below
1845          *      will fix it up.
1846          */
1847         type = cf_section_name2_type(cs);
1848         slen = tmpl_afrom_str(cs, &vpt, name2, strlen(name2), type, REQUEST_CURRENT, PAIR_LIST_REQUEST);
1849         if ((slen < 0) && ((type != T_BARE_WORD) || (name2[0] != '&'))) {
1850                 char *spaces, *text;
1851
1852                 fr_canonicalize_error(cs, &spaces, &text, slen, fr_strerror());
1853
1854                 cf_log_err_cs(cs, "Syntax error");
1855                 cf_log_err_cs(cs, "%s", name2);
1856                 cf_log_err_cs(cs, "%s^ %s", spaces, text);
1857
1858                 talloc_free(spaces);
1859                 talloc_free(text);
1860
1861                 return NULL;
1862         }
1863
1864         /*
1865          *      Otherwise a NULL vpt may refer to an attribute defined
1866          *      by a module.  That is checked in pass 2.
1867          */
1868
1869         /*
1870          *      Walk through the children of the switch section,
1871          *      ensuring that they're all 'case' statements
1872          */
1873         for (ci = cf_item_find_next(cs, NULL);
1874              ci != NULL;
1875              ci = cf_item_find_next(cs, ci)) {
1876                 CONF_SECTION *subcs;
1877                 char const *name1;
1878
1879                 if (!cf_item_is_section(ci)) {
1880                         if (!cf_item_is_pair(ci)) continue;
1881
1882                         cf_log_err(ci, "\"switch\" sections can only have \"case\" subsections");
1883                         talloc_free(vpt);
1884                         return NULL;
1885                 }
1886
1887                 subcs = cf_item_to_section(ci); /* can't return NULL */
1888                 name1 = cf_section_name1(subcs);
1889
1890                 if (strcmp(name1, "case") != 0) {
1891                         cf_log_err(ci, "\"switch\" sections can only have \"case\" subsections");
1892                         talloc_free(vpt);
1893                         return NULL;
1894                 }
1895
1896                 name2 = cf_section_name2(subcs);
1897                 if (!name2) {
1898                         if (!had_seen_default) {
1899                                 had_seen_default = true;
1900                                 continue;
1901                         }
1902
1903                         cf_log_err(ci, "Cannot have two 'default' case statements");
1904                         talloc_free(vpt);
1905                         return NULL;
1906                 }
1907         }
1908
1909         csingle = do_compile_modgroup(parent, component, cs,
1910                                       GROUPTYPE_SIMPLE,
1911                                       GROUPTYPE_SIMPLE,
1912                                       MOD_SWITCH);
1913         if (!csingle) {
1914                 talloc_free(vpt);
1915                 return NULL;
1916         }
1917
1918         g = mod_callabletogroup(csingle);
1919         g->vpt = talloc_steal(g, vpt);
1920
1921         return csingle;
1922 }
1923
1924 static modcallable *do_compile_modcase(modcallable *parent, rlm_components_t component, CONF_SECTION *cs)
1925 {
1926         int i;
1927         char const *name2;
1928         modcallable *csingle;
1929         modgroup *g;
1930         value_pair_tmpl_t *vpt;
1931
1932         if (!parent || (parent->type != MOD_SWITCH)) {
1933                 cf_log_err_cs(cs, "\"case\" statements may only appear within a \"switch\" section");
1934                 return NULL;
1935         }
1936
1937         /*
1938          *      case THING means "match THING"
1939          *      case       means "match anything"
1940          */
1941         name2 = cf_section_name2(cs);
1942         if (name2) {
1943                 ssize_t slen;
1944                 FR_TOKEN type;
1945
1946                 type = cf_section_name2_type(cs);
1947
1948                 slen = tmpl_afrom_str(cs, &vpt, name2, strlen(name2), type, REQUEST_CURRENT, PAIR_LIST_REQUEST);
1949                 if ((slen < 0) && ((type != T_BARE_WORD) || (name2[0] != '&'))) {
1950                         char *spaces, *text;
1951
1952                         fr_canonicalize_error(cs, &spaces, &text, slen, fr_strerror());
1953
1954                         cf_log_err_cs(cs, "Syntax error");
1955                         cf_log_err_cs(cs, "%s", name2);
1956                         cf_log_err_cs(cs, "%s^ %s", spaces, text);
1957
1958                         talloc_free(spaces);
1959                         talloc_free(text);
1960
1961                         return NULL;
1962                 }
1963
1964                 /*
1965                  *      Otherwise a NULL vpt may refer to an attribute defined
1966                  *      by a module.  That is checked in pass 2.
1967                  */
1968
1969         } else {
1970                 vpt = NULL;
1971         }
1972
1973         csingle = do_compile_modgroup(parent, component, cs,
1974                                       GROUPTYPE_SIMPLE,
1975                                       GROUPTYPE_SIMPLE,
1976                                       MOD_CASE);
1977         if (!csingle) {
1978                 talloc_free(vpt);
1979                 return NULL;
1980         }
1981
1982         /*
1983          *      The interpretor expects this to be NULL for the
1984          *      default case.  do_compile_modgroup sets it to name2,
1985          *      unless name2 is NULL, in which case it sets it to name1.
1986          */
1987         csingle->name = name2;
1988
1989         g = mod_callabletogroup(csingle);
1990         g->vpt = talloc_steal(g, vpt);
1991
1992         /*
1993          *      Set all of it's codes to return, so that
1994          *      when we pick a 'case' statement, we don't
1995          *      fall through to processing the next one.
1996          */
1997         for (i = 0; i < RLM_MODULE_NUMCODES; i++) {
1998                 csingle->actions[i] = MOD_ACTION_RETURN;
1999         }
2000
2001         return csingle;
2002 }
2003
2004 static modcallable *do_compile_modforeach(modcallable *parent,
2005                                           rlm_components_t component, CONF_SECTION *cs)
2006 {
2007         FR_TOKEN type;
2008         char const *name2;
2009         modcallable *csingle;
2010         modgroup *g;
2011         ssize_t slen;
2012         value_pair_tmpl_t *vpt;
2013
2014         name2 = cf_section_name2(cs);
2015         if (!name2) {
2016                 cf_log_err_cs(cs,
2017                            "You must specify an attribute to loop over in 'foreach'");
2018                 return NULL;
2019         }
2020
2021         if (!cf_item_find_next(cs, NULL)) {
2022                 cf_log_err_cs(cs, "'foreach' blocks cannot be empty");
2023                 return NULL;
2024         }
2025
2026         /*
2027          *      Create the template.  If we fail, AND it's a bare word
2028          *      with &Foo-Bar, it MAY be an attribute defined by a
2029          *      module.  Allow it for now.  The pass2 checks below
2030          *      will fix it up.
2031          */
2032         type = cf_section_name2_type(cs);
2033         slen = tmpl_afrom_str(cs, &vpt, name2, strlen(name2), type, REQUEST_CURRENT, PAIR_LIST_REQUEST);
2034         if ((slen < 0) && ((type != T_BARE_WORD) || (name2[0] != '&'))) {
2035                 char *spaces, *text;
2036
2037                 fr_canonicalize_error(cs, &spaces, &text, slen, fr_strerror());
2038
2039                 cf_log_err_cs(cs, "Syntax error");
2040                 cf_log_err_cs(cs, "%s", name2);
2041                 cf_log_err_cs(cs, "%s^ %s", spaces, text);
2042
2043                 talloc_free(spaces);
2044                 talloc_free(text);
2045
2046                 return NULL;
2047         }
2048
2049         /*
2050          *      If we don't have a negative return code, we must have a vpt
2051          *      (mostly to quiet coverity).
2052          */
2053         rad_assert(vpt);
2054
2055         if ((vpt->type != TMPL_TYPE_ATTR) && (vpt->type != TMPL_TYPE_LIST)) {
2056                 cf_log_err_cs(cs, "MUST use attribute or list reference in 'foreach'");
2057                 return NULL;
2058         }
2059
2060         /*
2061          *      Fix up the template to iterate over all instances of
2062          *      the attribute. In a perfect consistent world, users would do
2063          *      foreach &attr[*], but that's taking the consistency thing a bit far.
2064          */
2065         vpt->tmpl_num = NUM_ALL;
2066
2067         csingle = do_compile_modgroup(parent, component, cs,
2068                                       GROUPTYPE_SIMPLE, GROUPTYPE_SIMPLE,
2069                                       MOD_FOREACH);
2070
2071         if (!csingle) {
2072                 talloc_free(vpt);
2073                 return NULL;
2074         }
2075
2076         g = mod_callabletogroup(csingle);
2077         g->vpt = vpt;
2078
2079         return csingle;
2080 }
2081
2082 static modcallable *do_compile_modbreak(modcallable *parent,
2083                                         rlm_components_t component, CONF_ITEM const *ci)
2084 {
2085         CONF_SECTION const *cs = NULL;
2086
2087         for (cs = cf_item_parent(ci);
2088              cs != NULL;
2089              cs = cf_item_parent(cf_section_to_item(cs))) {
2090                 if (strcmp(cf_section_name1(cs), "foreach") == 0) {
2091                         break;
2092                 }
2093         }
2094
2095         if (!cs) {
2096                 cf_log_err(ci, "'break' can only be used in a 'foreach' section");
2097                 return NULL;
2098         }
2099
2100         return do_compile_modgroup(parent, component, NULL,
2101                                    GROUPTYPE_SIMPLE, GROUPTYPE_SIMPLE,
2102                                    MOD_BREAK);
2103 }
2104 #endif
2105
2106 static modcallable *do_compile_modserver(modcallable *parent,
2107                                          rlm_components_t component, CONF_ITEM *ci,
2108                                          char const *name,
2109                                          CONF_SECTION *cs,
2110                                          char const *server)
2111 {
2112         modcallable *csingle;
2113         CONF_SECTION *subcs;
2114         modref *mr;
2115
2116         subcs = cf_section_sub_find_name2(cs, comp2str[component], NULL);
2117         if (!subcs) {
2118                 cf_log_err(ci, "Server %s has no %s section",
2119                            server, comp2str[component]);
2120                 return NULL;
2121         }
2122
2123         mr = talloc_zero(parent, modref);
2124
2125         csingle = mod_reftocallable(mr);
2126         csingle->parent = parent;
2127         csingle->next = NULL;
2128         csingle->name = name;
2129         csingle->type = MOD_REFERENCE;
2130         csingle->method = component;
2131
2132         memcpy(csingle->actions, defaultactions[component][GROUPTYPE_SIMPLE],
2133                sizeof(csingle->actions));
2134
2135         mr->ref_name = strdup(server);
2136         mr->ref_cs = cs;
2137
2138         return csingle;
2139 }
2140
2141 static modcallable *do_compile_modxlat(modcallable *parent,
2142                                        rlm_components_t component, char const *fmt)
2143 {
2144         modcallable *csingle;
2145         modxlat *mx;
2146
2147         mx = talloc_zero(parent, modxlat);
2148
2149         csingle = mod_xlattocallable(mx);
2150         csingle->parent = parent;
2151         csingle->next = NULL;
2152         csingle->name = "expand";
2153         csingle->type = MOD_XLAT;
2154         csingle->method = component;
2155
2156         memcpy(csingle->actions, defaultactions[component][GROUPTYPE_SIMPLE],
2157                sizeof(csingle->actions));
2158
2159         mx->xlat_name = strdup(fmt);
2160         if (fmt[0] != '%') {
2161                 char *p;
2162                 mx->exec = true;
2163
2164                 strcpy(mx->xlat_name, fmt + 1);
2165                 p = strrchr(mx->xlat_name, '`');
2166                 if (p) *p = '\0';
2167         }
2168
2169         return csingle;
2170 }
2171
2172 /*
2173  *      redundant, etc. can refer to modules or groups, but not much else.
2174  */
2175 static int all_children_are_modules(CONF_SECTION *cs, char const *name)
2176 {
2177         CONF_ITEM *ci;
2178
2179         for (ci=cf_item_find_next(cs, NULL);
2180              ci != NULL;
2181              ci=cf_item_find_next(cs, ci)) {
2182                 /*
2183                  *      If we're a redundant, etc. group, then the
2184                  *      intention is to call modules, rather than
2185                  *      processing logic.  These checks aren't
2186                  *      *strictly* necessary, but they keep the users
2187                  *      from doing crazy things.
2188                  */
2189                 if (cf_item_is_section(ci)) {
2190                         CONF_SECTION *subcs = cf_item_to_section(ci);
2191                         char const *name1 = cf_section_name1(subcs);
2192
2193                         if ((strcmp(name1, "if") == 0) ||
2194                             (strcmp(name1, "else") == 0) ||
2195                             (strcmp(name1, "elsif") == 0) ||
2196                             (strcmp(name1, "update") == 0) ||
2197                             (strcmp(name1, "switch") == 0) ||
2198                             (strcmp(name1, "case") == 0)) {
2199                                 cf_log_err(ci, "%s sections cannot contain a \"%s\" statement",
2200                                        name, name1);
2201                                 return 0;
2202                         }
2203                         continue;
2204                 }
2205
2206                 if (cf_item_is_pair(ci)) {
2207                         CONF_PAIR *cp = cf_item_to_pair(ci);
2208                         if (cf_pair_value(cp) != NULL) {
2209                                 cf_log_err(ci,
2210                                            "Entry with no value is invalid");
2211                                 return 0;
2212                         }
2213                 }
2214         }
2215
2216         return 1;
2217 }
2218
2219
2220 /*
2221  *      Compile one entry of a module call.
2222  */
2223 static modcallable *do_compile_modsingle(modcallable *parent,
2224                                          rlm_components_t component, CONF_ITEM *ci,
2225                                          int grouptype,
2226                                          char const **modname)
2227 {
2228         char const *modrefname, *p;
2229         modsingle *single;
2230         modcallable *csingle;
2231         module_instance_t *this;
2232         CONF_SECTION *cs, *subcs, *modules;
2233         CONF_SECTION *loop;
2234         char const *realname;
2235         rlm_components_t method = component;
2236
2237         if (cf_item_is_section(ci)) {
2238                 char const *name2;
2239
2240                 cs = cf_item_to_section(ci);
2241                 modrefname = cf_section_name1(cs);
2242                 name2 = cf_section_name2(cs);
2243                 if (!name2) name2 = "";
2244
2245                 /*
2246                  *      group{}, redundant{}, or append{} may appear
2247                  *      where a single module instance was expected.
2248                  *      In that case, we hand it off to
2249                  *      compile_modgroup
2250                  */
2251                 if (strcmp(modrefname, "group") == 0) {
2252                         *modname = name2;
2253                         return do_compile_modgroup(parent, component, cs,
2254                                                    GROUPTYPE_SIMPLE,
2255                                                    grouptype, MOD_GROUP);
2256
2257                 } else if (strcmp(modrefname, "redundant") == 0) {
2258                         *modname = name2;
2259
2260                         if (!all_children_are_modules(cs, modrefname)) {
2261                                 return NULL;
2262                         }
2263
2264                         return do_compile_modgroup(parent, component, cs,
2265                                                    GROUPTYPE_REDUNDANT,
2266                                                    grouptype, MOD_GROUP);
2267
2268                 } else if (strcmp(modrefname, "append") == 0) {
2269                         *modname = name2;
2270                         return do_compile_modgroup(parent, component, cs,
2271                                                    GROUPTYPE_APPEND,
2272                                                    grouptype, MOD_GROUP);
2273
2274                 } else if (strcmp(modrefname, "load-balance") == 0) {
2275                         *modname = name2;
2276
2277                         if (!all_children_are_modules(cs, modrefname)) {
2278                                 return NULL;
2279                         }
2280
2281                         return do_compile_modgroup(parent, component, cs,
2282                                                    GROUPTYPE_SIMPLE,
2283                                                    grouptype, MOD_LOAD_BALANCE);
2284
2285                 } else if (strcmp(modrefname, "redundant-load-balance") == 0) {
2286                         *modname = name2;
2287
2288                         if (!all_children_are_modules(cs, modrefname)) {
2289                                 return NULL;
2290                         }
2291
2292                         return do_compile_modgroup(parent, component, cs,
2293                                                    GROUPTYPE_REDUNDANT,
2294                                                    grouptype, MOD_REDUNDANT_LOAD_BALANCE);
2295
2296 #ifdef WITH_UNLANG
2297                 } else  if (strcmp(modrefname, "if") == 0) {
2298                         if (!cf_section_name2(cs)) {
2299                                 cf_log_err(ci, "'if' without condition");
2300                                 return NULL;
2301                         }
2302
2303                         *modname = name2;
2304                         csingle= do_compile_modgroup(parent, component, cs,
2305                                                      GROUPTYPE_SIMPLE,
2306                                                      grouptype, MOD_IF);
2307                         if (!csingle) return NULL;
2308                         *modname = name2;
2309
2310                         return csingle;
2311
2312                 } else  if (strcmp(modrefname, "elsif") == 0) {
2313                         if (parent &&
2314                             ((parent->type == MOD_LOAD_BALANCE) ||
2315                              (parent->type == MOD_REDUNDANT_LOAD_BALANCE))) {
2316                                 cf_log_err(ci, "'elsif' cannot be used in this section");
2317                                 return NULL;
2318                         }
2319
2320                         if (!cf_section_name2(cs)) {
2321                                 cf_log_err(ci, "'elsif' without condition");
2322                                 return NULL;
2323                         }
2324
2325                         *modname = name2;
2326                         return do_compile_modgroup(parent, component, cs,
2327                                                    GROUPTYPE_SIMPLE,
2328                                                    grouptype, MOD_ELSIF);
2329
2330                 } else  if (strcmp(modrefname, "else") == 0) {
2331                         if (parent &&
2332                             ((parent->type == MOD_LOAD_BALANCE) ||
2333                              (parent->type == MOD_REDUNDANT_LOAD_BALANCE))) {
2334                                 cf_log_err(ci, "'else' cannot be used in this section section");
2335                                 return NULL;
2336                         }
2337
2338                         if (cf_section_name2(cs)) {
2339                                 cf_log_err(ci, "Cannot have conditions on 'else'");
2340                                 return NULL;
2341                         }
2342
2343                         *modname = name2;
2344                         return  do_compile_modgroup(parent, component, cs,
2345                                                     GROUPTYPE_SIMPLE,
2346                                                     grouptype, MOD_ELSE);
2347
2348                 } else  if (strcmp(modrefname, "update") == 0) {
2349                         *modname = name2;
2350
2351                         return do_compile_modupdate(parent, component, cs,
2352                                                     name2);
2353
2354                 } else  if (strcmp(modrefname, "switch") == 0) {
2355                         *modname = name2;
2356
2357                         return do_compile_modswitch (parent, component, cs);
2358
2359                 } else  if (strcmp(modrefname, "case") == 0) {
2360                         *modname = name2;
2361
2362                         return do_compile_modcase(parent, component, cs);
2363
2364                 } else  if (strcmp(modrefname, "foreach") == 0) {
2365                         *modname = name2;
2366
2367                         return do_compile_modforeach(parent, component, cs);
2368
2369 #endif
2370                 } /* else it's something like sql { fail = 1 ...} */
2371
2372         } else if (!cf_item_is_pair(ci)) { /* CONF_DATA or some such */
2373                 return NULL;
2374
2375                 /*
2376                  *      Else it's a module reference, with updated return
2377                  *      codes.
2378                  */
2379         } else {
2380                 CONF_PAIR *cp = cf_item_to_pair(ci);
2381                 modrefname = cf_pair_attr(cp);
2382
2383                 /*
2384                  *      Actions (ok = 1), etc. are orthogonal to just
2385                  *      about everything else.
2386                  */
2387                 if (cf_pair_value(cp) != NULL) {
2388                         cf_log_err(ci, "Entry is not a reference to a module");
2389                         return NULL;
2390                 }
2391
2392                 /*
2393                  *      In-place xlat's via %{...}.
2394                  *
2395                  *      This should really be removed from the server.
2396                  */
2397                 if (((modrefname[0] == '%') && (modrefname[1] == '{')) ||
2398                     (modrefname[0] == '`')) {
2399                         return do_compile_modxlat(parent, component,
2400                                                   modrefname);
2401                 }
2402         }
2403
2404 #ifdef WITH_UNLANG
2405         /*
2406          *      These can't be over-ridden.
2407          */
2408         if (strcmp(modrefname, "break") == 0) {
2409                 if (!cf_item_is_pair(ci)) {
2410                         cf_log_err(ci, "Invalid use of 'break' as section name.");
2411                         return NULL;
2412                 }
2413
2414                 return do_compile_modbreak(parent, component, ci);
2415         }
2416
2417         if (strcmp(modrefname, "return") == 0) {
2418                 if (!cf_item_is_pair(ci)) {
2419                         cf_log_err(ci, "Invalid use of 'return' as section name.");
2420                         return NULL;
2421                 }
2422
2423                 return do_compile_modgroup(parent, component, NULL,
2424                                            GROUPTYPE_SIMPLE, GROUPTYPE_SIMPLE,
2425                                            MOD_RETURN);
2426         }
2427 #endif
2428
2429         /*
2430          *      Run a virtual server.  This is really terrible and
2431          *      should be deleted.
2432          */
2433         if (strncmp(modrefname, "server[", 7) == 0) {
2434                 char buffer[256];
2435
2436                 if (!cf_item_is_pair(ci)) {
2437                         cf_log_err(ci, "Invalid syntax");
2438                         return NULL;
2439                 }
2440
2441                 strlcpy(buffer, modrefname + 7, sizeof(buffer));
2442                 p = strrchr(buffer, ']');
2443                 if (!p || p[1] != '\0' || (p == buffer)) {
2444                         cf_log_err(ci, "Invalid server reference in \"%s\".", modrefname);
2445                         return NULL;
2446                 }
2447
2448                 buffer[p - buffer] = '\0';
2449
2450                 cs = cf_section_sub_find_name2(NULL, "server", buffer);
2451                 if (!cs) {
2452                         cf_log_err(ci, "No such server \"%s\".", buffer);
2453                         return NULL;
2454                 }
2455
2456                 /*
2457                  *      Ignore stupid attempts to over-ride the return
2458                  *      code.
2459                  */
2460                 return do_compile_modserver(parent, component, ci,
2461                                             modrefname, cs, buffer);
2462         }
2463
2464         /*
2465          *      We now have a name.  It can be one of two forms.  A
2466          *      bare module name, or a section named for the module,
2467          *      with over-rides for the return codes.
2468          *
2469          *      The name can refer to a real module, in the "modules"
2470          *      section.  In that case, the name will be either the
2471          *      first or second name of the sub-section of "modules".
2472          *
2473          *      Or, the name can refer to a policy, in the "policy"
2474          *      section.  In that case, the name will be first name of
2475          *      the sub-section of "policy".  Unless it's a "redudant"
2476          *      block...
2477          *
2478          *      Or, the name can refer to a "module.method", in which
2479          *      case we're calling a different method than normal for
2480          *      this section.
2481          *
2482          *      Or, the name can refer to a virtual module, in the
2483          *      "instantiate" section.  In that case, the name will be
2484          *      the first of the sub-section of "instantiate".  Unless
2485          *      it's a "redudant" block...
2486          *
2487          *      We try these in sequence, from the bottom up.  This is
2488          *      so that things in "instantiate" and "policy" can
2489          *      over-ride calls to real modules.
2490          */
2491
2492
2493         /*
2494          *      Try:
2495          *
2496          *      instantiate { ... name { ...} ... }
2497          *      instantiate { ... name.method { ...} ... }
2498          *      policy { ... name { .. } .. }
2499          *      policy { ... name.method { .. } .. }
2500          *
2501          *      The "instantiate" virtual modules are identical to the
2502          *      policies at this point.  We should probably get rid of
2503          *      the "instantiate" ones, as they're duplicate and
2504          *      confusing.
2505          */
2506         subcs = NULL;
2507         cs = cf_section_find("instantiate");
2508         if (cs) subcs = cf_section_sub_find_name2(cs, NULL,
2509                                                   modrefname);
2510         if (!subcs &&
2511             (cs = cf_section_find("policy")) != NULL) {
2512                 char buffer[256];
2513
2514                 snprintf(buffer, sizeof(buffer), "%s.%s",
2515                          modrefname, comp2str[component]);
2516
2517                 /*
2518                  *      Prefer name.section, then name.
2519                  */
2520                 subcs = cf_section_sub_find_name2(cs, NULL,
2521                                                           buffer);
2522                 if (!subcs) {
2523                         subcs = cf_section_sub_find_name2(cs, NULL,
2524                                                           modrefname);
2525                 }
2526         }
2527
2528         /*
2529          *      Check that we're not creating a loop.  We may
2530          *      be compiling an "sql" module reference inside
2531          *      of an "sql" policy.  If so, we allow the
2532          *      second "sql" to refer to the module.
2533          */
2534         for (loop = cf_item_parent(ci);
2535              loop && subcs;
2536              loop = cf_item_parent(cf_section_to_item(loop))) {
2537                 if (loop == subcs) {
2538                         subcs = NULL;
2539                 }
2540         }
2541
2542         /*
2543          *      We've found the relevant entry.  It MUST be a
2544          *      sub-section.
2545          *
2546          *      However, it can be a "redundant" block, or just a
2547          *      section name.
2548          */
2549         if (subcs) {
2550                 /*
2551                  *      modules.c takes care of ensuring that this is:
2552                  *
2553                  *      group foo { ...
2554                  *      load-balance foo { ...
2555                  *      redundant foo { ...
2556                  *      redundant-load-balance foo { ...
2557                  *
2558                  *      We can just recurs to compile the section as
2559                  *      if it was found here.
2560                  */
2561                 if (cf_section_name2(subcs)) {
2562                         csingle = do_compile_modsingle(parent,
2563                                                        component,
2564                                                        cf_section_to_item(subcs),
2565                                                        grouptype,
2566                                                        modname);
2567                 } else {
2568                         /*
2569                          *      We have:
2570                          *
2571                          *      foo { ...
2572                          *
2573                          *      So we compile it like it was:
2574                          *
2575                          *      group foo { ...
2576                          */
2577                         csingle = do_compile_modgroup(parent,
2578                                                       component,
2579                                                       subcs,
2580                                                       GROUPTYPE_SIMPLE,
2581                                                       grouptype, MOD_GROUP);
2582                 }
2583
2584                 /*
2585                  *      Return the compiled thing if we can.
2586                  */
2587                 if (!csingle) return NULL;
2588                 if (cf_item_is_pair(ci)) return csingle;
2589
2590                 /*
2591                  *      Else we have a reference to a policy, and that reference
2592                  *      over-rides the return codes for the policy!
2593                  */
2594                 goto action_override;
2595         }
2596
2597         /*
2598          *      Not a virtual module.  It must be a real module.
2599          */
2600         modules = cf_section_find("modules");
2601         this = NULL;
2602         realname = modrefname;
2603
2604         if (modules) {
2605                 /*
2606                  *      Try to load the optional module.
2607                  */
2608                 if (realname[0] == '-') realname++;
2609
2610                 /*
2611                  *      As of v3, the "modules" section contains
2612                  *      modules we use.  Configuration for other
2613                  *      modules belongs in raddb/mods-available/,
2614                  *      which isn't loaded into the "modules" section.
2615                  */
2616                 if (cf_section_sub_find_name2(modules, NULL, realname)) {
2617                         this = find_module_instance(modules, realname, true);
2618                         if (this) goto allocate_csingle;
2619
2620                         /*
2621                          *
2622                          */
2623                         if (realname != modrefname) {
2624                                 return NULL;
2625                         }
2626
2627                 } else {
2628                         /*
2629                          *      We were asked to MAYBE load it and it
2630                          *      doesn't exist.  Return a soft error.
2631                          */
2632                         if (realname != modrefname) {
2633                                 *modname = modrefname;
2634                                 return NULL;
2635                         }
2636                 }
2637         }
2638
2639         /*
2640          *      No module found by that name.  Maybe we're calling
2641          *      module.method
2642          */
2643         p = strrchr(modrefname, '.');
2644         if (p) {
2645                 rlm_components_t i;
2646                 p++;
2647
2648                 /*
2649                  *      Find the component.
2650                  */
2651                 for (i = RLM_COMPONENT_AUTH;
2652                      i < RLM_COMPONENT_COUNT;
2653                      i++) {
2654                         if (strcmp(p, comp2str[i]) == 0) {
2655                                 char buffer[256];
2656
2657                                 strlcpy(buffer, modrefname, sizeof(buffer));
2658                                 buffer[p - modrefname - 1] = '\0';
2659                                 component = i;
2660
2661                                 this = find_module_instance(modules, buffer, true);
2662                                 if (this) {
2663                                         method = i;
2664                                         goto allocate_csingle;
2665                                 }
2666                         }
2667                 }
2668
2669                 /*
2670                  *      FIXME: check for "module", and give error "no
2671                  *      such component" when we don't find the method.
2672                  */
2673         }
2674
2675         /*
2676          *      Can't de-reference it to anything.  Ugh.
2677          */
2678         *modname = NULL;
2679         cf_log_err(ci, "Failed to find \"%s\" as a module or policy.", modrefname);
2680         cf_log_err(ci, "Please verify that the configuration exists in %s/mods-enabled/%s.", get_radius_dir(), modrefname);
2681         return NULL;
2682
2683         /*
2684          *      We know it's all OK, allocate the structures, and fill
2685          *      them in.
2686          */
2687 allocate_csingle:
2688         /*
2689          *      Check if the module in question has the necessary
2690          *      component.
2691          */
2692         if (!this->entry->module->methods[method]) {
2693                 cf_log_err(ci, "\"%s\" modules aren't allowed in '%s' sections -- they have no such method.", this->entry->module->name,
2694                            comp2str[method]);
2695                 return NULL;
2696         }
2697
2698         single = talloc_zero(parent, modsingle);
2699         single->modinst = this;
2700         *modname = this->entry->module->name;
2701
2702         csingle = mod_singletocallable(single);
2703         csingle->parent = parent;
2704         csingle->next = NULL;
2705         if (!parent || (component != RLM_COMPONENT_AUTH)) {
2706                 memcpy(csingle->actions, defaultactions[component][grouptype],
2707                        sizeof csingle->actions);
2708         } else { /* inside Auth-Type has different rules */
2709                 memcpy(csingle->actions, defaultactions[RLM_COMPONENT_AUTZ][grouptype],
2710                        sizeof csingle->actions);
2711         }
2712         rad_assert(modrefname != NULL);
2713         csingle->name = realname;
2714         csingle->type = MOD_SINGLE;
2715         csingle->method = method;
2716
2717 action_override:
2718         /*
2719          *      Over-ride the default return codes of the module.
2720          */
2721         if (cf_item_is_section(ci)) {
2722                 CONF_ITEM *csi;
2723
2724                 cs = cf_item_to_section(ci);
2725                 for (csi=cf_item_find_next(cs, NULL);
2726                      csi != NULL;
2727                      csi=cf_item_find_next(cs, csi)) {
2728
2729                         if (cf_item_is_section(csi)) {
2730                                 cf_log_err(csi, "Subsection of module instance call not allowed");
2731                                 talloc_free(csingle);
2732                                 return NULL;
2733                         }
2734
2735                         if (!cf_item_is_pair(csi)) continue;
2736
2737                         if (!compile_action(csingle, cf_item_to_pair(csi))) {
2738                                 talloc_free(csingle);
2739                                 return NULL;
2740                         }
2741                 }
2742         }
2743
2744         return csingle;
2745 }
2746
2747 modcallable *compile_modsingle(TALLOC_CTX *ctx,
2748                                modcallable **parent,
2749                                rlm_components_t component, CONF_ITEM *ci,
2750                                char const **modname)
2751 {
2752         modcallable *ret;
2753
2754         if (!*parent) {
2755                 modcallable *c;
2756                 modgroup *g;
2757                 CONF_SECTION *parentcs;
2758
2759                 g = talloc_zero(ctx, modgroup);
2760                 memset(g, 0, sizeof(*g));
2761                 g->grouptype = GROUPTYPE_SIMPLE;
2762                 c = mod_grouptocallable(g);
2763                 c->next = NULL;
2764                 memcpy(c->actions,
2765                        defaultactions[component][GROUPTYPE_SIMPLE],
2766                        sizeof(c->actions));
2767
2768                 parentcs = cf_item_parent(ci);
2769                 c->name = cf_section_name2(parentcs);
2770                 if (!c->name) {
2771                         c->name = cf_section_name1(parentcs);
2772                 }
2773
2774                 c->type = MOD_GROUP;
2775                 c->method = component;
2776                 g->children = NULL;
2777
2778                 *parent = mod_grouptocallable(g);
2779         }
2780
2781         ret = do_compile_modsingle(*parent, component, ci,
2782                                    GROUPTYPE_SIMPLE,
2783                                    modname);
2784         dump_tree(component, ret);
2785         return ret;
2786 }
2787
2788
2789 /*
2790  *      Internal compile group code.
2791  */
2792 static modcallable *do_compile_modgroup(modcallable *parent,
2793                                         rlm_components_t component, CONF_SECTION *cs,
2794                                         int grouptype, int parentgrouptype, int mod_type)
2795 {
2796         int i;
2797         modgroup *g;
2798         modcallable *c;
2799         CONF_ITEM *ci;
2800
2801         g = talloc_zero(parent, modgroup);
2802         g->grouptype = grouptype;
2803         g->children = NULL;
2804         g->cs = cs;
2805
2806         c = mod_grouptocallable(g);
2807         c->parent = parent;
2808         c->type = mod_type;
2809         c->next = NULL;
2810         memset(c->actions, 0, sizeof(c->actions));
2811
2812         if (!cs) {              /* only for "break" and "return" */
2813                 c->name = "";
2814                 goto set_codes;
2815         }
2816
2817         /*
2818          *      Remember the name for printing, etc.
2819          *
2820          *      FIXME: We may also want to put the names into a
2821          *      rbtree, so that groups can reference each other...
2822          */
2823         c->name = cf_section_name2(cs);
2824         if (!c->name) {
2825                 c->name = cf_section_name1(cs);
2826                 if ((strcmp(c->name, "group") == 0) ||
2827                     (strcmp(c->name, "redundant") == 0)) {
2828                         c->name = "";
2829                 } else if (c->type == MOD_GROUP) {
2830                         c->type = MOD_POLICY;
2831                 }
2832         }
2833
2834 #ifdef WITH_UNLANG
2835         /*
2836          *      Do load-time optimizations
2837          */
2838         if ((c->type == MOD_IF) || (c->type == MOD_ELSIF) || (c->type == MOD_ELSE)) {
2839                 modgroup *f, *p;
2840
2841                 rad_assert(parent != NULL);
2842
2843                 if (c->type == MOD_IF) {
2844                         g->cond = cf_data_find(g->cs, "if");
2845                         rad_assert(g->cond != NULL);
2846
2847                 check_if:
2848                         if (g->cond->type == COND_TYPE_FALSE) {
2849                                 INFO(" # Skipping contents of '%s' as it is always 'false' -- %s:%d",
2850                                      unlang_keyword[g->mc.type],
2851                                      cf_section_filename(g->cs), cf_section_lineno(g->cs));
2852                                 goto set_codes;
2853                         }
2854
2855                 } else if (c->type == MOD_ELSIF) {
2856
2857                         g->cond = cf_data_find(g->cs, "if");
2858                         rad_assert(g->cond != NULL);
2859
2860                         rad_assert(parent != NULL);
2861                         p = mod_callabletogroup(parent);
2862
2863                         rad_assert(p->tail != NULL);
2864
2865                         f = mod_callabletogroup(p->tail);
2866                         rad_assert((f->mc.type == MOD_IF) ||
2867                                    (f->mc.type == MOD_ELSIF));
2868
2869                         /*
2870                          *      If we took the previous condition, we
2871                          *      don't need to take this one.
2872                          *
2873                          *      We reset our condition to 'true', so
2874                          *      that subsequent sections can check
2875                          *      that they don't need to be executed.
2876                          */
2877                         if (f->cond->type == COND_TYPE_TRUE) {
2878                         skip_true:
2879                                 INFO(" # Skipping contents of '%s' as previous '%s' is always  'true' -- %s:%d",
2880                                      unlang_keyword[g->mc.type],
2881                                      unlang_keyword[f->mc.type],
2882                                      cf_section_filename(g->cs), cf_section_lineno(g->cs));
2883                                 g->cond = f->cond;
2884                                 goto set_codes;
2885                         }
2886                         goto check_if;
2887
2888                 } else {
2889                         rad_assert(c->type == MOD_ELSE);
2890
2891                         rad_assert(parent != NULL);
2892                         p = mod_callabletogroup(parent);
2893
2894                         rad_assert(p->tail != NULL);
2895
2896                         f = mod_callabletogroup(p->tail);
2897                         rad_assert((f->mc.type == MOD_IF) ||
2898                                    (f->mc.type == MOD_ELSIF));
2899
2900                         /*
2901                          *      If we took the previous condition, we
2902                          *      don't need to take this one.
2903                          */
2904                         if (f->cond->type == COND_TYPE_TRUE) goto skip_true;
2905                 }
2906
2907                 /*
2908                  *      Else we need to compile this section
2909                  */
2910         }
2911 #endif
2912
2913         /*
2914          *      Loop over the children of this group.
2915          */
2916         for (ci=cf_item_find_next(cs, NULL);
2917              ci != NULL;
2918              ci=cf_item_find_next(cs, ci)) {
2919
2920                 /*
2921                  *      Sections are references to other groups, or
2922                  *      to modules with updated return codes.
2923                  */
2924                 if (cf_item_is_section(ci)) {
2925                         char const *junk = NULL;
2926                         modcallable *single;
2927                         CONF_SECTION *subcs = cf_item_to_section(ci);
2928
2929                         single = do_compile_modsingle(c, component, ci,
2930                                                       grouptype, &junk);
2931                         if (!single) {
2932                                 cf_log_err(ci, "Failed to parse \"%s\" subsection.",
2933                                        cf_section_name1(subcs));
2934                                 talloc_free(c);
2935                                 return NULL;
2936                         }
2937                         add_child(g, single);
2938
2939                 } else if (!cf_item_is_pair(ci)) { /* CONF_DATA */
2940                         continue;
2941
2942                 } else {
2943                         char const *attr, *value;
2944                         CONF_PAIR *cp = cf_item_to_pair(ci);
2945
2946                         attr = cf_pair_attr(cp);
2947                         value = cf_pair_value(cp);
2948
2949                         /*
2950                          *      A CONF_PAIR is either a module
2951                          *      instance with no actions
2952                          *      specified ...
2953                          */
2954                         if (!value) {
2955                                 modcallable *single;
2956                                 char const *junk = NULL;
2957
2958                                 single = do_compile_modsingle(c,
2959                                                               component,
2960                                                               ci,
2961                                                               grouptype,
2962                                                               &junk);
2963                                 if (!single) {
2964                                         if (cf_item_is_pair(ci) &&
2965                                             cf_pair_attr(cf_item_to_pair(ci))[0] == '-') {
2966                                                 continue;
2967                                         }
2968
2969                                         cf_log_err(ci,
2970                                                    "Failed to parse \"%s\" entry.",
2971                                                    attr);
2972                                         talloc_free(c);
2973                                         return NULL;
2974                                 }
2975                                 add_child(g, single);
2976
2977                                 /*
2978                                  *      Or a module instance with action.
2979                                  */
2980                         } else if (!compile_action(c, cp)) {
2981                                 talloc_free(c);
2982                                 return NULL;
2983                         } /* else it worked */
2984                 }
2985         }
2986
2987 set_codes:
2988         /*
2989          *      Set the default actions, if they haven't already been
2990          *      set.
2991          */
2992         for (i = 0; i < RLM_MODULE_NUMCODES; i++) {
2993                 if (!c->actions[i]) {
2994                         if (!parent || (component != RLM_COMPONENT_AUTH)) {
2995                                 c->actions[i] = defaultactions[component][parentgrouptype][i];
2996                         } else { /* inside Auth-Type has different rules */
2997                                 c->actions[i] = defaultactions[RLM_COMPONENT_AUTZ][parentgrouptype][i];
2998                         }
2999                 }
3000         }
3001
3002         switch (c->type) {
3003         default:
3004                 break;
3005
3006         case MOD_GROUP:
3007                 if (grouptype != GROUPTYPE_REDUNDANT) break;
3008                 /* FALL-THROUGH */
3009
3010         case MOD_LOAD_BALANCE:
3011         case MOD_REDUNDANT_LOAD_BALANCE:
3012                 if (!g->children) {
3013                         cf_log_err_cs(g->cs, "%s sections cannot be empty",
3014                                       cf_section_name1(g->cs));
3015                         talloc_free(c);
3016                         return NULL;
3017                 }
3018         }
3019
3020         /*
3021          *      FIXME: If there are no children, return NULL?
3022          */
3023         return mod_grouptocallable(g);
3024 }
3025
3026 modcallable *compile_modgroup(modcallable *parent,
3027                               rlm_components_t component, CONF_SECTION *cs)
3028 {
3029         modcallable *ret = do_compile_modgroup(parent, component, cs,
3030                                                GROUPTYPE_SIMPLE,
3031                                                GROUPTYPE_SIMPLE, MOD_GROUP);
3032
3033         if (debug_flag > 3) {
3034                 modcall_debug(ret, 2);
3035         }
3036
3037         return ret;
3038 }
3039
3040 void add_to_modcallable(modcallable *parent, modcallable *this)
3041 {
3042         modgroup *g;
3043
3044         rad_assert(this != NULL);
3045         rad_assert(parent != NULL);
3046
3047         g = mod_callabletogroup(parent);
3048
3049         add_child(g, this);
3050 }
3051
3052
3053 #ifdef WITH_UNLANG
3054 static bool pass2_xlat_compile(CONF_ITEM const *ci, value_pair_tmpl_t **pvpt, bool convert,
3055                                DICT_ATTR const *da)
3056 {
3057         ssize_t slen;
3058         char *fmt;
3059         char const *error;
3060         xlat_exp_t *head;
3061         value_pair_tmpl_t *vpt;
3062
3063         vpt = *pvpt;
3064
3065         rad_assert(vpt->type == TMPL_TYPE_XLAT);
3066
3067         fmt = talloc_typed_strdup(vpt, vpt->name);
3068         slen = xlat_tokenize(vpt, fmt, &head, &error);
3069
3070         if (slen < 0) {
3071                 char *spaces, *text;
3072
3073                 fr_canonicalize_error(vpt, &spaces, &text, slen, vpt->name);
3074
3075                 cf_log_err(ci, "Failed parsing expanded string:");
3076                 cf_log_err(ci, "%s", text);
3077                 cf_log_err(ci, "%s^ %s", spaces, error);
3078
3079                 talloc_free(spaces);
3080                 talloc_free(text);
3081                 return false;
3082         }
3083
3084         /*
3085          *      Convert %{Attribute-Name} to &Attribute-Name
3086          */
3087         if (convert) {
3088                 value_pair_tmpl_t *attr;
3089
3090                 attr = xlat_to_tmpl_attr(talloc_parent(vpt), head);
3091                 if (attr) {
3092                         /*
3093                          *      If it's a virtual attribute, leave it
3094                          *      alone.
3095                          */
3096                         if (attr->tmpl_da->flags.virtual) {
3097                                 talloc_free(attr);
3098                                 return true;
3099                         }
3100
3101                         /*
3102                          *      If the attribute is of incompatible
3103                          *      type, leave it alone.
3104                          */
3105                         if (da && (da->type != attr->tmpl_da->type)) {
3106                                 talloc_free(attr);
3107                                 return true;
3108                         }
3109
3110                         if (cf_item_is_pair(ci)) {
3111                                 CONF_PAIR *cp = cf_item_to_pair(ci);
3112
3113                                 WARN("%s[%d] Please change %%{%s} to &%s",
3114                                        cf_pair_filename(cp), cf_pair_lineno(cp),
3115                                        attr->name, attr->name);
3116                         } else {
3117                                 CONF_SECTION *cs = cf_item_to_section(ci);
3118
3119                                 WARN("%s[%d] Please change %%{%s} to &%s",
3120                                        cf_section_filename(cs), cf_section_lineno(cs),
3121                                        attr->name, attr->name);
3122                         }
3123                         TALLOC_FREE(*pvpt);
3124                         *pvpt = attr;
3125                         return true;
3126                 }
3127         }
3128
3129         /*
3130          *      Re-write it to be a pre-parsed XLAT structure.
3131          */
3132         vpt->type = TMPL_TYPE_XLAT_STRUCT;
3133         vpt->tmpl_xlat = head;
3134
3135         return true;
3136 }
3137
3138
3139 #ifdef HAVE_REGEX
3140 static bool pass2_regex_compile(CONF_ITEM const *ci, value_pair_tmpl_t *vpt)
3141 {
3142         ssize_t slen;
3143         regex_t *preg;
3144
3145         rad_assert(vpt->type == TMPL_TYPE_REGEX);
3146
3147         /*
3148          *      It's a dynamic expansion.  We can't expand the string,
3149          *      but we can pre-parse it as an xlat struct.  In that
3150          *      case, we convert it to a pre-compiled XLAT.
3151          *
3152          *      This is a little more complicated than it needs to be
3153          *      because radius_evaluate_map() keys off of the src
3154          *      template type, instead of the operators.  And, the
3155          *      pass2_xlat_compile() function expects to get passed an
3156          *      XLAT instead of a REGEX.
3157          */
3158         if (strchr(vpt->name, '%')) {
3159                 vpt->type = TMPL_TYPE_XLAT;
3160                 return pass2_xlat_compile(ci, &vpt, false, NULL);
3161         }
3162
3163         slen = regex_compile(vpt, &preg, vpt->name, vpt->len,
3164                              vpt->tmpl_iflag, vpt->tmpl_mflag, true, false);
3165         if (slen <= 0) {
3166                 char *spaces, *text;
3167
3168                 fr_canonicalize_error(vpt, &spaces, &text, slen, vpt->name);
3169
3170                 cf_log_err(ci, "Invalid regular expression:");
3171                 cf_log_err(ci, "%s", text);
3172                 cf_log_err(ci, "%s^ %s", spaces, fr_strerror());
3173
3174                 talloc_free(spaces);
3175                 talloc_free(text);
3176
3177                 return false;
3178         }
3179
3180         vpt->type = TMPL_TYPE_REGEX_STRUCT;
3181         vpt->tmpl_preg = preg;
3182
3183         return true;
3184 }
3185 #endif
3186
3187 static bool pass2_fixup_undefined(CONF_ITEM const *ci, value_pair_tmpl_t *vpt)
3188 {
3189         DICT_ATTR const *da;
3190
3191         rad_assert(vpt->type == TMPL_TYPE_ATTR_UNDEFINED);
3192
3193         da = dict_attrbyname(vpt->tmpl_unknown_name);
3194         if (!da) {
3195                 cf_log_err(ci, "Unknown attribute '%s'", vpt->tmpl_unknown_name);
3196                 return false;
3197         }
3198
3199         vpt->tmpl_da = da;
3200         vpt->type = TMPL_TYPE_ATTR;
3201         return true;
3202 }
3203
3204 static bool pass2_callback(UNUSED void *ctx, fr_cond_t *c)
3205 {
3206         value_pair_map_t *map;
3207
3208         if (c->type == COND_TYPE_EXISTS) {
3209                 if (c->data.vpt->type == TMPL_TYPE_XLAT) {
3210                         return pass2_xlat_compile(c->ci, &c->data.vpt, true, NULL);
3211                 }
3212
3213                 rad_assert(c->data.vpt->type != TMPL_TYPE_REGEX);
3214
3215                 /*
3216                  *      The existence check might have been &Foo-Bar,
3217                  *      where Foo-Bar is defined by a module.
3218                  */
3219                 if (c->pass2_fixup == PASS2_FIXUP_ATTR) {
3220                         if (!pass2_fixup_undefined(c->ci, c->data.vpt)) return false;
3221                         c->pass2_fixup = PASS2_FIXUP_NONE;
3222                 }
3223                 return true;
3224         }
3225
3226         /*
3227          *      Maps have a paircompare fixup applied to them.
3228          *      Others get ignored.
3229          */
3230         if (c->pass2_fixup == PASS2_FIXUP_NONE) {
3231                 if (c->type == COND_TYPE_MAP) {
3232                         map = c->data.map;
3233                         goto check_paircmp;
3234                 }
3235
3236                 return true;
3237         }
3238
3239         map = c->data.map;      /* shorter */
3240
3241         /*
3242          *      Auth-Type := foo
3243          *
3244          *      Where "foo" is dynamically defined.
3245          */
3246         if (c->pass2_fixup == PASS2_FIXUP_TYPE) {
3247                 if (!dict_valbyname(map->lhs->tmpl_da->attr,
3248                                     map->lhs->tmpl_da->vendor,
3249                                     map->rhs->name)) {
3250                         cf_log_err(map->ci, "Invalid reference to non-existent %s %s { ... }",
3251                                    map->lhs->tmpl_da->name,
3252                                    map->rhs->name);
3253                         return false;
3254                 }
3255
3256                 /*
3257                  *      These guys can't have a paircompare fixup applied.
3258                  */
3259                 c->pass2_fixup = PASS2_FIXUP_NONE;
3260                 return true;
3261         }
3262
3263         if (c->pass2_fixup == PASS2_FIXUP_ATTR) {
3264                 if (map->lhs->type == TMPL_TYPE_ATTR_UNDEFINED) {
3265                         if (!pass2_fixup_undefined(map->ci, map->lhs)) return false;
3266                 }
3267
3268                 if (map->rhs->type == TMPL_TYPE_ATTR_UNDEFINED) {
3269                         if (!pass2_fixup_undefined(map->ci, map->rhs)) return false;
3270                 }
3271
3272                 c->pass2_fixup = PASS2_FIXUP_NONE;
3273         }
3274
3275 check_paircmp:
3276         /*
3277          *      Just in case someone adds a new fixup later.
3278          */
3279         rad_assert((c->pass2_fixup == PASS2_FIXUP_NONE) ||
3280                    (c->pass2_fixup == PASS2_PAIRCOMPARE));
3281
3282         /*
3283          *      Precompile xlat's
3284          */
3285         if (map->lhs->type == TMPL_TYPE_XLAT) {
3286                 /*
3287                  *      Don't compile the LHS to an attribute
3288                  *      reference for now.  When we do that, we've got
3289                  *      to check the RHS for type-specific data, and
3290                  *      parse it to a TMPL_TYPE_DATA.
3291                  */
3292                 if (!pass2_xlat_compile(map->ci, &map->lhs, false, NULL)) {
3293                         return false;
3294                 }
3295         }
3296
3297         if (map->rhs->type == TMPL_TYPE_XLAT) {
3298                 /*
3299                  *      Convert the RHS to an attribute reference only
3300                  *      if the LHS is an attribute reference, AND is
3301                  *      of the same type as the RHS.
3302                  *
3303                  *      We can fix this when the code in evaluate.c
3304                  *      can handle strings on the LHS, and attributes
3305                  *      on the RHS.  For now, the code in parser.c
3306                  *      forbids this.
3307                  */
3308                 if (map->lhs->type == TMPL_TYPE_ATTR) {
3309                         DICT_ATTR const *da = c->cast;
3310
3311                         if (!c->cast) da = map->lhs->tmpl_da;
3312
3313                         if (!pass2_xlat_compile(map->ci, &map->rhs, true, da)) {
3314                                 return false;
3315                         }
3316
3317                 } else {
3318                         if (!pass2_xlat_compile(map->ci, &map->rhs, false, NULL)) {
3319                                 return false;
3320                         }
3321                 }
3322         }
3323
3324         /*
3325          *      Convert bare refs to %{Foreach-Variable-N}
3326          */
3327         if ((map->lhs->type == TMPL_TYPE_LITERAL) &&
3328             (strncmp(map->lhs->name, "Foreach-Variable-", 17) == 0)) {
3329                 char *fmt;
3330                 ssize_t slen;
3331                 value_pair_tmpl_t *vpt;
3332
3333                 fmt = talloc_asprintf(map->lhs, "%%{%s}", map->lhs->name);
3334                 slen = tmpl_afrom_str(map, &vpt, fmt, talloc_array_length(fmt) - 1,
3335                                       T_DOUBLE_QUOTED_STRING, REQUEST_CURRENT, PAIR_LIST_REQUEST);
3336                 if (slen < 0) {
3337                         char *spaces, *text;
3338
3339                         fr_canonicalize_error(map->ci, &spaces, &text, slen, fr_strerror());
3340
3341                         cf_log_err(map->ci, "Failed converting %s to xlat", map->lhs->name);
3342                         cf_log_err(map->ci, "%s", fmt);
3343                         cf_log_err(map->ci, "%s^ %s", spaces, text);
3344
3345                         talloc_free(spaces);
3346                         talloc_free(text);
3347                         talloc_free(fmt);
3348
3349                         return false;
3350                 }
3351                 talloc_free(map->lhs);
3352                 map->lhs = vpt;
3353         }
3354
3355 #ifdef HAVE_REGEX
3356         if (map->rhs->type == TMPL_TYPE_REGEX) {
3357                 if (!pass2_regex_compile(map->ci, map->rhs)) {
3358                         return false;
3359                 }
3360         }
3361         rad_assert(map->lhs->type != TMPL_TYPE_REGEX);
3362 #endif
3363
3364         /*
3365          *      Only attributes can have a paircompare registered, and
3366          *      they can only be with the current REQUEST, and only
3367          *      with the request pairs.
3368          */
3369         if ((map->lhs->type != TMPL_TYPE_ATTR) ||
3370             (map->lhs->tmpl_request != REQUEST_CURRENT) ||
3371             (map->lhs->tmpl_list != PAIR_LIST_REQUEST)) {
3372                 return true;
3373         }
3374
3375         if (!radius_find_compare(map->lhs->tmpl_da)) return true;
3376
3377         if (map->rhs->type == TMPL_TYPE_ATTR) {
3378                 cf_log_err(map->ci, "Cannot compare virtual attribute %s to another attribute",
3379                            map->lhs->name);
3380                 return false;
3381         }
3382
3383         if (map->rhs->type == TMPL_TYPE_REGEX) {
3384                 cf_log_err(map->ci, "Cannot compare virtual attribute %s via a regex",
3385                            map->lhs->name);
3386                 return false;
3387         }
3388
3389         if (c->cast) {
3390                 cf_log_err(map->ci, "Cannot cast virtual attribute %s",
3391                            map->lhs->name);
3392                 return false;
3393         }
3394
3395         if (map->op != T_OP_CMP_EQ) {
3396                 cf_log_err(map->ci, "Must use '==' for comparisons with virtual attribute %s",
3397                            map->lhs->name);
3398                 return false;
3399         }
3400
3401         /*
3402          *      Mark it as requiring a paircompare() call, instead of
3403          *      paircmp().
3404          */
3405         c->pass2_fixup = PASS2_PAIRCOMPARE;
3406
3407         return true;
3408 }
3409
3410
3411 /*
3412  *      Compile the RHS of update sections to xlat_exp_t
3413  */
3414 static bool modcall_pass2_update(modgroup *g)
3415 {
3416         value_pair_map_t *map;
3417
3418         for (map = g->map; map != NULL; map = map->next) {
3419                 if (map->rhs->type == TMPL_TYPE_XLAT) {
3420                         rad_assert(map->rhs->tmpl_xlat == NULL);
3421
3422                         /*
3423                          *      FIXME: compile to attribute && handle
3424                          *      the conversion in map_to_vp().
3425                          */
3426                         if (!pass2_xlat_compile(map->ci, &map->rhs, false, NULL)) {
3427                                 return false;
3428                         }
3429                 }
3430
3431                 rad_assert(map->rhs->type != TMPL_TYPE_REGEX);
3432
3433                 /*
3434                  *      Deal with undefined attributes now.
3435                  */
3436                 if (map->lhs->type == TMPL_TYPE_ATTR_UNDEFINED) {
3437                         if (!pass2_fixup_undefined(map->ci, map->lhs)) return false;
3438                 }
3439
3440                 if (map->rhs->type == TMPL_TYPE_ATTR_UNDEFINED) {
3441                         if (!pass2_fixup_undefined(map->ci, map->rhs)) return false;
3442                 }
3443         }
3444
3445         return true;
3446 }
3447 #endif
3448
3449 /*
3450  *      Do a second-stage pass on compiling the modules.
3451  */
3452 bool modcall_pass2(modcallable *mc)
3453 {
3454         ssize_t slen;
3455         char const *name2;
3456         modcallable *c;
3457         modgroup *g;
3458
3459         for (c = mc; c != NULL; c = c->next) {
3460                 switch (c->type) {
3461                 default:
3462                         rad_assert(0 == 1);
3463                         break;
3464
3465 #ifdef WITH_UNLANG
3466                 case MOD_UPDATE:
3467                         g = mod_callabletogroup(c);
3468                         if (g->done_pass2) return true;
3469
3470                         name2 = cf_section_name2(g->cs);
3471                         if (!name2) {
3472                                 c->debug_name = unlang_keyword[c->type];
3473                         } else {
3474                                 c->debug_name = talloc_asprintf(c, "update %s", name2);
3475                         }
3476
3477                         if (!modcall_pass2_update(g)) {
3478                                 return false;
3479                         }
3480                         g->done_pass2 = true;
3481                         break;
3482
3483                 case MOD_XLAT:   /* @todo: pre-parse xlat's */
3484                 case MOD_REFERENCE:
3485                 case MOD_BREAK:
3486                 case MOD_RETURN:
3487 #endif
3488
3489                 case MOD_SINGLE:
3490                         c->debug_name = c->name;
3491                         break;  /* do nothing */
3492
3493 #ifdef WITH_UNLANG
3494                 case MOD_IF:
3495                 case MOD_ELSIF:
3496                         g = mod_callabletogroup(c);
3497                         if (g->done_pass2) return true;
3498
3499                         name2 = cf_section_name2(g->cs);
3500                         c->debug_name = talloc_asprintf(c, "%s %s", unlang_keyword[c->type], name2);
3501
3502                         /*
3503                          *      The compilation code takes care of
3504                          *      simplifying 'true' and 'false'
3505                          *      conditions.  For others, we have to do
3506                          *      a second pass to parse && compile
3507                          *      xlats.
3508                          */
3509                         if (!((g->cond->type == COND_TYPE_TRUE) ||
3510                               (g->cond->type == COND_TYPE_FALSE))) {
3511                                 if (!fr_condition_walk(g->cond, pass2_callback, NULL)) {
3512                                         return false;
3513                                 }
3514                         }
3515
3516                         if (!modcall_pass2(g->children)) return false;
3517                         g->done_pass2 = true;
3518                         break;
3519 #endif
3520
3521 #ifdef WITH_UNLANG
3522                 case MOD_SWITCH:
3523                         g = mod_callabletogroup(c);
3524                         if (g->done_pass2) return true;
3525
3526                         name2 = cf_section_name2(g->cs);
3527                         c->debug_name = talloc_asprintf(c, "%s %s", unlang_keyword[c->type], name2);
3528
3529                         /*
3530                          *      We had &Foo-Bar, where Foo-Bar is
3531                          *      defined by a module.
3532                          */
3533                         if (!g->vpt) {
3534                                 rad_assert(c->name != NULL);
3535                                 rad_assert(c->name[0] == '&');
3536                                 rad_assert(cf_section_name2_type(g->cs) == T_BARE_WORD);
3537
3538                                 slen = tmpl_afrom_str(g->cs, &g->vpt, c->name, strlen(c->name),
3539                                                       cf_section_name2_type(g->cs),
3540                                                       REQUEST_CURRENT, PAIR_LIST_REQUEST);
3541                                 if (slen < 0) {
3542                                         char *spaces, *text;
3543
3544                                 parse_error:
3545                                         fr_canonicalize_error(g->cs, &spaces, &text, slen, fr_strerror());
3546
3547                                         cf_log_err_cs(g->cs, "Syntax error");
3548                                         cf_log_err_cs(g->cs, "%s", c->name);
3549                                         cf_log_err_cs(g->cs, "%s^ %s", spaces, text);
3550
3551                                         talloc_free(spaces);
3552                                         talloc_free(text);
3553
3554                                         return false;
3555                                 }
3556
3557                                 goto do_children;
3558                         }
3559
3560                         /*
3561                          *      Statically compile xlats
3562                          */
3563                         if (g->vpt->type == TMPL_TYPE_XLAT) {
3564                                 if (!pass2_xlat_compile(cf_section_to_item(g->cs),
3565                                                         &g->vpt, true, NULL)) {
3566                                         return false;
3567                                 }
3568
3569                                 goto do_children;
3570                         }
3571
3572                         /*
3573                          *      We may have: switch Foo-Bar {
3574                          *
3575                          *      where Foo-Bar is an attribute defined
3576                          *      by a module.  Since there's no leading
3577                          *      &, it's parsed as a literal.  But if
3578                          *      we can parse it as an attribute,
3579                          *      switch to using that.
3580                          */
3581                         if (g->vpt->type == TMPL_TYPE_LITERAL) {
3582                                 value_pair_tmpl_t *vpt;
3583
3584                                 slen = tmpl_afrom_str(g->cs, &vpt, c->name, strlen(c->name), cf_section_name2_type(g->cs),
3585                                                       REQUEST_CURRENT, PAIR_LIST_REQUEST);
3586                                 if (slen < 0) goto parse_error;
3587                                 if (vpt->type == TMPL_TYPE_ATTR) {
3588                                         talloc_free(g->vpt);
3589                                         g->vpt = vpt;
3590                                 }
3591
3592                                 goto do_children;
3593                         }
3594
3595                         /*
3596                          *      Warn about old-style configuration.
3597                          *
3598                          *      DEPRECATED: switch User-Name { ...
3599                          *      ALLOWED   : switch &User-Name { ...
3600                          */
3601                         if ((g->vpt->type == TMPL_TYPE_ATTR) &&
3602                             (c->name[0] != '&')) {
3603                                 WARN("%s[%d]: Please change %s to &%s",
3604                                        cf_section_filename(g->cs),
3605                                        cf_section_lineno(g->cs),
3606                                        c->name, c->name);
3607                         }
3608
3609                 do_children:
3610                         if (!modcall_pass2(g->children)) return false;
3611                         g->done_pass2 = true;
3612                         break;
3613
3614                 case MOD_CASE:
3615                         g = mod_callabletogroup(c);
3616                         if (g->done_pass2) return true;
3617
3618                         name2 = cf_section_name2(g->cs);
3619                         if (!name2) {
3620                                 c->debug_name = unlang_keyword[c->type];
3621                         } else {
3622                                 c->debug_name = talloc_asprintf(c, "%s %s", unlang_keyword[c->type], name2);
3623                         }
3624
3625                         rad_assert(c->parent != NULL);
3626                         rad_assert(c->parent->type == MOD_SWITCH);
3627
3628                         /*
3629                          *      The statement may refer to an
3630                          *      attribute which doesn't exist until
3631                          *      all of the modules have been loaded.
3632                          *      Check for that now.
3633                          */
3634                         if (!g->vpt && c->name &&
3635                             (c->name[0] == '&') &&
3636                             (cf_section_name2_type(g->cs) == T_BARE_WORD)) {
3637                                 slen = tmpl_afrom_str(g->cs, &g->vpt, c->name, strlen(c->name),
3638                                                       cf_section_name2_type(g->cs),
3639                                                       REQUEST_CURRENT, PAIR_LIST_REQUEST);
3640                                 if (slen < 0) goto parse_error;
3641                         }
3642
3643                         /*
3644                          *      We have "case {...}".  There's no
3645                          *      argument, so we don't need to check
3646                          *      it.
3647                          */
3648                         if (!g->vpt) goto do_children;
3649
3650                         /*
3651                          *      Do type-specific checks on the case statement
3652                          */
3653                         if (g->vpt->type == TMPL_TYPE_LITERAL) {
3654                                 modgroup *f;
3655
3656                                 f = mod_callabletogroup(mc->parent);
3657                                 rad_assert(f->vpt != NULL);
3658
3659                                 /*
3660                                  *      We're switching over an
3661                                  *      attribute.  Check that the
3662                                  *      values match.
3663                                  */
3664                                 if (f->vpt->type == TMPL_TYPE_ATTR) {
3665                                         rad_assert(f->vpt->tmpl_da != NULL);
3666
3667                                         if (!tmpl_cast_in_place(g->vpt, f->vpt->tmpl_da->type, f->vpt->tmpl_da)) {
3668                                                 cf_log_err_cs(g->cs, "Invalid argument for case statement: %s",
3669                                                               fr_strerror());
3670                                                 return false;
3671                                         }
3672                                 }
3673
3674                                 goto do_children;
3675                         }
3676
3677                         /*
3678                          *      Compile and sanity check xlat
3679                          *      expansions.
3680                          */
3681                         if (g->vpt->type == TMPL_TYPE_XLAT) {
3682                                 modgroup *f;
3683
3684                                 f = mod_callabletogroup(mc->parent);
3685                                 rad_assert(f->vpt != NULL);
3686
3687                                 /*
3688                                  *      Don't expand xlat's into an
3689                                  *      attribute of a different type.
3690                                  */
3691                                 if (f->vpt->type == TMPL_TYPE_ATTR) {
3692                                         if (!pass2_xlat_compile(cf_section_to_item(g->cs),
3693                                                                 &g->vpt, true, f->vpt->tmpl_da)) {
3694                                                 return false;
3695                                         }
3696                                 } else {
3697                                         if (!pass2_xlat_compile(cf_section_to_item(g->cs),
3698                                                                 &g->vpt, true, NULL)) {
3699                                                 return false;
3700                                         }
3701                                 }
3702                         }
3703
3704                         if (!modcall_pass2(g->children)) return false;
3705                         g->done_pass2 = true;
3706                         break;
3707
3708                 case MOD_FOREACH:
3709                         g = mod_callabletogroup(c);
3710                         if (g->done_pass2) return true;
3711
3712                         name2 = cf_section_name2(g->cs);
3713                         c->debug_name = talloc_asprintf(c, "%s %s", unlang_keyword[c->type], name2);
3714
3715                         /*
3716                          *      Already parsed, handle the children.
3717                          */
3718                         if (g->vpt) goto check_children;
3719
3720                         /*
3721                          *      We had &Foo-Bar, where Foo-Bar is
3722                          *      defined by a module.
3723                          */
3724                         rad_assert(c->name != NULL);
3725                         rad_assert(c->name[0] == '&');
3726                         rad_assert(cf_section_name2_type(g->cs) == T_BARE_WORD);
3727
3728                         /*
3729                          *      The statement may refer to an
3730                          *      attribute which doesn't exist until
3731                          *      all of the modules have been loaded.
3732                          *      Check for that now.
3733                          */
3734                         slen = tmpl_afrom_str(g->cs, &g->vpt, c->name, strlen(c->name), cf_section_name2_type(g->cs),
3735                                               REQUEST_CURRENT, PAIR_LIST_REQUEST);
3736                         if (slen < 0) goto parse_error;
3737
3738                 check_children:
3739                         rad_assert((g->vpt->type == TMPL_TYPE_ATTR) || (g->vpt->type == TMPL_TYPE_LIST));
3740                         if (g->vpt->tmpl_num != NUM_ALL) {
3741                                 cf_log_err_cs(g->cs, "MUST NOT use instance selectors in 'foreach'");
3742                                 return false;
3743                         }
3744                         if (!modcall_pass2(g->children)) return false;
3745                         g->done_pass2 = true;
3746                         break;
3747
3748                 case MOD_ELSE:
3749                         c->debug_name = unlang_keyword[c->type];
3750                         goto do_recurse;
3751
3752                 case MOD_POLICY:
3753                         g = mod_callabletogroup(c);
3754                         c->debug_name = talloc_asprintf(c, "%s %s", unlang_keyword[c->type], cf_section_name1(g->cs));
3755                         goto do_recurse;
3756 #endif
3757
3758                 case MOD_GROUP:
3759                 case MOD_LOAD_BALANCE:
3760                 case MOD_REDUNDANT_LOAD_BALANCE:
3761                         c->debug_name = unlang_keyword[c->type];
3762
3763 #ifdef WITH_UNLANG
3764                 do_recurse:
3765 #endif
3766                         g = mod_callabletogroup(c);
3767                         if (!g->cs) {
3768                                 c->debug_name = mc->name; /* for authorize, etc. */
3769
3770                         } else if (c->type == MOD_GROUP) { /* for Auth-Type, etc. */
3771                                 char const *name1 = cf_section_name1(g->cs);
3772
3773                                 if (strcmp(name1, unlang_keyword[c->type]) != 0) {
3774                                         c->debug_name = talloc_asprintf(c, "%s %s", name1, cf_section_name2(g->cs));
3775                                 }
3776                         }
3777
3778                         if (g->done_pass2) return true;
3779                         if (!modcall_pass2(g->children)) return false;
3780                         g->done_pass2 = true;
3781                         break;
3782                 }
3783         }
3784
3785         return true;
3786 }
3787
3788 void modcall_debug(modcallable *mc, int depth)
3789 {
3790         modcallable *this;
3791         modgroup *g;
3792         value_pair_map_t *map;
3793         char buffer[1024];
3794
3795         for (this = mc; this != NULL; this = this->next) {
3796                 switch (this->type) {
3797                 default:
3798                         break;
3799
3800                 case MOD_SINGLE: {
3801                         modsingle *single = mod_callabletosingle(this);
3802
3803                         DEBUG("%.*s%s", depth, modcall_spaces,
3804                                 single->modinst->name);
3805                         }
3806                         break;
3807
3808 #ifdef WITH_UNLANG
3809                 case MOD_UPDATE:
3810                         g = mod_callabletogroup(this);
3811                         DEBUG("%.*s%s {", depth, modcall_spaces,
3812                                 unlang_keyword[this->type]);
3813
3814                         for (map = g->map; map != NULL; map = map->next) {
3815                                 map_prints(buffer, sizeof(buffer), map);
3816                                 DEBUG("%.*s%s", depth + 1, modcall_spaces, buffer);
3817                         }
3818
3819                         DEBUG("%.*s}", depth, modcall_spaces);
3820                         break;
3821
3822                 case MOD_ELSE:
3823                         g = mod_callabletogroup(this);
3824                         DEBUG("%.*s%s {", depth, modcall_spaces,
3825                                 unlang_keyword[this->type]);
3826                         modcall_debug(g->children, depth + 1);
3827                         DEBUG("%.*s}", depth, modcall_spaces);
3828                         break;
3829
3830                 case MOD_IF:
3831                 case MOD_ELSIF:
3832                         g = mod_callabletogroup(this);
3833                         fr_cond_sprint(buffer, sizeof(buffer), g->cond);
3834                         DEBUG("%.*s%s (%s) {", depth, modcall_spaces,
3835                                 unlang_keyword[this->type], buffer);
3836                         modcall_debug(g->children, depth + 1);
3837                         DEBUG("%.*s}", depth, modcall_spaces);
3838                         break;
3839
3840                 case MOD_SWITCH:
3841                 case MOD_CASE:
3842                         g = mod_callabletogroup(this);
3843                         tmpl_prints(buffer, sizeof(buffer), g->vpt, NULL);
3844                         DEBUG("%.*s%s %s {", depth, modcall_spaces,
3845                                 unlang_keyword[this->type], buffer);
3846                         modcall_debug(g->children, depth + 1);
3847                         DEBUG("%.*s}", depth, modcall_spaces);
3848                         break;
3849
3850                 case MOD_POLICY:
3851                 case MOD_FOREACH:
3852                         g = mod_callabletogroup(this);
3853                         DEBUG("%.*s%s %s {", depth, modcall_spaces,
3854                                 unlang_keyword[this->type], this->name);
3855                         modcall_debug(g->children, depth + 1);
3856                         DEBUG("%.*s}", depth, modcall_spaces);
3857                         break;
3858
3859                 case MOD_BREAK:
3860                         DEBUG("%.*sbreak", depth, modcall_spaces);
3861                         break;
3862
3863 #endif
3864                 case MOD_GROUP:
3865                         g = mod_callabletogroup(this);
3866                         DEBUG("%.*s%s {", depth, modcall_spaces,
3867                               unlang_keyword[this->type]);
3868                         modcall_debug(g->children, depth + 1);
3869                         DEBUG("%.*s}", depth, modcall_spaces);
3870                         break;
3871
3872
3873                 case MOD_LOAD_BALANCE:
3874                 case MOD_REDUNDANT_LOAD_BALANCE:
3875                         g = mod_callabletogroup(this);
3876                         DEBUG("%.*s%s {", depth, modcall_spaces,
3877                                 unlang_keyword[this->type]);
3878                         modcall_debug(g->children, depth + 1);
3879                         DEBUG("%.*s}", depth, modcall_spaces);
3880                         break;
3881                 }
3882         }
3883 }