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