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