simplify debug messages
[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)",
287                 comp2str[component], sp->modinst->name,
288                 sp->modinst->entry->name);
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", sp->modinst->entry->name);
313         }
314
315  fail:
316         request->log.indent = indent;
317         RDEBUG3("modsingle[%s]: returned from %s (%s)",
318                comp2str[component], sp->modinst->name,
319                sp->modinst->entry->name);
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         if (fr_debug_lvl >= 3) {
453                 VERIFY_REQUEST(request);
454         }
455
456         rad_assert(c->debug_name != NULL); /* if this happens, all bets are off. */
457
458         /*
459          *      We've been asked to stop.  Do so.
460          */
461         if ((request->master_state == REQUEST_STOP_PROCESSING) ||
462             (request->parent &&
463              (request->parent->master_state == REQUEST_STOP_PROCESSING))) {
464                 entry->result = RLM_MODULE_FAIL;
465                 entry->priority = 9999;
466                 goto finish;
467         }
468
469 #ifdef WITH_UNLANG
470         /*
471          *      Handle "if" conditions.
472          */
473         if (c->type == MOD_IF) {
474                 int condition;
475                 modgroup *g;
476
477         mod_if:
478                 g = mod_callabletogroup(c);
479                 rad_assert(g->cond != NULL);
480
481                 RDEBUG2("%s %s{", unlang_keyword[c->type], c->name);
482
483                 condition = radius_evaluate_cond(request, result, 0, g->cond);
484                 if (condition < 0) {
485                         condition = false;
486                         REDEBUG("Failed retrieving values required to evaluate condition");
487                 } else {
488                         RDEBUG2("%s %s -> %s",
489                                 unlang_keyword[c->type],
490                                 c->name, condition ? "TRUE" : "FALSE");
491                 }
492
493                 /*
494                  *      Didn't pass.  Remember that.
495                  */
496                 if (!condition) {
497                         was_if = true;
498                         if_taken = false;
499                         goto next_sibling;
500                 }
501
502                 /*
503                  *      We took the "if".  Go recurse into its' children.
504                  */
505                 was_if = true;
506                 if_taken = true;
507                 goto do_children;
508         } /* MOD_IF */
509
510         /*
511          *      "else" if the previous "if" was taken.
512          *      "if" if the previous if wasn't taken.
513          */
514         if (c->type == MOD_ELSIF) {
515                 if (!was_if) goto elsif_error;
516
517                 /*
518                  *      Like MOD_ELSE, but allow for a later "else"
519                  */
520                 if (if_taken) {
521                         RDEBUG2("... skipping %s: Preceding \"if\" was taken",
522                                 unlang_keyword[c->type]);
523                         was_if = true;
524                         if_taken = true;
525                         goto next_sibling;
526                 }
527
528                 /*
529                  *      Check the "if" condition.
530                  */
531                 goto mod_if;
532         } /* MOD_ELSIF */
533
534         /*
535          *      "else" for a preceding "if".
536          */
537         if (c->type == MOD_ELSE) {
538                 if (!was_if) { /* error */
539                 elsif_error:
540                         RDEBUG2("... skipping %s: No preceding \"if\"",
541                                 unlang_keyword[c->type]);
542                         goto next_sibling;
543                 }
544
545                 if (if_taken) {
546                         RDEBUG2("... skipping %s: Preceding \"if\" was taken",
547                                 unlang_keyword[c->type]);
548                         was_if = false;
549                         if_taken = false;
550                         goto next_sibling;
551                 }
552
553                 /*
554                  *      We need to process it.  Go do that.
555                  */
556                 was_if = false;
557                 if_taken = false;
558                 goto do_children;
559         } /* MOD_ELSE */
560
561         /*
562          *      We're no longer processing if/else/elsif.  Reset the
563          *      trackers for those conditions.
564          */
565         was_if = false;
566         if_taken = false;
567 #endif  /* WITH_UNLANG */
568
569         if (c->type == MOD_SINGLE) {
570                 modsingle *sp;
571
572                 /*
573                  *      Process a stand-alone child, and fall through
574                  *      to dealing with it's parent.
575                  */
576                 sp = mod_callabletosingle(c);
577
578                 result = call_modsingle(c->method, sp, request);
579                 RDEBUG2("[%s] = %s", c->name ? c->name : "",
580                         fr_int2str(mod_rcode_table, result, "<invalid>"));
581                 goto calculate_result;
582         } /* MOD_SINGLE */
583
584 #ifdef WITH_UNLANG
585         /*
586          *      Update attribute(s)
587          */
588         if (c->type == MOD_UPDATE) {
589                 int rcode;
590                 modgroup *g = mod_callabletogroup(c);
591                 vp_map_t *map;
592
593                 MOD_LOG_OPEN_BRACE;
594                 RINDENT();
595                 for (map = g->map; map != NULL; map = map->next) {
596                         rcode = map_to_request(request, map, map_to_vp, NULL);
597                         if (rcode < 0) {
598                                 result = (rcode == -2) ? RLM_MODULE_INVALID : RLM_MODULE_FAIL;
599                                 REXDENT();
600                                 MOD_LOG_CLOSE_BRACE;
601                                 goto calculate_result;
602                         }
603                 }
604                 REXDENT();
605                 result = RLM_MODULE_NOOP;
606                 MOD_LOG_CLOSE_BRACE;
607                 goto calculate_result;
608         } /* MOD_IF */
609
610         /*
611          *      Loop over a set of attributes.
612          */
613         if (c->type == MOD_FOREACH) {
614                 int i, foreach_depth = -1;
615                 VALUE_PAIR *vps, *vp;
616                 modcall_stack_entry_t *next = NULL;
617                 vp_cursor_t copy;
618                 modgroup *g = mod_callabletogroup(c);
619
620                 if (depth >= MODCALL_STACK_MAX) {
621                         ERROR("Internal sanity check failed: module stack is too deep");
622                         fr_exit(1);
623                 }
624
625                 /*
626                  *      Figure out how deep we are in nesting by looking at request_data
627                  *      stored previously.
628                  */
629                 for (i = 0; i < 8; i++) {
630                         if (!request_data_reference(request, (void *)radius_get_vp, i)) {
631                                 foreach_depth = i;
632                                 break;
633                         }
634                 }
635
636                 if (foreach_depth < 0) {
637                         REDEBUG("foreach Nesting too deep!");
638                         result = RLM_MODULE_FAIL;
639                         goto calculate_result;
640                 }
641
642                 /*
643                  *      Copy the VPs from the original request, this ensures deterministic
644                  *      behaviour if someone decides to add or remove VPs in the set were
645                  *      iterating over.
646                  */
647                 if (tmpl_copy_vps(request, &vps, request, g->vpt) < 0) {        /* nothing to loop over */
648                         MOD_LOG_OPEN_BRACE;
649                         result = RLM_MODULE_NOOP;
650                         MOD_LOG_CLOSE_BRACE;
651                         goto calculate_result;
652                 }
653
654                 rad_assert(vps != NULL);
655                 fr_cursor_init(&copy, &vps);
656
657                 RDEBUG2("foreach %s ", c->name);
658
659                 /*
660                  *      This is the actual body of the foreach loop
661                  */
662                 for (vp = fr_cursor_first(&copy);
663                      vp != NULL;
664                      vp = fr_cursor_next(&copy)) {
665 #ifndef NDEBUG
666                         if (fr_debug_lvl >= 2) {
667                                 char buffer[1024];
668
669                                 vp_prints_value(buffer, sizeof(buffer), vp, '"');
670                                 RDEBUG2("# Foreach-Variable-%d = %s", foreach_depth, buffer);
671                         }
672 #endif
673
674                         /*
675                          *      Add the vp to the request, so that
676                          *      xlat.c, xlat_foreach() can find it.
677                          */
678                         request_data_add(request, (void *)radius_get_vp, foreach_depth, &vp, false);
679
680                         /*
681                          *      Initialize the childs stack frame.
682                          */
683                         next = entry + 1;
684                         next->c = g->children;
685                         next->result = entry->result;
686                         next->priority = 0;
687                         next->unwind = 0;
688
689                         if (!modcall_recurse(request, component, depth + 1, next, true)) {
690                                 break;
691                         }
692
693                         /*
694                          *      We've been asked to unwind to the
695                          *      enclosing "foreach".  We're here, so
696                          *      we can stop unwinding.
697                          */
698                         if (next->unwind == MOD_BREAK) {
699                                 entry->unwind = 0;
700                                 break;
701                         }
702
703                         /*
704                          *      Unwind all the way.
705                          */
706                         if (next->unwind == MOD_RETURN) {
707                                 entry->unwind = MOD_RETURN;
708                                 break;
709                         }
710                 } /* loop over VPs */
711
712                 /*
713                  *      Free the copied vps and the request data
714                  *      If we don't remove the request data, something could call
715                  *      the xlat outside of a foreach loop and trigger a segv.
716                  */
717                 fr_pair_list_free(&vps);
718                 request_data_get(request, (void *)radius_get_vp, foreach_depth);
719
720                 rad_assert(next != NULL);
721                 result = next->result;
722                 priority = next->priority;
723                 MOD_LOG_CLOSE_BRACE;
724                 goto calculate_result;
725         } /* MOD_FOREACH */
726
727         /*
728          *      Break out of a "foreach" loop, or return from a nested
729          *      group.
730          */
731         if ((c->type == MOD_BREAK) || (c->type == MOD_RETURN)) {
732                 int i;
733                 VALUE_PAIR **copy_p;
734
735                 RDEBUG2("%s", unlang_keyword[c->type]);
736
737                 for (i = 8; i >= 0; i--) {
738                         copy_p = request_data_get(request, (void *)radius_get_vp, i);
739                         if (copy_p) {
740                                 if (c->type == MOD_BREAK) {
741                                         RDEBUG2("# break Foreach-Variable-%d", i);
742                                         break;
743                                 }
744                         }
745                 }
746
747                 /*
748                  *      Leave result / priority on the stack, and stop processing the section.
749                  */
750                 entry->unwind = c->type;
751                 goto finish;
752         } /* MOD_BREAK */
753
754 #endif    /* WITH_UNLANG */
755
756         /*
757          *      Child is a group that has children of it's own.
758          */
759         if ((c->type == MOD_GROUP) || (c->type == MOD_POLICY)
760 #ifdef WITH_UNLANG
761             || (c->type == MOD_CASE)
762 #endif
763                 ) {
764                 modgroup *g;
765
766 #ifdef WITH_UNLANG
767         do_children:
768 #endif
769                 g = mod_callabletogroup(c);
770
771                 /*
772                  *      This should really have been caught in the
773                  *      compiler, and the node never generated.  But
774                  *      doing that requires changing it's API so that
775                  *      it returns a flag instead of the compiled
776                  *      MOD_GROUP.
777                  */
778                 if (!g->children) {
779                         if (c->type == MOD_CASE) {
780                                 result = RLM_MODULE_NOOP;
781                                 goto calculate_result;
782                         }
783
784                         RDEBUG2("%s { ... } # empty sub-section is ignored", c->name);
785                         goto next_sibling;
786                 }
787
788                 MOD_LOG_OPEN_BRACE;
789                 modcall_child(request, component,
790                               depth + 1, entry, g->children,
791                               &result, true);
792                 MOD_LOG_CLOSE_BRACE;
793                 goto calculate_result;
794         } /* MOD_GROUP */
795
796 #ifdef WITH_UNLANG
797         if (c->type == MOD_SWITCH) {
798                 modcallable *this, *found, *null_case;
799                 modgroup *g, *h;
800                 fr_cond_t cond;
801                 value_data_t data;
802                 vp_map_t map;
803                 vp_tmpl_t vpt;
804
805                 MOD_LOG_OPEN_BRACE;
806
807                 g = mod_callabletogroup(c);
808
809                 memset(&cond, 0, sizeof(cond));
810                 memset(&map, 0, sizeof(map));
811
812                 cond.type = COND_TYPE_MAP;
813                 cond.data.map = &map;
814
815                 map.op = T_OP_CMP_EQ;
816                 map.ci = cf_section_to_item(g->cs);
817
818                 rad_assert(g->vpt != NULL);
819
820                 null_case = found = NULL;
821                 data.ptr = NULL;
822
823                 /*
824                  *      The attribute doesn't exist.  We can skip
825                  *      directly to the default 'case' statement.
826                  */
827                 if ((g->vpt->type == TMPL_TYPE_ATTR) && (tmpl_find_vp(NULL, request, g->vpt) < 0)) {
828                 find_null_case:
829                         for (this = g->children; this; this = this->next) {
830                                 rad_assert(this->type == MOD_CASE);
831
832                                 h = mod_callabletogroup(this);
833                                 if (h->vpt) continue;
834
835                                 found = this;
836                                 break;
837                         }
838
839                         goto do_null_case;
840                 }
841
842                 /*
843                  *      Expand the template if necessary, so that it
844                  *      is evaluated once instead of for each 'case'
845                  *      statement.
846                  */
847                 if ((g->vpt->type == TMPL_TYPE_XLAT_STRUCT) ||
848                     (g->vpt->type == TMPL_TYPE_XLAT) ||
849                     (g->vpt->type == TMPL_TYPE_EXEC)) {
850                         char *p;
851                         ssize_t len;
852
853                         len = tmpl_aexpand(request, &p, request, g->vpt, NULL, NULL);
854                         if (len < 0) goto find_null_case;
855                         data.strvalue = p;
856                         tmpl_init(&vpt, TMPL_TYPE_LITERAL, data.strvalue, len);
857                 }
858
859                 /*
860                  *      Find either the exact matching name, or the
861                  *      "case {...}" statement.
862                  */
863                 for (this = g->children; this; this = this->next) {
864                         rad_assert(this->type == MOD_CASE);
865
866                         h = mod_callabletogroup(this);
867
868                         /*
869                          *      Remember the default case
870                          */
871                         if (!h->vpt) {
872                                 if (!null_case) null_case = this;
873                                 continue;
874                         }
875
876                         /*
877                          *      If we're switching over an attribute
878                          *      AND we haven't pre-parsed the data for
879                          *      the case statement, then cast the data
880                          *      to the type of the attribute.
881                          */
882                         if ((g->vpt->type == TMPL_TYPE_ATTR) &&
883                             (h->vpt->type != TMPL_TYPE_DATA)) {
884                                 map.rhs = g->vpt;
885                                 map.lhs = h->vpt;
886                                 cond.cast = g->vpt->tmpl_da;
887
888                                 /*
889                                  *      Remove unnecessary casting.
890                                  */
891                                 if ((h->vpt->type == TMPL_TYPE_ATTR) &&
892                                     (g->vpt->tmpl_da->type == h->vpt->tmpl_da->type)) {
893                                         cond.cast = NULL;
894                                 }
895
896                                 /*
897                                  *      Use the pre-expanded string.
898                                  */
899                         } else if ((g->vpt->type == TMPL_TYPE_XLAT_STRUCT) ||
900                                    (g->vpt->type == TMPL_TYPE_XLAT) ||
901                                    (g->vpt->type == TMPL_TYPE_EXEC)) {
902                                 map.rhs = h->vpt;
903                                 map.lhs = &vpt;
904                                 cond.cast = NULL;
905
906                                 /*
907                                  *      Else evaluate the 'switch' statement.
908                                  */
909                         } else {
910                                 map.rhs = h->vpt;
911                                 map.lhs = g->vpt;
912                                 cond.cast = NULL;
913                         }
914
915                         if (radius_evaluate_map(request, RLM_MODULE_UNKNOWN, 0,
916                                                 &cond) == 1) {
917                                 found = this;
918                                 break;
919                         }
920                 }
921
922                 if (!found) found = null_case;
923
924         do_null_case:
925                 talloc_free(data.ptr);
926                 modcall_child(request, component, depth + 1, entry, found, &result, true);
927                 MOD_LOG_CLOSE_BRACE;
928                 goto calculate_result;
929         } /* MOD_SWITCH */
930 #endif
931
932         if ((c->type == MOD_LOAD_BALANCE) ||
933             (c->type == MOD_REDUNDANT_LOAD_BALANCE)) {
934                 uint32_t count = 0;
935                 modcallable *this, *found;
936                 modgroup *g;
937
938                 MOD_LOG_OPEN_BRACE;
939
940                 g = mod_callabletogroup(c);
941                 found = g->children;
942                 rad_assert(g->children != NULL);
943
944                 /*
945                  *      Choose a child at random.
946                  */
947                 for (this = g->children; this; this = this->next) {
948                         count++;
949
950                         if ((count * (fr_rand() & 0xffff)) < (uint32_t) 0x10000) {
951                                 found = this;
952                         }
953                 }
954
955                 if (c->type == MOD_LOAD_BALANCE) {
956                         modcall_child(request, component,
957                                       depth + 1, entry, found,
958                                       &result, false);
959
960                 } else {
961                         this = found;
962
963                         do {
964                                 modcall_child(request, component,
965                                               depth + 1, entry, this,
966                                               &result, false);
967                                 if (this->actions[result] == MOD_ACTION_RETURN) {
968                                         priority = -1;
969                                         break;
970                                 }
971
972                                 this = this->next;
973                                 if (!this) this = g->children;
974                         } while (this != found);
975                 }
976                 MOD_LOG_CLOSE_BRACE;
977                 goto calculate_result;
978         } /* MOD_LOAD_BALANCE */
979
980         /*
981          *      Reference another virtual server.
982          *
983          *      This should really be deleted, and replaced with a
984          *      more abstracted / functional version.
985          */
986         if (c->type == MOD_REFERENCE) {
987                 modref *mr = mod_callabletoref(c);
988                 char const *server = request->server;
989
990                 if (server == mr->ref_name) {
991                         RWDEBUG("Suppressing recursive call to server %s", server);
992                         goto next_sibling;
993                 }
994
995                 request->server = mr->ref_name;
996                 RDEBUG("server %s { # nested call", mr->ref_name);
997                 result = indexed_modcall(component, 0, request);
998                 RDEBUG("} # server %s with nested call", mr->ref_name);
999                 request->server = server;
1000                 goto calculate_result;
1001         } /* MOD_REFERENCE */
1002
1003         /*
1004          *      xlat a string without doing anything else
1005          *
1006          *      This should really be deleted, and replaced with a
1007          *      more abstracted / functional version.
1008          */
1009         if (c->type == MOD_XLAT) {
1010                 modxlat *mx = mod_callabletoxlat(c);
1011                 char buffer[128];
1012
1013                 if (!mx->exec) {
1014                         radius_xlat(buffer, sizeof(buffer), request, mx->xlat_name, NULL, NULL);
1015                 } else {
1016                         RDEBUG("`%s`", mx->xlat_name);
1017                         radius_exec_program(request, NULL, 0, NULL, request, mx->xlat_name, request->packet->vps,
1018                                             false, true, EXEC_TIMEOUT);
1019                 }
1020
1021                 goto next_sibling;
1022         } /* MOD_XLAT */
1023
1024         /*
1025          *      Add new module types here.
1026          */
1027
1028 calculate_result:
1029 #if 0
1030         RDEBUG("(%s, %d) ? (%s, %d)",
1031                fr_int2str(mod_rcode_table, result, "<invalid>"),
1032                priority,
1033                fr_int2str(mod_rcode_table, entry->result, "<invalid>"),
1034                entry->priority);
1035 #endif
1036
1037
1038         rad_assert(result != RLM_MODULE_UNKNOWN);
1039
1040         /*
1041          *      The child's action says return.  Do so.
1042          */
1043         if ((c->actions[result] == MOD_ACTION_RETURN) &&
1044             (priority <= 0)) {
1045                 entry->result = result;
1046                 goto finish;
1047         }
1048
1049         /*
1050          *      If "reject", break out of the loop and return
1051          *      reject.
1052          */
1053         if (c->actions[result] == MOD_ACTION_REJECT) {
1054                 entry->result = RLM_MODULE_REJECT;
1055                 goto finish;
1056         }
1057
1058         /*
1059          *      The array holds a default priority for this return
1060          *      code.  Grab it in preference to any unset priority.
1061          */
1062         if (priority < 0) {
1063                 priority = c->actions[result];
1064         }
1065
1066         /*
1067          *      We're higher than any previous priority, remember this
1068          *      return code and priority.
1069          */
1070         if (priority > entry->priority) {
1071                 entry->result = result;
1072                 entry->priority = priority;
1073         }
1074
1075 #ifdef WITH_UNLANG
1076         /*
1077          *      If we're processing a "case" statement, we return once
1078          *      it's done, rather than going to the next "case" statement.
1079          */
1080         if (c->type == MOD_CASE) goto finish;
1081 #endif
1082
1083         /*
1084          *      If we've been told to stop processing
1085          *      it, do so.
1086          */
1087         if (entry->unwind == MOD_BREAK) {
1088                 RDEBUG2("# unwind to enclosing foreach");
1089                 goto finish;
1090         }
1091
1092         if (entry->unwind == MOD_RETURN) {
1093                 goto finish;
1094         }
1095
1096 next_sibling:
1097         if (do_next_sibling) {
1098                 entry->c = entry->c->next;
1099
1100                 if (entry->c) goto redo;
1101         }
1102
1103 finish:
1104         /*
1105          *      And we're done!
1106          */
1107         REXDENT();
1108         return true;
1109 }
1110
1111
1112 /** Call a module, iteratively, with a local stack, rather than recursively
1113  *
1114  * What did Paul Graham say about Lisp...?
1115  */
1116 int modcall(rlm_components_t component, modcallable *c, REQUEST *request)
1117 {
1118         modcall_stack_entry_t stack[MODCALL_STACK_MAX];
1119
1120 #ifndef NDEBUG
1121         memset(stack, 0, sizeof(stack));
1122 #endif
1123         /*
1124          *      Set up the initial stack frame.
1125          */
1126         stack[0].c = c;
1127         stack[0].result = default_component_results[component];
1128         stack[0].priority = 0;
1129         stack[0].unwind = 0;
1130
1131         /*
1132          *      Call the main handler.
1133          */
1134         if (!modcall_recurse(request, component, 0, &stack[0], true)) {
1135                 return RLM_MODULE_FAIL;
1136         }
1137
1138         /*
1139          *      Return the result.
1140          */
1141         return stack[0].result;
1142 }
1143
1144
1145 #if 0
1146 static char const *action2str(int action)
1147 {
1148         static char buf[32];
1149         if(action==MOD_ACTION_RETURN)
1150                 return "return";
1151         if(action==MOD_ACTION_REJECT)
1152                 return "reject";
1153         snprintf(buf, sizeof buf, "%d", action);
1154         return buf;
1155 }
1156
1157 /* If you suspect a bug in the parser, you'll want to use these dump
1158  * functions. dump_tree should reproduce a whole tree exactly as it was found
1159  * in radiusd.conf, but in long form (all actions explicitly defined) */
1160 static void dump_mc(modcallable *c, int indent)
1161 {
1162         int i;
1163
1164         if(c->type==MOD_SINGLE) {
1165                 modsingle *single = mod_callabletosingle(c);
1166                 DEBUG("%.*s%s {", indent, "\t\t\t\t\t\t\t\t\t\t\t",
1167                         single->modinst->name);
1168         } else if ((c->type > MOD_SINGLE) && (c->type <= MOD_POLICY)) {
1169                 modgroup *g = mod_callabletogroup(c);
1170                 modcallable *p;
1171                 DEBUG("%.*s%s {", indent, "\t\t\t\t\t\t\t\t\t\t\t",
1172                       unlang_keyword[c->type]);
1173                 for(p = g->children;p;p = p->next)
1174                         dump_mc(p, indent+1);
1175         } /* else ignore it for now */
1176
1177         for(i = 0; i<RLM_MODULE_NUMCODES; ++i) {
1178                 DEBUG("%.*s%s = %s", indent+1, "\t\t\t\t\t\t\t\t\t\t\t",
1179                       fr_int2str(mod_rcode_table, i, "<invalid>"),
1180                       action2str(c->actions[i]));
1181         }
1182
1183         DEBUG("%.*s}", indent, "\t\t\t\t\t\t\t\t\t\t\t");
1184 }
1185
1186 static void dump_tree(rlm_components_t comp, modcallable *c)
1187 {
1188         DEBUG("[%s]", comp2str[comp]);
1189         dump_mc(c, 0);
1190 }
1191 #else
1192 #define dump_tree(a, b)
1193 #endif
1194
1195 /* These are the default actions. For each component, the group{} block
1196  * behaves like the code from the old module_*() function. redundant{}
1197  * are based on my guesses of what they will be used for. --Pac. */
1198 static const int
1199 defaultactions[MOD_COUNT][GROUPTYPE_COUNT][RLM_MODULE_NUMCODES] =
1200 {
1201         /* authenticate */
1202         {
1203                 /* group */
1204                 {
1205                         MOD_ACTION_RETURN,      /* reject   */
1206                         1,                      /* fail     */
1207                         MOD_ACTION_RETURN,      /* ok       */
1208                         MOD_ACTION_RETURN,      /* handled  */
1209                         1,                      /* invalid  */
1210                         MOD_ACTION_RETURN,      /* userlock */
1211                         MOD_ACTION_RETURN,      /* notfound */
1212                         1,                      /* noop     */
1213                         1                       /* updated  */
1214                 },
1215                 /* redundant */
1216                 {
1217                         MOD_ACTION_RETURN,      /* reject   */
1218                         1,                      /* fail     */
1219                         MOD_ACTION_RETURN,      /* ok       */
1220                         MOD_ACTION_RETURN,      /* handled  */
1221                         MOD_ACTION_RETURN,      /* invalid  */
1222                         MOD_ACTION_RETURN,      /* userlock */
1223                         MOD_ACTION_RETURN,      /* notfound */
1224                         MOD_ACTION_RETURN,      /* noop     */
1225                         MOD_ACTION_RETURN       /* updated  */
1226                 }
1227         },
1228         /* authorize */
1229         {
1230                 /* group */
1231                 {
1232                         MOD_ACTION_RETURN,      /* reject   */
1233                         MOD_ACTION_RETURN,      /* fail     */
1234                         3,                      /* ok       */
1235                         MOD_ACTION_RETURN,      /* handled  */
1236                         MOD_ACTION_RETURN,      /* invalid  */
1237                         MOD_ACTION_RETURN,      /* userlock */
1238                         1,                      /* notfound */
1239                         2,                      /* noop     */
1240                         4                       /* updated  */
1241                 },
1242                 /* redundant */
1243                 {
1244                         MOD_ACTION_RETURN,      /* reject   */
1245                         1,                      /* fail     */
1246                         MOD_ACTION_RETURN,      /* ok       */
1247                         MOD_ACTION_RETURN,      /* handled  */
1248                         MOD_ACTION_RETURN,      /* invalid  */
1249                         MOD_ACTION_RETURN,      /* userlock */
1250                         MOD_ACTION_RETURN,      /* notfound */
1251                         MOD_ACTION_RETURN,      /* noop     */
1252                         MOD_ACTION_RETURN       /* updated  */
1253                 }
1254         },
1255         /* preacct */
1256         {
1257                 /* group */
1258                 {
1259                         MOD_ACTION_RETURN,      /* reject   */
1260                         MOD_ACTION_RETURN,      /* fail     */
1261                         2,                      /* ok       */
1262                         MOD_ACTION_RETURN,      /* handled  */
1263                         MOD_ACTION_RETURN,      /* invalid  */
1264                         MOD_ACTION_RETURN,      /* userlock */
1265                         MOD_ACTION_RETURN,      /* notfound */
1266                         1,                      /* noop     */
1267                         3                       /* updated  */
1268                 },
1269                 /* redundant */
1270                 {
1271                         MOD_ACTION_RETURN,      /* reject   */
1272                         1,                      /* fail     */
1273                         MOD_ACTION_RETURN,      /* ok       */
1274                         MOD_ACTION_RETURN,      /* handled  */
1275                         MOD_ACTION_RETURN,      /* invalid  */
1276                         MOD_ACTION_RETURN,      /* userlock */
1277                         MOD_ACTION_RETURN,      /* notfound */
1278                         MOD_ACTION_RETURN,      /* noop     */
1279                         MOD_ACTION_RETURN       /* updated  */
1280                 }
1281         },
1282         /* accounting */
1283         {
1284                 /* group */
1285                 {
1286                         MOD_ACTION_RETURN,      /* reject   */
1287                         MOD_ACTION_RETURN,      /* fail     */
1288                         2,                      /* ok       */
1289                         MOD_ACTION_RETURN,      /* handled  */
1290                         MOD_ACTION_RETURN,      /* invalid  */
1291                         MOD_ACTION_RETURN,      /* userlock */
1292                         MOD_ACTION_RETURN,      /* notfound */
1293                         1,                      /* noop     */
1294                         3                       /* updated  */
1295                 },
1296                 /* redundant */
1297                 {
1298                         1,                      /* reject   */
1299                         1,                      /* fail     */
1300                         MOD_ACTION_RETURN,      /* ok       */
1301                         MOD_ACTION_RETURN,      /* handled  */
1302                         1,                      /* invalid  */
1303                         1,                      /* userlock */
1304                         1,                      /* notfound */
1305                         2,                      /* noop     */
1306                         4                       /* updated  */
1307                 }
1308         },
1309         /* checksimul */
1310         {
1311                 /* group */
1312                 {
1313                         MOD_ACTION_RETURN,      /* reject   */
1314                         1,                      /* fail     */
1315                         MOD_ACTION_RETURN,      /* ok       */
1316                         MOD_ACTION_RETURN,      /* handled  */
1317                         MOD_ACTION_RETURN,      /* invalid  */
1318                         MOD_ACTION_RETURN,      /* userlock */
1319                         MOD_ACTION_RETURN,      /* notfound */
1320                         MOD_ACTION_RETURN,      /* noop     */
1321                         MOD_ACTION_RETURN       /* updated  */
1322                 },
1323                 /* redundant */
1324                 {
1325                         MOD_ACTION_RETURN,      /* reject   */
1326                         1,                      /* fail     */
1327                         MOD_ACTION_RETURN,      /* ok       */
1328                         MOD_ACTION_RETURN,      /* handled  */
1329                         MOD_ACTION_RETURN,      /* invalid  */
1330                         MOD_ACTION_RETURN,      /* userlock */
1331                         MOD_ACTION_RETURN,      /* notfound */
1332                         MOD_ACTION_RETURN,      /* noop     */
1333                         MOD_ACTION_RETURN       /* updated  */
1334                 }
1335         },
1336         /* pre-proxy */
1337         {
1338                 /* group */
1339                 {
1340                         MOD_ACTION_RETURN,      /* reject   */
1341                         MOD_ACTION_RETURN,      /* fail     */
1342                         3,                      /* ok       */
1343                         MOD_ACTION_RETURN,      /* handled  */
1344                         MOD_ACTION_RETURN,      /* invalid  */
1345                         MOD_ACTION_RETURN,      /* userlock */
1346                         1,                      /* notfound */
1347                         2,                      /* noop     */
1348                         4                       /* updated  */
1349                 },
1350                 /* redundant */
1351                 {
1352                         MOD_ACTION_RETURN,      /* reject   */
1353                         1,                      /* fail     */
1354                         MOD_ACTION_RETURN,      /* ok       */
1355                         MOD_ACTION_RETURN,      /* handled  */
1356                         MOD_ACTION_RETURN,      /* invalid  */
1357                         MOD_ACTION_RETURN,      /* userlock */
1358                         MOD_ACTION_RETURN,      /* notfound */
1359                         MOD_ACTION_RETURN,      /* noop     */
1360                         MOD_ACTION_RETURN       /* updated  */
1361                 }
1362         },
1363         /* post-proxy */
1364         {
1365                 /* group */
1366                 {
1367                         MOD_ACTION_RETURN,      /* reject   */
1368                         MOD_ACTION_RETURN,      /* fail     */
1369                         3,                      /* ok       */
1370                         MOD_ACTION_RETURN,      /* handled  */
1371                         MOD_ACTION_RETURN,      /* invalid  */
1372                         MOD_ACTION_RETURN,      /* userlock */
1373                         1,                      /* notfound */
1374                         2,                      /* noop     */
1375                         4                       /* updated  */
1376                 },
1377                 /* redundant */
1378                 {
1379                         MOD_ACTION_RETURN,      /* reject   */
1380                         1,                      /* fail     */
1381                         MOD_ACTION_RETURN,      /* ok       */
1382                         MOD_ACTION_RETURN,      /* handled  */
1383                         MOD_ACTION_RETURN,      /* invalid  */
1384                         MOD_ACTION_RETURN,      /* userlock */
1385                         MOD_ACTION_RETURN,      /* notfound */
1386                         MOD_ACTION_RETURN,      /* noop     */
1387                         MOD_ACTION_RETURN       /* updated  */
1388                 }
1389         },
1390         /* post-auth */
1391         {
1392                 /* group */
1393                 {
1394                         MOD_ACTION_RETURN,      /* reject   */
1395                         MOD_ACTION_RETURN,      /* fail     */
1396                         3,                      /* ok       */
1397                         MOD_ACTION_RETURN,      /* handled  */
1398                         MOD_ACTION_RETURN,      /* invalid  */
1399                         MOD_ACTION_RETURN,      /* userlock */
1400                         1,                      /* notfound */
1401                         2,                      /* noop     */
1402                         4                       /* updated  */
1403                 },
1404                 /* redundant */
1405                 {
1406                         MOD_ACTION_RETURN,      /* reject   */
1407                         1,                      /* fail     */
1408                         MOD_ACTION_RETURN,      /* ok       */
1409                         MOD_ACTION_RETURN,      /* handled  */
1410                         MOD_ACTION_RETURN,      /* invalid  */
1411                         MOD_ACTION_RETURN,      /* userlock */
1412                         MOD_ACTION_RETURN,      /* notfound */
1413                         MOD_ACTION_RETURN,      /* noop     */
1414                         MOD_ACTION_RETURN       /* updated  */
1415                 }
1416         }
1417 #ifdef WITH_COA
1418         ,
1419         /* recv-coa */
1420         {
1421                 /* group */
1422                 {
1423                         MOD_ACTION_RETURN,      /* reject   */
1424                         MOD_ACTION_RETURN,      /* fail     */
1425                         3,                      /* ok       */
1426                         MOD_ACTION_RETURN,      /* handled  */
1427                         MOD_ACTION_RETURN,      /* invalid  */
1428                         MOD_ACTION_RETURN,      /* userlock */
1429                         1,                      /* notfound */
1430                         2,                      /* noop     */
1431                         4                       /* updated  */
1432                 },
1433                 /* redundant */
1434                 {
1435                         MOD_ACTION_RETURN,      /* reject   */
1436                         1,                      /* fail     */
1437                         MOD_ACTION_RETURN,      /* ok       */
1438                         MOD_ACTION_RETURN,      /* handled  */
1439                         MOD_ACTION_RETURN,      /* invalid  */
1440                         MOD_ACTION_RETURN,      /* userlock */
1441                         MOD_ACTION_RETURN,      /* notfound */
1442                         MOD_ACTION_RETURN,      /* noop     */
1443                         MOD_ACTION_RETURN       /* updated  */
1444                 }
1445         },
1446         /* send-coa */
1447         {
1448                 /* group */
1449                 {
1450                         MOD_ACTION_RETURN,      /* reject   */
1451                         MOD_ACTION_RETURN,      /* fail     */
1452                         3,                      /* ok       */
1453                         MOD_ACTION_RETURN,      /* handled  */
1454                         MOD_ACTION_RETURN,      /* invalid  */
1455                         MOD_ACTION_RETURN,      /* userlock */
1456                         1,                      /* notfound */
1457                         2,                      /* noop     */
1458                         4                       /* updated  */
1459                 },
1460                 /* redundant */
1461                 {
1462                         MOD_ACTION_RETURN,      /* reject   */
1463                         1,                      /* fail     */
1464                         MOD_ACTION_RETURN,      /* ok       */
1465                         MOD_ACTION_RETURN,      /* handled  */
1466                         MOD_ACTION_RETURN,      /* invalid  */
1467                         MOD_ACTION_RETURN,      /* userlock */
1468                         MOD_ACTION_RETURN,      /* notfound */
1469                         MOD_ACTION_RETURN,      /* noop     */
1470                         MOD_ACTION_RETURN       /* updated  */
1471                 }
1472         }
1473 #endif
1474 };
1475
1476 static const int authtype_actions[GROUPTYPE_COUNT][RLM_MODULE_NUMCODES] =
1477 {
1478         /* group */
1479         {
1480                 MOD_ACTION_RETURN,      /* reject   */
1481                 MOD_ACTION_RETURN,      /* fail     */
1482                 4,                      /* ok       */
1483                 MOD_ACTION_RETURN,      /* handled  */
1484                 MOD_ACTION_RETURN,      /* invalid  */
1485                 MOD_ACTION_RETURN,      /* userlock */
1486                 1,                      /* notfound */
1487                 2,                      /* noop     */
1488                 3                       /* updated  */
1489         },
1490         /* redundant */
1491         {
1492                 MOD_ACTION_RETURN,      /* reject   */
1493                 1,                      /* fail     */
1494                 MOD_ACTION_RETURN,      /* ok       */
1495                 MOD_ACTION_RETURN,      /* handled  */
1496                 MOD_ACTION_RETURN,      /* invalid  */
1497                 MOD_ACTION_RETURN,      /* userlock */
1498                 MOD_ACTION_RETURN,      /* notfound */
1499                 MOD_ACTION_RETURN,      /* noop     */
1500                 MOD_ACTION_RETURN       /* updated  */
1501         }
1502 };
1503
1504 /** Validate and fixup a map that's part of an update section.
1505  *
1506  * @param map to validate.
1507  * @param ctx data to pass to fixup function (currently unused).
1508  * @return 0 if valid else -1.
1509  */
1510 int modcall_fixup_update(vp_map_t *map, UNUSED void *ctx)
1511 {
1512         CONF_PAIR *cp = cf_item_to_pair(map->ci);
1513
1514         /*
1515          *      Anal-retentive checks.
1516          */
1517         if (DEBUG_ENABLED3) {
1518                 if ((map->lhs->type == TMPL_TYPE_ATTR) && (map->lhs->name[0] != '&')) {
1519                         WARN("%s[%d]: Please change attribute reference to '&%s %s ...'",
1520                              cf_pair_filename(cp), cf_pair_lineno(cp),
1521                              map->lhs->name, fr_int2str(fr_tokens, map->op, "<INVALID>"));
1522                 }
1523
1524                 if ((map->rhs->type == TMPL_TYPE_ATTR) && (map->rhs->name[0] != '&')) {
1525                         WARN("%s[%d]: Please change attribute reference to '... %s &%s'",
1526                              cf_pair_filename(cp), cf_pair_lineno(cp),
1527                              fr_int2str(fr_tokens, map->op, "<INVALID>"), map->rhs->name);
1528                 }
1529         }
1530
1531         /*
1532          *      Values used by unary operators should be literal ANY
1533          *
1534          *      We then free the template and alloc a NULL one instead.
1535          */
1536         if (map->op == T_OP_CMP_FALSE) {
1537                 if ((map->rhs->type != TMPL_TYPE_LITERAL) || (strcmp(map->rhs->name, "ANY") != 0)) {
1538                         WARN("%s[%d] Wildcard deletion MUST use '!* ANY'",
1539                              cf_pair_filename(cp), cf_pair_lineno(cp));
1540                 }
1541
1542                 TALLOC_FREE(map->rhs);
1543
1544                 map->rhs = tmpl_alloc(map, TMPL_TYPE_NULL, NULL, 0);
1545         }
1546
1547         /*
1548          *      Lots of sanity checks for insane people...
1549          */
1550
1551         /*
1552          *      What exactly where you expecting to happen here?
1553          */
1554         if ((map->lhs->type == TMPL_TYPE_ATTR) &&
1555             (map->rhs->type == TMPL_TYPE_LIST)) {
1556                 cf_log_err(map->ci, "Can't copy list into an attribute");
1557                 return -1;
1558         }
1559
1560         /*
1561          *      Depending on the attribute type, some operators are disallowed.
1562          */
1563         if ((map->lhs->type == TMPL_TYPE_ATTR) && (!fr_assignment_op[map->op] && !fr_equality_op[map->op])) {
1564                 cf_log_err(map->ci, "Invalid operator \"%s\" in update section.  "
1565                            "Only assignment or filter operators are allowed",
1566                            fr_int2str(fr_tokens, map->op, "<INVALID>"));
1567                 return -1;
1568         }
1569
1570         if (map->lhs->type == TMPL_TYPE_LIST) {
1571                 /*
1572                  *      Can't copy an xlat expansion or literal into a list,
1573                  *      we don't know what type of attribute we'd need
1574                  *      to create.
1575                  *
1576                  *      The only exception is where were using a unary
1577                  *      operator like !*.
1578                  */
1579                 if (map->op != T_OP_CMP_FALSE) switch (map->rhs->type) {
1580                 case TMPL_TYPE_XLAT:
1581                 case TMPL_TYPE_LITERAL:
1582                         cf_log_err(map->ci, "Can't copy value into list (we don't know which attribute to create)");
1583                         return -1;
1584
1585                 default:
1586                         break;
1587                 }
1588
1589                 /*
1590                  *      Only += and :=, and !* operators are supported
1591                  *      for lists.
1592                  */
1593                 switch (map->op) {
1594                 case T_OP_CMP_FALSE:
1595                         break;
1596
1597                 case T_OP_ADD:
1598                         if ((map->rhs->type != TMPL_TYPE_LIST) &&
1599                             (map->rhs->type != TMPL_TYPE_EXEC)) {
1600                                 cf_log_err(map->ci, "Invalid source for list assignment '%s += ...'", map->lhs->name);
1601                                 return -1;
1602                         }
1603                         break;
1604
1605                 case T_OP_SET:
1606                         if (map->rhs->type == TMPL_TYPE_EXEC) {
1607                                 WARN("%s[%d]: Please change ':=' to '=' for list assignment",
1608                                      cf_pair_filename(cp), cf_pair_lineno(cp));
1609                         }
1610
1611                         if (map->rhs->type != TMPL_TYPE_LIST) {
1612                                 cf_log_err(map->ci, "Invalid source for list assignment '%s := ...'", map->lhs->name);
1613                                 return -1;
1614                         }
1615                         break;
1616
1617                 case T_OP_EQ:
1618                         if (map->rhs->type != TMPL_TYPE_EXEC) {
1619                                 cf_log_err(map->ci, "Invalid source for list assignment '%s = ...'", map->lhs->name);
1620                                 return -1;
1621                         }
1622                         break;
1623
1624                 default:
1625                         cf_log_err(map->ci, "Operator \"%s\" not allowed for list assignment",
1626                                    fr_int2str(fr_tokens, map->op, "<INVALID>"));
1627                         return -1;
1628                 }
1629         }
1630
1631         /*
1632          *      If the map has a unary operator there's no further
1633          *      processing we need to, as RHS is unused.
1634          */
1635         if (map->op == T_OP_CMP_FALSE) return 0;
1636
1637         /*
1638          *      If LHS is an attribute, and RHS is a literal, we can
1639          *      preparse the information into a TMPL_TYPE_DATA.
1640          *
1641          *      Unless it's a unary operator in which case we
1642          *      ignore map->rhs.
1643          */
1644         if ((map->lhs->type == TMPL_TYPE_ATTR) && (map->rhs->type == TMPL_TYPE_LITERAL)) {
1645                 /*
1646                  *      It's a literal string, just copy it.
1647                  *      Don't escape anything.
1648                  */
1649                 if (!cf_new_escape &&
1650                     (map->lhs->tmpl_da->type == PW_TYPE_STRING) &&
1651                     (cf_pair_value_type(cp) == T_SINGLE_QUOTED_STRING)) {
1652                         tmpl_cast_in_place_str(map->rhs);
1653
1654                 } else {
1655                         /*
1656                          *      RHS is hex, try to parse it as
1657                          *      type-specific data.
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 /** Load a named module from "instantiate" or "policy".
2159  *
2160  * If it's "foo.method", look for "foo", and return "method" as the method
2161  * we wish to use, instead of the input component.
2162  *
2163  * @param[out] pcomponent Where to write the method we found, if any.  If no method is specified
2164  *      will be set to MOD_COUNT.
2165  * @param[in] real_name Complete name string e.g. foo.authorize.
2166  * @param[in] virtual_name Virtual module name e.g. foo.
2167  * @param[in] method_name Method override (may be NULL) or the method name e.g. authorize.
2168  * @return the CONF_SECTION specifying the virtual module.
2169  */
2170 static CONF_SECTION *virtual_module_find_cs(rlm_components_t *pcomponent,
2171                                             char const *real_name, char const *virtual_name, char const *method_name)
2172 {
2173         CONF_SECTION *cs, *subcs;
2174         rlm_components_t method = *pcomponent;
2175         char buffer[256];
2176
2177         /*
2178          *      Turn the method name into a method enum.
2179          */
2180         if (method_name) {
2181                 rlm_components_t i;
2182
2183                 for (i = MOD_AUTHENTICATE; i < MOD_COUNT; i++) {
2184                         if (strcmp(comp2str[i], method_name) == 0) break;
2185                 }
2186
2187                 if (i != MOD_COUNT) {
2188                         method = i;
2189                 } else {
2190                         method_name = NULL;
2191                         virtual_name = real_name;
2192                 }
2193         }
2194
2195         /*
2196          *      Look for "foo" in the "instantiate" section.  If we
2197          *      find it, AND there's no method name, we've found the
2198          *      right thing.
2199          *
2200          *      Return it to the caller, with the updated method.
2201          */
2202         cs = cf_section_find("instantiate");
2203         if (cs) {
2204                 /*
2205                  *      Found "foo".  Load it as "foo", or "foo.method".
2206                  */
2207                 subcs = cf_section_sub_find_name2(cs, NULL, virtual_name);
2208                 if (subcs) {
2209                         *pcomponent = method;
2210                         return subcs;
2211                 }
2212         }
2213
2214         /*
2215          *      Look for it in "policy".
2216          *
2217          *      If there's no policy section, we can't do anything else.
2218          */
2219         cs = cf_section_find("policy");
2220         if (!cs) return NULL;
2221
2222         /*
2223          *      "foo.authorize" means "load policy "foo" as method "authorize".
2224          *
2225          *      And bail out if there's no policy "foo".
2226          */
2227         if (method_name) {
2228                 subcs = cf_section_sub_find_name2(cs, NULL, virtual_name);
2229                 if (subcs) *pcomponent = method;
2230
2231                 return subcs;
2232         }
2233
2234         /*
2235          *      "foo" means "look for foo.component" first, to allow
2236          *      method overrides.  If that's not found, just look for
2237          *      a policy "foo".
2238          *
2239          */
2240         snprintf(buffer, sizeof(buffer), "%s.%s",
2241                  virtual_name, comp2str[method]);
2242         subcs = cf_section_sub_find_name2(cs, NULL, buffer);
2243         if (subcs) return subcs;
2244
2245         return cf_section_sub_find_name2(cs, NULL, virtual_name);
2246 }
2247
2248
2249 /*
2250  *      Compile one entry of a module call.
2251  */
2252 static modcallable *do_compile_modsingle(modcallable *parent,
2253                                          rlm_components_t component, CONF_ITEM *ci,
2254                                          int grouptype,
2255                                          char const **modname)
2256 {
2257         char const *modrefname, *p;
2258         modsingle *single;
2259         modcallable *csingle;
2260         module_instance_t *this;
2261         CONF_SECTION *cs, *subcs, *modules;
2262         CONF_SECTION *loop;
2263         char const *realname;
2264         rlm_components_t method = component;
2265
2266         if (cf_item_is_section(ci)) {
2267                 char const *name2;
2268
2269                 cs = cf_item_to_section(ci);
2270                 modrefname = cf_section_name1(cs);
2271                 name2 = cf_section_name2(cs);
2272                 if (!name2) name2 = "";
2273
2274                 /*
2275                  *      group{}, redundant{}, or append{} may appear
2276                  *      where a single module instance was expected.
2277                  *      In that case, we hand it off to
2278                  *      compile_modgroup
2279                  */
2280                 if (strcmp(modrefname, "group") == 0) {
2281                         *modname = name2;
2282                         return do_compile_modgroup(parent, component, cs,
2283                                                    GROUPTYPE_SIMPLE,
2284                                                    grouptype, MOD_GROUP);
2285
2286                 } else if (strcmp(modrefname, "redundant") == 0) {
2287                         *modname = name2;
2288
2289                         if (!all_children_are_modules(cs, modrefname)) {
2290                                 return NULL;
2291                         }
2292
2293                         return do_compile_modgroup(parent, component, cs,
2294                                                    GROUPTYPE_REDUNDANT,
2295                                                    grouptype, MOD_GROUP);
2296
2297                 } else if (strcmp(modrefname, "load-balance") == 0) {
2298                         *modname = name2;
2299
2300                         if (!all_children_are_modules(cs, modrefname)) {
2301                                 return NULL;
2302                         }
2303
2304                         return do_compile_modgroup(parent, component, cs,
2305                                                    GROUPTYPE_SIMPLE,
2306                                                    grouptype, MOD_LOAD_BALANCE);
2307
2308                 } else if (strcmp(modrefname, "redundant-load-balance") == 0) {
2309                         *modname = name2;
2310
2311                         if (!all_children_are_modules(cs, modrefname)) {
2312                                 return NULL;
2313                         }
2314
2315                         return do_compile_modgroup(parent, component, cs,
2316                                                    GROUPTYPE_REDUNDANT,
2317                                                    grouptype, MOD_REDUNDANT_LOAD_BALANCE);
2318
2319 #ifdef WITH_UNLANG
2320                 } else  if (strcmp(modrefname, "if") == 0) {
2321                         if (!cf_section_name2(cs)) {
2322                                 cf_log_err(ci, "'if' without condition");
2323                                 return NULL;
2324                         }
2325
2326                         *modname = name2;
2327                         csingle= do_compile_modgroup(parent, component, cs,
2328                                                      GROUPTYPE_SIMPLE,
2329                                                      grouptype, MOD_IF);
2330                         if (!csingle) return NULL;
2331                         *modname = name2;
2332
2333                         return csingle;
2334
2335                 } else  if (strcmp(modrefname, "elsif") == 0) {
2336                         if (parent &&
2337                             ((parent->type == MOD_LOAD_BALANCE) ||
2338                              (parent->type == MOD_REDUNDANT_LOAD_BALANCE))) {
2339                                 cf_log_err(ci, "'elsif' cannot be used in this section");
2340                                 return NULL;
2341                         }
2342
2343                         if (!cf_section_name2(cs)) {
2344                                 cf_log_err(ci, "'elsif' without condition");
2345                                 return NULL;
2346                         }
2347
2348                         *modname = name2;
2349                         return do_compile_modgroup(parent, component, cs,
2350                                                    GROUPTYPE_SIMPLE,
2351                                                    grouptype, MOD_ELSIF);
2352
2353                 } else  if (strcmp(modrefname, "else") == 0) {
2354                         if (parent &&
2355                             ((parent->type == MOD_LOAD_BALANCE) ||
2356                              (parent->type == MOD_REDUNDANT_LOAD_BALANCE))) {
2357                                 cf_log_err(ci, "'else' cannot be used in this section section");
2358                                 return NULL;
2359                         }
2360
2361                         if (cf_section_name2(cs)) {
2362                                 cf_log_err(ci, "Cannot have conditions on 'else'");
2363                                 return NULL;
2364                         }
2365
2366                         *modname = name2;
2367                         return  do_compile_modgroup(parent, component, cs,
2368                                                     GROUPTYPE_SIMPLE,
2369                                                     grouptype, MOD_ELSE);
2370
2371                 } else  if (strcmp(modrefname, "update") == 0) {
2372                         *modname = name2;
2373
2374                         return do_compile_modupdate(parent, component, cs,
2375                                                     name2);
2376
2377                 } else  if (strcmp(modrefname, "switch") == 0) {
2378                         *modname = name2;
2379
2380                         return do_compile_modswitch (parent, component, cs);
2381
2382                 } else  if (strcmp(modrefname, "case") == 0) {
2383                         *modname = name2;
2384
2385                         return do_compile_modcase(parent, component, cs);
2386
2387                 } else  if (strcmp(modrefname, "foreach") == 0) {
2388                         *modname = name2;
2389
2390                         return do_compile_modforeach(parent, component, cs);
2391
2392 #endif
2393                 } /* else it's something like sql { fail = 1 ...} */
2394
2395         } else if (!cf_item_is_pair(ci)) { /* CONF_DATA or some such */
2396                 return NULL;
2397
2398                 /*
2399                  *      Else it's a module reference, with updated return
2400                  *      codes.
2401                  */
2402         } else {
2403                 CONF_PAIR *cp = cf_item_to_pair(ci);
2404                 modrefname = cf_pair_attr(cp);
2405
2406                 /*
2407                  *      Actions (ok = 1), etc. are orthogonal to just
2408                  *      about everything else.
2409                  */
2410                 if (cf_pair_value(cp) != NULL) {
2411                         cf_log_err(ci, "Entry is not a reference to a module");
2412                         return NULL;
2413                 }
2414
2415                 /*
2416                  *      In-place xlat's via %{...}.
2417                  *
2418                  *      This should really be removed from the server.
2419                  */
2420                 if (((modrefname[0] == '%') && (modrefname[1] == '{')) ||
2421                     (modrefname[0] == '`')) {
2422                         return do_compile_modxlat(parent, component,
2423                                                   modrefname);
2424                 }
2425         }
2426
2427 #ifdef WITH_UNLANG
2428         /*
2429          *      These can't be over-ridden.
2430          */
2431         if (strcmp(modrefname, "break") == 0) {
2432                 if (!cf_item_is_pair(ci)) {
2433                         cf_log_err(ci, "Invalid use of 'break' as section name.");
2434                         return NULL;
2435                 }
2436
2437                 return do_compile_modbreak(parent, component, ci);
2438         }
2439
2440         if (strcmp(modrefname, "return") == 0) {
2441                 if (!cf_item_is_pair(ci)) {
2442                         cf_log_err(ci, "Invalid use of 'return' as section name.");
2443                         return NULL;
2444                 }
2445
2446                 return do_compile_modgroup(parent, component, NULL,
2447                                            GROUPTYPE_SIMPLE, GROUPTYPE_SIMPLE,
2448                                            MOD_RETURN);
2449         }
2450 #endif
2451
2452         /*
2453          *      Run a virtual server.  This is really terrible and
2454          *      should be deleted.
2455          */
2456         if (strncmp(modrefname, "server[", 7) == 0) {
2457                 char buffer[256];
2458
2459                 if (!cf_item_is_pair(ci)) {
2460                         cf_log_err(ci, "Invalid syntax");
2461                         return NULL;
2462                 }
2463
2464                 strlcpy(buffer, modrefname + 7, sizeof(buffer));
2465                 p = strrchr(buffer, ']');
2466                 if (!p || p[1] != '\0' || (p == buffer)) {
2467                         cf_log_err(ci, "Invalid server reference in \"%s\".", modrefname);
2468                         return NULL;
2469                 }
2470
2471                 buffer[p - buffer] = '\0';
2472
2473                 cs = cf_section_sub_find_name2(NULL, "server", buffer);
2474                 if (!cs) {
2475                         cf_log_err(ci, "No such server \"%s\".", buffer);
2476                         return NULL;
2477                 }
2478
2479                 /*
2480                  *      Ignore stupid attempts to over-ride the return
2481                  *      code.
2482                  */
2483                 return do_compile_modserver(parent, component, ci,
2484                                             modrefname, cs, buffer);
2485         }
2486
2487         /*
2488          *      We now have a name.  It can be one of two forms.  A
2489          *      bare module name, or a section named for the module,
2490          *      with over-rides for the return codes.
2491          *
2492          *      The name can refer to a real module, in the "modules"
2493          *      section.  In that case, the name will be either the
2494          *      first or second name of the sub-section of "modules".
2495          *
2496          *      Or, the name can refer to a policy, in the "policy"
2497          *      section.  In that case, the name will be first name of
2498          *      the sub-section of "policy".  Unless it's a "redudant"
2499          *      block...
2500          *
2501          *      Or, the name can refer to a "module.method", in which
2502          *      case we're calling a different method than normal for
2503          *      this section.
2504          *
2505          *      Or, the name can refer to a virtual module, in the
2506          *      "instantiate" section.  In that case, the name will be
2507          *      the first of the sub-section of "instantiate".  Unless
2508          *      it's a "redudant" block...
2509          *
2510          *      We try these in sequence, from the bottom up.  This is
2511          *      so that things in "instantiate" and "policy" can
2512          *      over-ride calls to real modules.
2513          */
2514
2515
2516         /*
2517          *      Try:
2518          *
2519          *      instantiate { ... name { ...} ... }
2520          *      instantiate { ... name.method { ...} ... }
2521          *      policy { ... name { .. } .. }
2522          *      policy { ... name.method { .. } .. }
2523          *
2524          *      The only difference between things in "instantiate"
2525          *      and "policy" is that "instantiate" will cause modules
2526          *      to be instantiated in a particular order.
2527          */
2528         subcs = NULL;
2529         p = strrchr(modrefname, '.');
2530         if (!p) {
2531                 subcs = virtual_module_find_cs(&method, modrefname, modrefname, NULL);
2532         } else {
2533                 char buffer[256];
2534
2535                 strlcpy(buffer, modrefname, sizeof(buffer));
2536                 buffer[p - modrefname] = '\0';
2537
2538                 subcs = virtual_module_find_cs(&method, modrefname, buffer, buffer + (p - modrefname) + 1);
2539         }
2540
2541         /*
2542          *      Check that we're not creating a loop.  We may
2543          *      be compiling an "sql" module reference inside
2544          *      of an "sql" policy.  If so, we allow the
2545          *      second "sql" to refer to the module.
2546          */
2547         for (loop = cf_item_parent(ci);
2548              loop && subcs;
2549              loop = cf_item_parent(cf_section_to_item(loop))) {
2550                 if (loop == subcs) {
2551                         subcs = NULL;
2552                 }
2553         }
2554
2555         /*
2556          *      We've found the relevant entry.  It MUST be a
2557          *      sub-section.
2558          *
2559          *      However, it can be a "redundant" block, or just a
2560          *      section name.
2561          */
2562         if (subcs) {
2563                 /*
2564                  *      modules.c takes care of ensuring that this is:
2565                  *
2566                  *      group foo { ...
2567                  *      load-balance foo { ...
2568                  *      redundant foo { ...
2569                  *      redundant-load-balance foo { ...
2570                  *
2571                  *      We can just recurs to compile the section as
2572                  *      if it was found here.
2573                  */
2574                 if (cf_section_name2(subcs)) {
2575                         csingle = do_compile_modsingle(parent,
2576                                                        method,
2577                                                        cf_section_to_item(subcs),
2578                                                        grouptype,
2579                                                        modname);
2580                 } else {
2581                         /*
2582                          *      We have:
2583                          *
2584                          *      foo { ...
2585                          *
2586                          *      So we compile it like it was:
2587                          *
2588                          *      group foo { ...
2589                          */
2590                         csingle = do_compile_modgroup(parent,
2591                                                       method,
2592                                                       subcs,
2593                                                       GROUPTYPE_SIMPLE,
2594                                                       grouptype, MOD_GROUP);
2595                 }
2596
2597                 /*
2598                  *      Return the compiled thing if we can.
2599                  */
2600                 if (!csingle) return NULL;
2601                 if (cf_item_is_pair(ci)) return csingle;
2602
2603                 /*
2604                  *      Else we have a reference to a policy, and that reference
2605                  *      over-rides the return codes for the policy!
2606                  */
2607                 goto action_override;
2608         }
2609
2610         /*
2611          *      Not a virtual module.  It must be a real module.
2612          */
2613         modules = cf_section_find("modules");
2614         this = NULL;
2615         realname = modrefname;
2616
2617         if (modules) {
2618                 /*
2619                  *      Try to load the optional module.
2620                  */
2621                 if (realname[0] == '-') realname++;
2622
2623                 /*
2624                  *      As of v3, the "modules" section contains
2625                  *      modules we use.  Configuration for other
2626                  *      modules belongs in raddb/mods-available/,
2627                  *      which isn't loaded into the "modules" section.
2628                  */
2629                 this = module_instantiate_method(modules, realname, &method);
2630                 if (this) goto allocate_csingle;
2631
2632                 /*
2633                  *      We were asked to MAYBE load it and it
2634                  *      doesn't exist.  Return a soft error.
2635                  */
2636                 if (realname != modrefname) {
2637                         *modname = modrefname;
2638                         return NULL;
2639                 }
2640         }
2641
2642         /*
2643          *      Can't de-reference it to anything.  Ugh.
2644          */
2645         *modname = NULL;
2646         cf_log_err(ci, "Failed to find \"%s\" as a module or policy.", modrefname);
2647         cf_log_err(ci, "Please verify that the configuration exists in %s/mods-enabled/%s.", get_radius_dir(), modrefname);
2648         return NULL;
2649
2650         /*
2651          *      We know it's all OK, allocate the structures, and fill
2652          *      them in.
2653          */
2654 allocate_csingle:
2655         /*
2656          *      Check if the module in question has the necessary
2657          *      component.
2658          */
2659         if (!this->entry->module->methods[method]) {
2660                 cf_log_err(ci, "\"%s\" modules aren't allowed in '%s' sections -- they have no such method.", this->entry->module->name,
2661                            comp2str[method]);
2662                 return NULL;
2663         }
2664
2665         single = talloc_zero(parent, modsingle);
2666         single->modinst = this;
2667         *modname = this->entry->module->name;
2668
2669         csingle = mod_singletocallable(single);
2670         csingle->parent = parent;
2671         csingle->next = NULL;
2672         if (!parent || (component != MOD_AUTHENTICATE)) {
2673                 memcpy(csingle->actions, defaultactions[component][grouptype],
2674                        sizeof csingle->actions);
2675         } else { /* inside Auth-Type has different rules */
2676                 memcpy(csingle->actions, authtype_actions[grouptype],
2677                        sizeof csingle->actions);
2678         }
2679         rad_assert(modrefname != NULL);
2680         csingle->name = realname;
2681         csingle->type = MOD_SINGLE;
2682         csingle->method = method;
2683
2684 action_override:
2685         /*
2686          *      Over-ride the default return codes of the module.
2687          */
2688         if (cf_item_is_section(ci)) {
2689                 CONF_ITEM *csi;
2690
2691                 cs = cf_item_to_section(ci);
2692                 for (csi=cf_item_find_next(cs, NULL);
2693                      csi != NULL;
2694                      csi=cf_item_find_next(cs, csi)) {
2695
2696                         if (cf_item_is_section(csi)) {
2697                                 cf_log_err(csi, "Subsection of module instance call not allowed");
2698                                 talloc_free(csingle);
2699                                 return NULL;
2700                         }
2701
2702                         if (!cf_item_is_pair(csi)) continue;
2703
2704                         if (!compile_action(csingle, cf_item_to_pair(csi))) {
2705                                 talloc_free(csingle);
2706                                 return NULL;
2707                         }
2708                 }
2709         }
2710
2711         return csingle;
2712 }
2713
2714 modcallable *compile_modsingle(TALLOC_CTX *ctx,
2715                                modcallable **parent,
2716                                rlm_components_t component, CONF_ITEM *ci,
2717                                char const **modname)
2718 {
2719         modcallable *ret;
2720
2721         if (!*parent) {
2722                 modcallable *c;
2723                 modgroup *g;
2724                 CONF_SECTION *parentcs;
2725
2726                 g = talloc_zero(ctx, modgroup);
2727                 memset(g, 0, sizeof(*g));
2728                 g->grouptype = GROUPTYPE_SIMPLE;
2729                 c = mod_grouptocallable(g);
2730                 c->next = NULL;
2731                 memcpy(c->actions,
2732                        defaultactions[component][GROUPTYPE_SIMPLE],
2733                        sizeof(c->actions));
2734
2735                 parentcs = cf_item_parent(ci);
2736                 c->name = cf_section_name2(parentcs);
2737                 if (!c->name) {
2738                         c->name = cf_section_name1(parentcs);
2739                 }
2740
2741                 c->type = MOD_GROUP;
2742                 c->method = component;
2743                 g->children = NULL;
2744
2745                 *parent = mod_grouptocallable(g);
2746         }
2747
2748         ret = do_compile_modsingle(*parent, component, ci,
2749                                    GROUPTYPE_SIMPLE,
2750                                    modname);
2751         dump_tree(component, ret);
2752         return ret;
2753 }
2754
2755
2756 /*
2757  *      Internal compile group code.
2758  */
2759 static modcallable *do_compile_modgroup(modcallable *parent,
2760                                         rlm_components_t component, CONF_SECTION *cs,
2761                                         int grouptype, int parentgrouptype, int mod_type)
2762 {
2763         int i;
2764         modgroup *g;
2765         modcallable *c;
2766         CONF_ITEM *ci;
2767
2768         g = talloc_zero(parent, modgroup);
2769         g->grouptype = grouptype;
2770         g->children = NULL;
2771         g->cs = cs;
2772
2773         c = mod_grouptocallable(g);
2774         c->parent = parent;
2775         c->type = mod_type;
2776         c->next = NULL;
2777         memset(c->actions, 0, sizeof(c->actions));
2778
2779         if (!cs) {              /* only for "break" and "return" */
2780                 c->name = "";
2781                 goto set_codes;
2782         }
2783
2784         /*
2785          *      Remember the name for printing, etc.
2786          *
2787          *      FIXME: We may also want to put the names into a
2788          *      rbtree, so that groups can reference each other...
2789          */
2790         c->name = cf_section_name2(cs);
2791         if (!c->name) {
2792                 c->name = cf_section_name1(cs);
2793                 if ((strcmp(c->name, "group") == 0) ||
2794                     (strcmp(c->name, "redundant") == 0)) {
2795                         c->name = "";
2796                 } else if (c->type == MOD_GROUP) {
2797                         c->type = MOD_POLICY;
2798                 }
2799         }
2800
2801 #ifdef WITH_UNLANG
2802         /*
2803          *      Do load-time optimizations
2804          */
2805         if ((c->type == MOD_IF) || (c->type == MOD_ELSIF) || (c->type == MOD_ELSE)) {
2806                 modgroup *f, *p;
2807
2808                 rad_assert(parent != NULL);
2809
2810                 if (c->type == MOD_IF) {
2811                         g->cond = cf_data_find(g->cs, "if");
2812                         rad_assert(g->cond != NULL);
2813
2814                 check_if:
2815                         if (g->cond->type == COND_TYPE_FALSE) {
2816                                 INFO(" # Skipping contents of '%s' as it is always 'false' -- %s:%d",
2817                                      unlang_keyword[g->mc.type],
2818                                      cf_section_filename(g->cs), cf_section_lineno(g->cs));
2819                                 goto set_codes;
2820                         }
2821
2822                 } else if (c->type == MOD_ELSIF) {
2823
2824                         g->cond = cf_data_find(g->cs, "if");
2825                         rad_assert(g->cond != NULL);
2826
2827                         rad_assert(parent != NULL);
2828                         p = mod_callabletogroup(parent);
2829
2830                         if (!p->tail) goto elsif_fail;
2831
2832                         /*
2833                          *      We're in the process of compiling the
2834                          *      section, so the parent's tail is the
2835                          *      previous "if" statement.
2836                          */
2837                         f = mod_callabletogroup(p->tail);
2838                         if ((f->mc.type != MOD_IF) &&
2839                             (f->mc.type != MOD_ELSIF)) {
2840                         elsif_fail:
2841                                 cf_log_err_cs(g->cs, "Invalid location for 'elsif'.  There is no preceding 'if' statement");
2842                                 talloc_free(g);
2843                                 return NULL;
2844                         }
2845
2846                         /*
2847                          *      If we took the previous condition, we
2848                          *      don't need to take this one.
2849                          *
2850                          *      We reset our condition to 'true', so
2851                          *      that subsequent sections can check
2852                          *      that they don't need to be executed.
2853                          */
2854                         if (f->cond->type == COND_TYPE_TRUE) {
2855                         skip_true:
2856                                 INFO(" # Skipping contents of '%s' as previous '%s' is always  'true' -- %s:%d",
2857                                      unlang_keyword[g->mc.type],
2858                                      unlang_keyword[f->mc.type],
2859                                      cf_section_filename(g->cs), cf_section_lineno(g->cs));
2860                                 g->cond = f->cond;
2861                                 goto set_codes;
2862                         }
2863                         goto check_if;
2864
2865                 } else {
2866                         rad_assert(c->type == MOD_ELSE);
2867
2868                         rad_assert(parent != NULL);
2869                         p = mod_callabletogroup(parent);
2870
2871                         if (!p->tail) goto else_fail;
2872
2873                         f = mod_callabletogroup(p->tail);
2874                         if ((f->mc.type != MOD_IF) &&
2875                             (f->mc.type != MOD_ELSIF)) {
2876                         else_fail:
2877                                 cf_log_err_cs(g->cs, "Invalid location for 'else'.  There is no preceding 'if' statement");
2878                                 talloc_free(g);
2879                                 return NULL;
2880                         }
2881
2882                         /*
2883                          *      If we took the previous condition, we
2884                          *      don't need to take this one.
2885                          */
2886                         if (f->cond->type == COND_TYPE_TRUE) goto skip_true;
2887                 }
2888
2889                 /*
2890                  *      Else we need to compile this section
2891                  */
2892         }
2893 #endif
2894
2895         /*
2896          *      Loop over the children of this group.
2897          */
2898         for (ci=cf_item_find_next(cs, NULL);
2899              ci != NULL;
2900              ci=cf_item_find_next(cs, ci)) {
2901
2902                 /*
2903                  *      Sections are references to other groups, or
2904                  *      to modules with updated return codes.
2905                  */
2906                 if (cf_item_is_section(ci)) {
2907                         char const *junk = NULL;
2908                         modcallable *single;
2909                         CONF_SECTION *subcs = cf_item_to_section(ci);
2910
2911                         single = do_compile_modsingle(c, component, ci,
2912                                                       grouptype, &junk);
2913                         if (!single) {
2914                                 cf_log_err(ci, "Failed to parse \"%s\" subsection.",
2915                                        cf_section_name1(subcs));
2916                                 talloc_free(c);
2917                                 return NULL;
2918                         }
2919                         add_child(g, single);
2920
2921                 } else if (!cf_item_is_pair(ci)) { /* CONF_DATA */
2922                         continue;
2923
2924                 } else {
2925                         char const *attr, *value;
2926                         CONF_PAIR *cp = cf_item_to_pair(ci);
2927
2928                         attr = cf_pair_attr(cp);
2929                         value = cf_pair_value(cp);
2930
2931                         /*
2932                          *      A CONF_PAIR is either a module
2933                          *      instance with no actions
2934                          *      specified ...
2935                          */
2936                         if (!value) {
2937                                 modcallable *single;
2938                                 char const *junk = NULL;
2939
2940                                 single = do_compile_modsingle(c,
2941                                                               component,
2942                                                               ci,
2943                                                               grouptype,
2944                                                               &junk);
2945                                 if (!single) {
2946                                         if (cf_item_is_pair(ci) &&
2947                                             cf_pair_attr(cf_item_to_pair(ci))[0] == '-') {
2948                                                 continue;
2949                                         }
2950
2951                                         cf_log_err(ci,
2952                                                    "Failed to parse \"%s\" entry.",
2953                                                    attr);
2954                                         talloc_free(c);
2955                                         return NULL;
2956                                 }
2957                                 add_child(g, single);
2958
2959                                 /*
2960                                  *      Or a module instance with action.
2961                                  */
2962                         } else if (!compile_action(c, cp)) {
2963                                 talloc_free(c);
2964                                 return NULL;
2965                         } /* else it worked */
2966                 }
2967         }
2968
2969 set_codes:
2970         /*
2971          *      Set the default actions, if they haven't already been
2972          *      set.
2973          */
2974         for (i = 0; i < RLM_MODULE_NUMCODES; i++) {
2975                 if (!c->actions[i]) {
2976                         if (!parent || (component != MOD_AUTHENTICATE)) {
2977                                 c->actions[i] = defaultactions[component][parentgrouptype][i];
2978                         } else { /* inside Auth-Type has different rules */
2979                                 c->actions[i] = authtype_actions[parentgrouptype][i];
2980                         }
2981                 }
2982         }
2983
2984         switch (c->type) {
2985         default:
2986                 break;
2987
2988         case MOD_GROUP:
2989                 if (grouptype != GROUPTYPE_REDUNDANT) break;
2990                 /* FALL-THROUGH */
2991
2992         case MOD_LOAD_BALANCE:
2993         case MOD_REDUNDANT_LOAD_BALANCE:
2994                 if (!g->children) {
2995                         cf_log_err_cs(g->cs, "%s sections cannot be empty",
2996                                       cf_section_name1(g->cs));
2997                         talloc_free(c);
2998                         return NULL;
2999                 }
3000         }
3001
3002         /*
3003          *      FIXME: If there are no children, return NULL?
3004          */
3005         return mod_grouptocallable(g);
3006 }
3007
3008 modcallable *compile_modgroup(modcallable *parent,
3009                               rlm_components_t component, CONF_SECTION *cs)
3010 {
3011         modcallable *ret = do_compile_modgroup(parent, component, cs,
3012                                                GROUPTYPE_SIMPLE,
3013                                                GROUPTYPE_SIMPLE, MOD_GROUP);
3014
3015         if (rad_debug_lvl > 3) {
3016                 modcall_debug(ret, 2);
3017         }
3018
3019         return ret;
3020 }
3021
3022 void add_to_modcallable(modcallable *parent, modcallable *this)
3023 {
3024         modgroup *g;
3025
3026         rad_assert(this != NULL);
3027         rad_assert(parent != NULL);
3028
3029         g = mod_callabletogroup(parent);
3030
3031         add_child(g, this);
3032 }
3033
3034
3035 #ifdef WITH_UNLANG
3036 static bool pass2_xlat_compile(CONF_ITEM const *ci, vp_tmpl_t **pvpt, bool convert,
3037                                DICT_ATTR const *da)
3038 {
3039         ssize_t slen;
3040         char *fmt;
3041         char const *error;
3042         xlat_exp_t *head;
3043         vp_tmpl_t *vpt;
3044
3045         vpt = *pvpt;
3046
3047         rad_assert(vpt->type == TMPL_TYPE_XLAT);
3048
3049         fmt = talloc_typed_strdup(vpt, vpt->name);
3050         slen = xlat_tokenize(vpt, fmt, &head, &error);
3051
3052         if (slen < 0) {
3053                 char *spaces, *text;
3054
3055                 fr_canonicalize_error(vpt, &spaces, &text, slen, vpt->name);
3056
3057                 cf_log_err(ci, "Failed parsing expanded string:");
3058                 cf_log_err(ci, "%s", text);
3059                 cf_log_err(ci, "%s^ %s", spaces, error);
3060
3061                 talloc_free(spaces);
3062                 talloc_free(text);
3063                 return false;
3064         }
3065
3066         /*
3067          *      Convert %{Attribute-Name} to &Attribute-Name
3068          */
3069         if (convert) {
3070                 vp_tmpl_t *attr;
3071
3072                 attr = xlat_to_tmpl_attr(talloc_parent(vpt), head);
3073                 if (attr) {
3074                         /*
3075                          *      If it's a virtual attribute, leave it
3076                          *      alone.
3077                          */
3078                         if (attr->tmpl_da->flags.virtual) {
3079                                 talloc_free(attr);
3080                                 return true;
3081                         }
3082
3083                         /*
3084                          *      If the attribute is of incompatible
3085                          *      type, leave it alone.
3086                          */
3087                         if (da && (da->type != attr->tmpl_da->type)) {
3088                                 talloc_free(attr);
3089                                 return true;
3090                         }
3091
3092                         if (cf_item_is_pair(ci)) {
3093                                 CONF_PAIR *cp = cf_item_to_pair(ci);
3094
3095                                 WARN("%s[%d]: Please change \"%%{%s}\" to &%s",
3096                                        cf_pair_filename(cp), cf_pair_lineno(cp),
3097                                        attr->name, attr->name);
3098                         } else {
3099                                 CONF_SECTION *cs = cf_item_to_section(ci);
3100
3101                                 WARN("%s[%d]: Please change \"%%{%s}\" to &%s",
3102                                        cf_section_filename(cs), cf_section_lineno(cs),
3103                                        attr->name, attr->name);
3104                         }
3105                         TALLOC_FREE(*pvpt);
3106                         *pvpt = attr;
3107                         return true;
3108                 }
3109         }
3110
3111         /*
3112          *      Re-write it to be a pre-parsed XLAT structure.
3113          */
3114         vpt->type = TMPL_TYPE_XLAT_STRUCT;
3115         vpt->tmpl_xlat = head;
3116
3117         return true;
3118 }
3119
3120
3121 #ifdef HAVE_REGEX
3122 static bool pass2_regex_compile(CONF_ITEM const *ci, vp_tmpl_t *vpt)
3123 {
3124         ssize_t slen;
3125         regex_t *preg;
3126
3127         rad_assert(vpt->type == TMPL_TYPE_REGEX);
3128
3129         /*
3130          *      It's a dynamic expansion.  We can't expand the string,
3131          *      but we can pre-parse it as an xlat struct.  In that
3132          *      case, we convert it to a pre-compiled XLAT.
3133          *
3134          *      This is a little more complicated than it needs to be
3135          *      because radius_evaluate_map() keys off of the src
3136          *      template type, instead of the operators.  And, the
3137          *      pass2_xlat_compile() function expects to get passed an
3138          *      XLAT instead of a REGEX.
3139          */
3140         if (strchr(vpt->name, '%')) {
3141                 vpt->type = TMPL_TYPE_XLAT;
3142                 return pass2_xlat_compile(ci, &vpt, false, NULL);
3143         }
3144
3145         slen = regex_compile(vpt, &preg, vpt->name, vpt->len,
3146                              vpt->tmpl_iflag, vpt->tmpl_mflag, true, false);
3147         if (slen <= 0) {
3148                 char *spaces, *text;
3149
3150                 fr_canonicalize_error(vpt, &spaces, &text, slen, vpt->name);
3151
3152                 cf_log_err(ci, "Invalid regular expression:");
3153                 cf_log_err(ci, "%s", text);
3154                 cf_log_err(ci, "%s^ %s", spaces, fr_strerror());
3155
3156                 talloc_free(spaces);
3157                 talloc_free(text);
3158
3159                 return false;
3160         }
3161
3162         vpt->type = TMPL_TYPE_REGEX_STRUCT;
3163         vpt->tmpl_preg = preg;
3164
3165         return true;
3166 }
3167 #endif
3168
3169 static bool pass2_fixup_undefined(CONF_ITEM const *ci, vp_tmpl_t *vpt)
3170 {
3171         DICT_ATTR const *da;
3172
3173         rad_assert(vpt->type == TMPL_TYPE_ATTR_UNDEFINED);
3174
3175         da = dict_attrbyname(vpt->tmpl_unknown_name);
3176         if (!da) {
3177                 cf_log_err(ci, "Unknown attribute '%s'", vpt->tmpl_unknown_name);
3178                 return false;
3179         }
3180
3181         vpt->tmpl_da = da;
3182         vpt->type = TMPL_TYPE_ATTR;
3183         return true;
3184 }
3185
3186 static bool pass2_callback(void *ctx, fr_cond_t *c)
3187 {
3188         vp_map_t *map;
3189         vp_tmpl_t *vpt;
3190
3191         /*
3192          *      These don't get optimized.
3193          */
3194         if ((c->type == COND_TYPE_TRUE) ||
3195             (c->type == COND_TYPE_FALSE)) {
3196                 return true;
3197         }
3198
3199         /*
3200          *      Call children.
3201          */
3202         if (c->type == COND_TYPE_CHILD) return pass2_callback(ctx, c->data.child);
3203
3204         /*
3205          *      A few simple checks here.
3206          */
3207         if (c->type == COND_TYPE_EXISTS) {
3208                 if (c->data.vpt->type == TMPL_TYPE_XLAT) {
3209                         return pass2_xlat_compile(c->ci, &c->data.vpt, true, NULL);
3210                 }
3211
3212                 rad_assert(c->data.vpt->type != TMPL_TYPE_REGEX);
3213
3214                 /*
3215                  *      The existence check might have been &Foo-Bar,
3216                  *      where Foo-Bar is defined by a module.
3217                  */
3218                 if (c->pass2_fixup == PASS2_FIXUP_ATTR) {
3219                         if (!pass2_fixup_undefined(c->ci, c->data.vpt)) return false;
3220                         c->pass2_fixup = PASS2_FIXUP_NONE;
3221                 }
3222
3223                 /*
3224                  *      Convert virtual &Attr-Foo to "%{Attr-Foo}"
3225                  */
3226                 vpt = c->data.vpt;
3227                 if ((vpt->type == TMPL_TYPE_ATTR) && vpt->tmpl_da->flags.virtual) {
3228                         vpt->tmpl_xlat = xlat_from_tmpl_attr(vpt, vpt);
3229                         vpt->type = TMPL_TYPE_XLAT_STRUCT;
3230                 }
3231
3232                 return true;
3233         }
3234
3235         /*
3236          *      And tons of complicated checks.
3237          */
3238         rad_assert(c->type == COND_TYPE_MAP);
3239
3240         map = c->data.map;      /* shorter */
3241
3242         /*
3243          *      Auth-Type := foo
3244          *
3245          *      Where "foo" is dynamically defined.
3246          */
3247         if (c->pass2_fixup == PASS2_FIXUP_TYPE) {
3248                 if (!dict_valbyname(map->lhs->tmpl_da->attr,
3249                                     map->lhs->tmpl_da->vendor,
3250                                     map->rhs->name)) {
3251                         cf_log_err(map->ci, "Invalid reference to non-existent %s %s { ... }",
3252                                    map->lhs->tmpl_da->name,
3253                                    map->rhs->name);
3254                         return false;
3255                 }
3256
3257                 /*
3258                  *      These guys can't have a paircompare fixup applied.
3259                  */
3260                 c->pass2_fixup = PASS2_FIXUP_NONE;
3261                 return true;
3262         }
3263
3264         if (c->pass2_fixup == PASS2_FIXUP_ATTR) {
3265                 if (map->lhs->type == TMPL_TYPE_ATTR_UNDEFINED) {
3266                         if (!pass2_fixup_undefined(map->ci, map->lhs)) return false;
3267                 }
3268
3269                 if (map->rhs->type == TMPL_TYPE_ATTR_UNDEFINED) {
3270                         if (!pass2_fixup_undefined(map->ci, map->rhs)) return false;
3271                 }
3272
3273                 c->pass2_fixup = PASS2_FIXUP_NONE;
3274         }
3275
3276         /*
3277          *      Just in case someone adds a new fixup later.
3278          */
3279         rad_assert((c->pass2_fixup == PASS2_FIXUP_NONE) ||
3280                    (c->pass2_fixup == PASS2_PAIRCOMPARE));
3281
3282         /*
3283          *      Precompile xlat's
3284          */
3285         if (map->lhs->type == TMPL_TYPE_XLAT) {
3286                 /*
3287                  *      Compile the LHS to an attribute reference only
3288                  *      if the RHS is a literal.
3289                  *
3290                  *      @todo v3.1: allow anything anywhere.
3291                  */
3292                 if (map->rhs->type != TMPL_TYPE_LITERAL) {
3293                         if (!pass2_xlat_compile(map->ci, &map->lhs, false, NULL)) {
3294                                 return false;
3295                         }
3296                 } else {
3297                         if (!pass2_xlat_compile(map->ci, &map->lhs, true, NULL)) {
3298                                 return false;
3299                         }
3300
3301                         /*
3302                          *      Attribute compared to a literal gets
3303                          *      the literal cast to the data type of
3304                          *      the attribute.
3305                          *
3306                          *      The code in parser.c did this for
3307                          *
3308                          *              &Attr == data
3309                          *
3310                          *      But now we've just converted "%{Attr}"
3311                          *      to &Attr, so we've got to do it again.
3312                          */
3313                         if ((map->lhs->type == TMPL_TYPE_ATTR) &&
3314                             (map->rhs->type == TMPL_TYPE_LITERAL)) {
3315                                 /*
3316                                  *      RHS is hex, try to parse it as
3317                                  *      type-specific data.
3318                                  */
3319                                 if (map->lhs->auto_converted &&
3320                                     (map->rhs->name[0] == '0') && (map->rhs->name[1] == 'x') &&
3321                                     (map->rhs->len > 2) && ((map->rhs->len & 0x01) == 0)) {
3322                                         vpt = map->rhs;
3323                                         map->rhs = NULL;
3324
3325                                         if (!map_cast_from_hex(map, T_BARE_WORD, vpt->name)) {
3326                                                 map->rhs = vpt;
3327                                                 cf_log_err(map->ci, "%s", fr_strerror());
3328                                                 return -1;
3329                                         }
3330                                         talloc_free(vpt);
3331
3332                                 } else if ((map->rhs->len > 0) ||
3333                                            (map->op != T_OP_CMP_EQ) ||
3334                                            (map->lhs->tmpl_da->type == PW_TYPE_STRING) ||
3335                                            (map->lhs->tmpl_da->type == PW_TYPE_OCTETS)) {
3336
3337                                         if (tmpl_cast_in_place(map->rhs, map->lhs->tmpl_da->type, map->lhs->tmpl_da) < 0) {
3338                                                 cf_log_err(map->ci, "Failed to parse data type %s from string: %s",
3339                                                            fr_int2str(dict_attr_types, map->lhs->tmpl_da->type, "<UNKNOWN>"),
3340                                                            map->rhs->name);
3341                                                 return false;
3342                                         } /* else the cast was successful */
3343
3344                                 } else {        /* RHS is empty, it's just a check for empty / non-empty string */
3345                                         vpt = talloc_steal(c, map->lhs);
3346                                         map->lhs = NULL;
3347                                         talloc_free(c->data.map);
3348
3349                                         /*
3350                                          *      "%{Foo}" == '' ---> !Foo
3351                                          *      "%{Foo}" != '' ---> Foo
3352                                          */
3353                                         c->type = COND_TYPE_EXISTS;
3354                                         c->data.vpt = vpt;
3355                                         c->negate = !c->negate;
3356
3357                                         WARN("%s[%d]: Please change (\"%%{%s}\" %s '') to %c&%s",
3358                                              cf_section_filename(cf_item_to_section(c->ci)),
3359                                              cf_section_lineno(cf_item_to_section(c->ci)),
3360                                              vpt->name, c->negate ? "==" : "!=",
3361                                              c->negate ? '!' : ' ', vpt->name);
3362
3363                                         /*
3364                                          *      No more RHS, so we can't do more optimizations
3365                                          */
3366                                         return true;
3367                                 }
3368                         }
3369                 }
3370         }
3371
3372         if (map->rhs->type == TMPL_TYPE_XLAT) {
3373                 /*
3374                  *      Convert the RHS to an attribute reference only
3375                  *      if the LHS is an attribute reference, AND is
3376                  *      of the same type as the RHS.
3377                  *
3378                  *      We can fix this when the code in evaluate.c
3379                  *      can handle strings on the LHS, and attributes
3380                  *      on the RHS.  For now, the code in parser.c
3381                  *      forbids this.
3382                  */
3383                 if (map->lhs->type == TMPL_TYPE_ATTR) {
3384                         DICT_ATTR const *da = c->cast;
3385
3386                         if (!c->cast) da = map->lhs->tmpl_da;
3387
3388                         if (!pass2_xlat_compile(map->ci, &map->rhs, true, da)) {
3389                                 return false;
3390                         }
3391
3392                 } else {
3393                         if (!pass2_xlat_compile(map->ci, &map->rhs, false, NULL)) {
3394                                 return false;
3395                         }
3396                 }
3397         }
3398
3399         /*
3400          *      Convert bare refs to %{Foreach-Variable-N}
3401          */
3402         if ((map->lhs->type == TMPL_TYPE_LITERAL) &&
3403             (strncmp(map->lhs->name, "Foreach-Variable-", 17) == 0)) {
3404                 char *fmt;
3405                 ssize_t slen;
3406
3407                 fmt = talloc_asprintf(map->lhs, "%%{%s}", map->lhs->name);
3408                 slen = tmpl_afrom_str(map, &vpt, fmt, talloc_array_length(fmt) - 1,
3409                                       T_DOUBLE_QUOTED_STRING, REQUEST_CURRENT, PAIR_LIST_REQUEST, true);
3410                 if (slen < 0) {
3411                         char *spaces, *text;
3412
3413                         fr_canonicalize_error(map->ci, &spaces, &text, slen, fr_strerror());
3414
3415                         cf_log_err(map->ci, "Failed converting %s to xlat", map->lhs->name);
3416                         cf_log_err(map->ci, "%s", fmt);
3417                         cf_log_err(map->ci, "%s^ %s", spaces, text);
3418
3419                         talloc_free(spaces);
3420                         talloc_free(text);
3421                         talloc_free(fmt);
3422
3423                         return false;
3424                 }
3425                 talloc_free(map->lhs);
3426                 map->lhs = vpt;
3427         }
3428
3429 #ifdef HAVE_REGEX
3430         if (map->rhs->type == TMPL_TYPE_REGEX) {
3431                 if (!pass2_regex_compile(map->ci, map->rhs)) {
3432                         return false;
3433                 }
3434         }
3435         rad_assert(map->lhs->type != TMPL_TYPE_REGEX);
3436 #endif
3437
3438         /*
3439          *      Convert &Packet-Type to "%{Packet-Type}", because
3440          *      these attributes don't really exist.  The code to
3441          *      find an attribute reference doesn't work, but the
3442          *      xlat code does.
3443          */
3444         vpt = c->data.map->lhs;
3445         if ((vpt->type == TMPL_TYPE_ATTR) && vpt->tmpl_da->flags.virtual) {
3446                 if (!c->cast) c->cast = vpt->tmpl_da;
3447                 vpt->tmpl_xlat = xlat_from_tmpl_attr(vpt, vpt);
3448                 vpt->type = TMPL_TYPE_XLAT_STRUCT;
3449         }
3450
3451         /*
3452          *      Convert RHS to expansions, too.
3453          */
3454         vpt = c->data.map->rhs;
3455         if ((vpt->type == TMPL_TYPE_ATTR) && vpt->tmpl_da->flags.virtual) {
3456                 vpt->tmpl_xlat = xlat_from_tmpl_attr(vpt, vpt);
3457                 vpt->type = TMPL_TYPE_XLAT_STRUCT;
3458         }
3459
3460         /*
3461          *      @todo v3.1: do the same thing for the RHS...
3462          */
3463
3464         /*
3465          *      Only attributes can have a paircompare registered, and
3466          *      they can only be with the current REQUEST, and only
3467          *      with the request pairs.
3468          */
3469         if ((map->lhs->type != TMPL_TYPE_ATTR) ||
3470             (map->lhs->tmpl_request != REQUEST_CURRENT) ||
3471             (map->lhs->tmpl_list != PAIR_LIST_REQUEST)) {
3472                 return true;
3473         }
3474
3475         if (!radius_find_compare(map->lhs->tmpl_da)) return true;
3476
3477         if (map->rhs->type == TMPL_TYPE_ATTR) {
3478                 cf_log_err(map->ci, "Cannot compare virtual attribute %s to another attribute",
3479                            map->lhs->name);
3480                 return false;
3481         }
3482
3483         if (map->rhs->type == TMPL_TYPE_REGEX) {
3484                 cf_log_err(map->ci, "Cannot compare virtual attribute %s via a regex",
3485                            map->lhs->name);
3486                 return false;
3487         }
3488
3489         if (c->cast) {
3490                 cf_log_err(map->ci, "Cannot cast virtual attribute %s",
3491                            map->lhs->name);
3492                 return false;
3493         }
3494
3495         if (map->op != T_OP_CMP_EQ) {
3496                 cf_log_err(map->ci, "Must use '==' for comparisons with virtual attribute %s",
3497                            map->lhs->name);
3498                 return false;
3499         }
3500
3501         /*
3502          *      Mark it as requiring a paircompare() call, instead of
3503          *      fr_pair_cmp().
3504          */
3505         c->pass2_fixup = PASS2_PAIRCOMPARE;
3506
3507         return true;
3508 }
3509
3510
3511 /*
3512  *      Compile the RHS of update sections to xlat_exp_t
3513  */
3514 static bool modcall_pass2_update(modgroup *g)
3515 {
3516         vp_map_t *map;
3517
3518         for (map = g->map; map != NULL; map = map->next) {
3519                 if (map->rhs->type == TMPL_TYPE_XLAT) {
3520                         rad_assert(map->rhs->tmpl_xlat == NULL);
3521
3522                         /*
3523                          *      FIXME: compile to attribute && handle
3524                          *      the conversion in map_to_vp().
3525                          */
3526                         if (!pass2_xlat_compile(map->ci, &map->rhs, false, NULL)) {
3527                                 return false;
3528                         }
3529                 }
3530
3531                 rad_assert(map->rhs->type != TMPL_TYPE_REGEX);
3532
3533                 /*
3534                  *      Deal with undefined attributes now.
3535                  */
3536                 if (map->lhs->type == TMPL_TYPE_ATTR_UNDEFINED) {
3537                         if (!pass2_fixup_undefined(map->ci, map->lhs)) return false;
3538                 }
3539
3540                 if (map->rhs->type == TMPL_TYPE_ATTR_UNDEFINED) {
3541                         if (!pass2_fixup_undefined(map->ci, map->rhs)) return false;
3542                 }
3543         }
3544
3545         return true;
3546 }
3547 #endif
3548
3549 /*
3550  *      Do a second-stage pass on compiling the modules.
3551  */
3552 bool modcall_pass2(modcallable *mc)
3553 {
3554         ssize_t slen;
3555         char const *name2;
3556         modcallable *c;
3557         modgroup *g;
3558
3559         for (c = mc; c != NULL; c = c->next) {
3560                 switch (c->type) {
3561                 default:
3562                         rad_assert(0 == 1);
3563                         break;
3564
3565 #ifdef WITH_UNLANG
3566                 case MOD_UPDATE:
3567                         g = mod_callabletogroup(c);
3568                         if (g->done_pass2) goto do_next;
3569
3570                         name2 = cf_section_name2(g->cs);
3571                         if (!name2) {
3572                                 c->debug_name = unlang_keyword[c->type];
3573                         } else {
3574                                 c->debug_name = talloc_asprintf(c, "update %s", name2);
3575                         }
3576
3577                         if (!modcall_pass2_update(g)) {
3578                                 return false;
3579                         }
3580                         g->done_pass2 = true;
3581                         break;
3582
3583                 case MOD_XLAT:   /* @todo: pre-parse xlat's */
3584                 case MOD_REFERENCE:
3585                 case MOD_BREAK:
3586                 case MOD_RETURN:
3587 #endif
3588
3589                 case MOD_SINGLE:
3590                         c->debug_name = c->name;
3591                         break;  /* do nothing */
3592
3593 #ifdef WITH_UNLANG
3594                 case MOD_IF:
3595                 case MOD_ELSIF:
3596                         g = mod_callabletogroup(c);
3597                         if (g->done_pass2) goto do_next;
3598
3599                         name2 = cf_section_name2(g->cs);
3600                         c->debug_name = talloc_asprintf(c, "%s %s", unlang_keyword[c->type], name2);
3601
3602                         /*
3603                          *      The compilation code takes care of
3604                          *      simplifying 'true' and 'false'
3605                          *      conditions.  For others, we have to do
3606                          *      a second pass to parse && compile
3607                          *      xlats.
3608                          */
3609                         if (!((g->cond->type == COND_TYPE_TRUE) ||
3610                               (g->cond->type == COND_TYPE_FALSE))) {
3611                                 if (!fr_condition_walk(g->cond, pass2_callback, NULL)) {
3612                                         return false;
3613                                 }
3614                         }
3615
3616                         if (!modcall_pass2(g->children)) return false;
3617                         g->done_pass2 = true;
3618                         break;
3619 #endif
3620
3621 #ifdef WITH_UNLANG
3622                 case MOD_SWITCH:
3623                         g = mod_callabletogroup(c);
3624                         if (g->done_pass2) goto do_next;
3625
3626                         name2 = cf_section_name2(g->cs);
3627                         c->debug_name = talloc_asprintf(c, "%s %s", unlang_keyword[c->type], name2);
3628
3629                         /*
3630                          *      We had &Foo-Bar, where Foo-Bar is
3631                          *      defined by a module.
3632                          */
3633                         if (!g->vpt) {
3634                                 rad_assert(c->name != NULL);
3635                                 rad_assert(c->name[0] == '&');
3636                                 rad_assert(cf_section_name2_type(g->cs) == T_BARE_WORD);
3637
3638                                 slen = tmpl_afrom_str(g->cs, &g->vpt, c->name, strlen(c->name),
3639                                                       cf_section_name2_type(g->cs),
3640                                                       REQUEST_CURRENT, PAIR_LIST_REQUEST, true);
3641                                 if (slen < 0) {
3642                                         char *spaces, *text;
3643
3644                                 parse_error:
3645                                         fr_canonicalize_error(g->cs, &spaces, &text, slen, fr_strerror());
3646
3647                                         cf_log_err_cs(g->cs, "Syntax error");
3648                                         cf_log_err_cs(g->cs, "%s", c->name);
3649                                         cf_log_err_cs(g->cs, "%s^ %s", spaces, text);
3650
3651                                         talloc_free(spaces);
3652                                         talloc_free(text);
3653
3654                                         return false;
3655                                 }
3656
3657                                 goto do_children;
3658                         }
3659
3660                         /*
3661                          *      Statically compile xlats
3662                          */
3663                         if (g->vpt->type == TMPL_TYPE_XLAT) {
3664                                 if (!pass2_xlat_compile(cf_section_to_item(g->cs),
3665                                                         &g->vpt, true, NULL)) {
3666                                         return false;
3667                                 }
3668
3669                                 goto do_children;
3670                         }
3671
3672                         /*
3673                          *      Convert virtual &Attr-Foo to "%{Attr-Foo}"
3674                          */
3675                         if ((g->vpt->type == TMPL_TYPE_ATTR) && g->vpt->tmpl_da->flags.virtual) {
3676                                 g->vpt->tmpl_xlat = xlat_from_tmpl_attr(g->vpt, g->vpt);
3677                                 g->vpt->type = TMPL_TYPE_XLAT_STRUCT;
3678                         }
3679
3680                         /*
3681                          *      We may have: switch Foo-Bar {
3682                          *
3683                          *      where Foo-Bar is an attribute defined
3684                          *      by a module.  Since there's no leading
3685                          *      &, it's parsed as a literal.  But if
3686                          *      we can parse it as an attribute,
3687                          *      switch to using that.
3688                          */
3689                         if (g->vpt->type == TMPL_TYPE_LITERAL) {
3690                                 vp_tmpl_t *vpt;
3691
3692                                 slen = tmpl_afrom_str(g->cs, &vpt, c->name, strlen(c->name), cf_section_name2_type(g->cs),
3693                                                       REQUEST_CURRENT, PAIR_LIST_REQUEST, true);
3694                                 if (slen < 0) goto parse_error;
3695                                 if (vpt->type == TMPL_TYPE_ATTR) {
3696                                         talloc_free(g->vpt);
3697                                         g->vpt = vpt;
3698                                 }
3699
3700                                 goto do_children;
3701                         }
3702
3703                         /*
3704                          *      Warn about old-style configuration.
3705                          *
3706                          *      DEPRECATED: switch User-Name { ...
3707                          *      ALLOWED   : switch &User-Name { ...
3708                          */
3709                         if ((g->vpt->type == TMPL_TYPE_ATTR) &&
3710                             (c->name[0] != '&')) {
3711                                 WARN("%s[%d]: Please change %s to &%s",
3712                                      cf_section_filename(g->cs),
3713                                      cf_section_lineno(g->cs),
3714                                      c->name, c->name);
3715                         }
3716
3717                 do_children:
3718                         if (!modcall_pass2(g->children)) return false;
3719                         g->done_pass2 = true;
3720                         break;
3721
3722                 case MOD_CASE:
3723                         g = mod_callabletogroup(c);
3724                         if (g->done_pass2) goto do_next;
3725
3726                         name2 = cf_section_name2(g->cs);
3727                         if (!name2) {
3728                                 c->debug_name = unlang_keyword[c->type];
3729                         } else {
3730                                 c->debug_name = talloc_asprintf(c, "%s %s", unlang_keyword[c->type], name2);
3731                         }
3732
3733                         rad_assert(c->parent != NULL);
3734                         rad_assert(c->parent->type == MOD_SWITCH);
3735
3736                         /*
3737                          *      The statement may refer to an
3738                          *      attribute which doesn't exist until
3739                          *      all of the modules have been loaded.
3740                          *      Check for that now.
3741                          */
3742                         if (!g->vpt && c->name &&
3743                             (c->name[0] == '&') &&
3744                             (cf_section_name2_type(g->cs) == T_BARE_WORD)) {
3745                                 slen = tmpl_afrom_str(g->cs, &g->vpt, c->name, strlen(c->name),
3746                                                       cf_section_name2_type(g->cs),
3747                                                       REQUEST_CURRENT, PAIR_LIST_REQUEST, true);
3748                                 if (slen < 0) goto parse_error;
3749                         }
3750
3751                         /*
3752                          *      We have "case {...}".  There's no
3753                          *      argument, so we don't need to check
3754                          *      it.
3755                          */
3756                         if (!g->vpt) goto do_children;
3757
3758                         /*
3759                          *      Do type-specific checks on the case statement
3760                          */
3761                         if (g->vpt->type == TMPL_TYPE_LITERAL) {
3762                                 modgroup *f;
3763
3764                                 f = mod_callabletogroup(mc->parent);
3765                                 rad_assert(f->vpt != NULL);
3766
3767                                 /*
3768                                  *      We're switching over an
3769                                  *      attribute.  Check that the
3770                                  *      values match.
3771                                  */
3772                                 if (f->vpt->type == TMPL_TYPE_ATTR) {
3773                                         rad_assert(f->vpt->tmpl_da != NULL);
3774
3775                                         if (tmpl_cast_in_place(g->vpt, f->vpt->tmpl_da->type, f->vpt->tmpl_da) < 0) {
3776                                                 cf_log_err_cs(g->cs, "Invalid argument for case statement: %s",
3777                                                               fr_strerror());
3778                                                 return false;
3779                                         }
3780                                 }
3781
3782                                 goto do_children;
3783                         }
3784
3785                         if (g->vpt->type == TMPL_TYPE_ATTR_UNDEFINED) {
3786                                 if (!pass2_fixup_undefined(cf_section_to_item(g->cs), g->vpt)) {
3787                                         return false;
3788                                 }
3789                         }
3790
3791                         /*
3792                          *      Compile and sanity check xlat
3793                          *      expansions.
3794                          */
3795                         if (g->vpt->type == TMPL_TYPE_XLAT) {
3796                                 modgroup *f;
3797
3798                                 f = mod_callabletogroup(mc->parent);
3799                                 rad_assert(f->vpt != NULL);
3800
3801                                 /*
3802                                  *      Don't expand xlat's into an
3803                                  *      attribute of a different type.
3804                                  */
3805                                 if (f->vpt->type == TMPL_TYPE_ATTR) {
3806                                         if (!pass2_xlat_compile(cf_section_to_item(g->cs),
3807                                                                 &g->vpt, true, f->vpt->tmpl_da)) {
3808                                                 return false;
3809                                         }
3810                                 } else {
3811                                         if (!pass2_xlat_compile(cf_section_to_item(g->cs),
3812                                                                 &g->vpt, true, NULL)) {
3813                                                 return false;
3814                                         }
3815                                 }
3816                         }
3817
3818                         /*
3819                          *      Virtual attribute fixes for "case" statements, too.
3820                          */
3821                         if ((g->vpt->type == TMPL_TYPE_ATTR) && g->vpt->tmpl_da->flags.virtual) {
3822                                 g->vpt->tmpl_xlat = xlat_from_tmpl_attr(g->vpt, g->vpt);
3823                                 g->vpt->type = TMPL_TYPE_XLAT_STRUCT;
3824                         }
3825
3826                         if (!modcall_pass2(g->children)) return false;
3827                         g->done_pass2 = true;
3828                         break;
3829
3830                 case MOD_FOREACH:
3831                         g = mod_callabletogroup(c);
3832                         if (g->done_pass2) goto do_next;
3833
3834                         name2 = cf_section_name2(g->cs);
3835                         c->debug_name = talloc_asprintf(c, "%s %s", unlang_keyword[c->type], name2);
3836
3837                         /*
3838                          *      Already parsed, handle the children.
3839                          */
3840                         if (g->vpt) goto check_children;
3841
3842                         /*
3843                          *      We had &Foo-Bar, where Foo-Bar is
3844                          *      defined by a module.
3845                          */
3846                         rad_assert(c->name != NULL);
3847                         rad_assert(c->name[0] == '&');
3848                         rad_assert(cf_section_name2_type(g->cs) == T_BARE_WORD);
3849
3850                         /*
3851                          *      The statement may refer to an
3852                          *      attribute which doesn't exist until
3853                          *      all of the modules have been loaded.
3854                          *      Check for that now.
3855                          */
3856                         slen = tmpl_afrom_str(g->cs, &g->vpt, c->name, strlen(c->name), cf_section_name2_type(g->cs),
3857                                               REQUEST_CURRENT, PAIR_LIST_REQUEST, true);
3858                         if (slen < 0) goto parse_error;
3859
3860                 check_children:
3861                         rad_assert((g->vpt->type == TMPL_TYPE_ATTR) || (g->vpt->type == TMPL_TYPE_LIST));
3862                         if (g->vpt->tmpl_num != NUM_ALL) {
3863                                 cf_log_err_cs(g->cs, "MUST NOT use instance selectors in 'foreach'");
3864                                 return false;
3865                         }
3866                         if (!modcall_pass2(g->children)) return false;
3867                         g->done_pass2 = true;
3868                         break;
3869
3870                 case MOD_ELSE:
3871                         c->debug_name = unlang_keyword[c->type];
3872                         goto do_recurse;
3873
3874                 case MOD_POLICY:
3875                         g = mod_callabletogroup(c);
3876                         c->debug_name = talloc_asprintf(c, "%s %s", unlang_keyword[c->type], cf_section_name1(g->cs));
3877                         goto do_recurse;
3878 #endif
3879
3880                 case MOD_GROUP:
3881                 case MOD_LOAD_BALANCE:
3882                 case MOD_REDUNDANT_LOAD_BALANCE:
3883                         c->debug_name = unlang_keyword[c->type];
3884
3885 #ifdef WITH_UNLANG
3886                 do_recurse:
3887 #endif
3888                         g = mod_callabletogroup(c);
3889                         if (!g->cs) {
3890                                 c->debug_name = mc->name; /* for authorize, etc. */
3891
3892                         } else if (c->type == MOD_GROUP) { /* for Auth-Type, etc. */
3893                                 char const *name1 = cf_section_name1(g->cs);
3894
3895                                 if (strcmp(name1, unlang_keyword[c->type]) != 0) {
3896                                         name2 = cf_section_name2(g->cs);
3897
3898                                         if (!name2) {
3899                                                 c->debug_name = name1;
3900                                         } else {
3901                                                 c->debug_name = talloc_asprintf(c, "%s %s", name1, name2);
3902                                         }
3903                                 }
3904                         }
3905
3906                         if (g->done_pass2) goto do_next;
3907                         if (!modcall_pass2(g->children)) return false;
3908                         g->done_pass2 = true;
3909                         break;
3910                 }
3911
3912         do_next:
3913                 rad_assert(c->debug_name != NULL);
3914         }
3915
3916         return true;
3917 }
3918
3919 void modcall_debug(modcallable *mc, int depth)
3920 {
3921         modcallable *this;
3922         modgroup *g;
3923         vp_map_t *map;
3924         char buffer[1024];
3925
3926         for (this = mc; this != NULL; this = this->next) {
3927                 switch (this->type) {
3928                 default:
3929                         break;
3930
3931                 case MOD_SINGLE: {
3932                         modsingle *single = mod_callabletosingle(this);
3933
3934                         DEBUG("%.*s%s", depth, modcall_spaces,
3935                                 single->modinst->name);
3936                         }
3937                         break;
3938
3939 #ifdef WITH_UNLANG
3940                 case MOD_UPDATE:
3941                         g = mod_callabletogroup(this);
3942                         DEBUG("%.*s%s {", depth, modcall_spaces,
3943                                 unlang_keyword[this->type]);
3944
3945                         for (map = g->map; map != NULL; map = map->next) {
3946                                 map_prints(buffer, sizeof(buffer), map);
3947                                 DEBUG("%.*s%s", depth + 1, modcall_spaces, buffer);
3948                         }
3949
3950                         DEBUG("%.*s}", depth, modcall_spaces);
3951                         break;
3952
3953                 case MOD_ELSE:
3954                         g = mod_callabletogroup(this);
3955                         DEBUG("%.*s%s {", depth, modcall_spaces,
3956                                 unlang_keyword[this->type]);
3957                         modcall_debug(g->children, depth + 1);
3958                         DEBUG("%.*s}", depth, modcall_spaces);
3959                         break;
3960
3961                 case MOD_IF:
3962                 case MOD_ELSIF:
3963                         g = mod_callabletogroup(this);
3964                         fr_cond_sprint(buffer, sizeof(buffer), g->cond);
3965                         DEBUG("%.*s%s (%s) {", depth, modcall_spaces,
3966                                 unlang_keyword[this->type], buffer);
3967                         modcall_debug(g->children, depth + 1);
3968                         DEBUG("%.*s}", depth, modcall_spaces);
3969                         break;
3970
3971                 case MOD_SWITCH:
3972                 case MOD_CASE:
3973                         g = mod_callabletogroup(this);
3974                         tmpl_prints(buffer, sizeof(buffer), g->vpt, NULL);
3975                         DEBUG("%.*s%s %s {", depth, modcall_spaces,
3976                                 unlang_keyword[this->type], buffer);
3977                         modcall_debug(g->children, depth + 1);
3978                         DEBUG("%.*s}", depth, modcall_spaces);
3979                         break;
3980
3981                 case MOD_POLICY:
3982                 case MOD_FOREACH:
3983                         g = mod_callabletogroup(this);
3984                         DEBUG("%.*s%s %s {", depth, modcall_spaces,
3985                                 unlang_keyword[this->type], this->name);
3986                         modcall_debug(g->children, depth + 1);
3987                         DEBUG("%.*s}", depth, modcall_spaces);
3988                         break;
3989
3990                 case MOD_BREAK:
3991                         DEBUG("%.*sbreak", depth, modcall_spaces);
3992                         break;
3993
3994 #endif
3995                 case MOD_GROUP:
3996                         g = mod_callabletogroup(this);
3997                         DEBUG("%.*s%s {", depth, modcall_spaces,
3998                               unlang_keyword[this->type]);
3999                         modcall_debug(g->children, depth + 1);
4000                         DEBUG("%.*s}", depth, modcall_spaces);
4001                         break;
4002
4003
4004                 case MOD_LOAD_BALANCE:
4005                 case MOD_REDUNDANT_LOAD_BALANCE:
4006                         g = mod_callabletogroup(this);
4007                         DEBUG("%.*s%s {", depth, modcall_spaces,
4008                                 unlang_keyword[this->type]);
4009                         modcall_debug(g->children, depth + 1);
4010                         DEBUG("%.*s}", depth, modcall_spaces);
4011                         break;
4012                 }
4013         }
4014 }
4015
4016 int modcall_pass2_condition(fr_cond_t *c)
4017 {
4018         if (!fr_condition_walk(c, pass2_callback, NULL)) return -1;
4019
4020         return 0;
4021 }