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