Allow in-line xlat's. The parser is horrible, but this feature
[freeradius.git] / src / main / modcall.c
1 /*
2  * 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 #include <freeradius-devel/ident.h>
24 RCSID("$Id$")
25
26 #include <freeradius-devel/radiusd.h>
27 #include <freeradius-devel/modpriv.h>
28 #include <freeradius-devel/modcall.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                                         int, CONF_SECTION *,
35                                         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/README.failover */
47 struct modcallable {
48         modcallable *parent;
49         struct modcallable *next;
50         const char *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 #endif
55                MOD_POLICY, MOD_REFERENCE, MOD_XLAT } type;
56         int method;
57         int actions[RLM_MODULE_NUMCODES];
58 };
59
60 #define GROUPTYPE_SIMPLE        0
61 #define GROUPTYPE_REDUNDANT     1
62 #define GROUPTYPE_APPEND        2
63 #define GROUPTYPE_COUNT         3
64
65 typedef struct {
66         modcallable mc;         /* self */
67         int grouptype;  /* after mc */
68         modcallable *children;
69         CONF_SECTION *cs;
70         VALUE_PAIR *vps;
71 } modgroup;
72
73 typedef struct {
74         modcallable mc;
75         module_instance_t *modinst;
76 } modsingle;
77
78 typedef struct {
79         modcallable mc;
80         const char *ref_name;
81         CONF_SECTION *ref_cs;
82 } modref;
83
84 typedef struct {
85         modcallable mc;
86         const char *xlat_name;
87 } modxlat;
88
89 static const FR_NAME_NUMBER grouptype_table[] = {
90         { "", GROUPTYPE_SIMPLE },
91         { "redundant ", GROUPTYPE_REDUNDANT },
92         { "append ", GROUPTYPE_APPEND },
93         { NULL, -1 }
94 };
95
96 /* Simple conversions: modsingle and modgroup are subclasses of modcallable,
97  * so we often want to go back and forth between them. */
98 static modsingle *mod_callabletosingle(modcallable *p)
99 {
100         rad_assert(p->type==MOD_SINGLE);
101         return (modsingle *)p;
102 }
103 static modgroup *mod_callabletogroup(modcallable *p)
104 {
105         rad_assert((p->type > MOD_SINGLE) && (p->type <= MOD_POLICY));
106
107         return (modgroup *)p;
108 }
109 static modcallable *mod_singletocallable(modsingle *p)
110 {
111         return (modcallable *)p;
112 }
113 static modcallable *mod_grouptocallable(modgroup *p)
114 {
115         return (modcallable *)p;
116 }
117
118 static modref *mod_callabletoref(modcallable *p)
119 {
120         rad_assert(p->type==MOD_REFERENCE);
121         return (modref *)p;
122 }
123 static modcallable *mod_reftocallable(modref *p)
124 {
125         return (modcallable *)p;
126 }
127
128 static modxlat *mod_callabletoxlat(modcallable *p)
129 {
130         rad_assert(p->type==MOD_XLAT);
131         return (modxlat *)p;
132 }
133 static modcallable *mod_xlattocallable(modxlat *p)
134 {
135         return (modcallable *)p;
136 }
137
138 /* modgroups are grown by adding a modcallable to the end */
139 /* FIXME: This is O(N^2) */
140 static void add_child(modgroup *g, modcallable *c)
141 {
142         modcallable **head = &g->children;
143         modcallable *node = *head;
144         modcallable **last = head;
145
146         if (!c) return;
147
148         while (node) {
149                 last = &node->next;
150                 node = node->next;
151         }
152
153         rad_assert(c->next == NULL);
154         *last = c;
155         c->parent = mod_grouptocallable(g);
156 }
157
158 /* Here's where we recognize all of our keywords: first the rcodes, then the
159  * actions */
160 static const FR_NAME_NUMBER rcode_table[] = {
161         { "reject",     RLM_MODULE_REJECT       },
162         { "fail",       RLM_MODULE_FAIL         },
163         { "ok",         RLM_MODULE_OK           },
164         { "handled",    RLM_MODULE_HANDLED      },
165         { "invalid",    RLM_MODULE_INVALID      },
166         { "userlock",   RLM_MODULE_USERLOCK     },
167         { "notfound",   RLM_MODULE_NOTFOUND     },
168         { "noop",       RLM_MODULE_NOOP         },
169         { "updated",    RLM_MODULE_UPDATED      },
170         { NULL, 0 }
171 };
172
173
174 /*
175  *      Compile action && rcode for later use.
176  */
177 static int compile_action(modcallable *c, CONF_PAIR *cp)
178 {
179         int action;
180         const char *attr, *value;
181
182         attr = cf_pair_attr(cp);
183         value = cf_pair_value(cp);
184         if (!value) return 0;
185
186         if (!strcasecmp(value, "return"))
187                 action = MOD_ACTION_RETURN;
188
189         else if (!strcasecmp(value, "break"))
190                 action = MOD_ACTION_RETURN;
191
192         else if (!strcasecmp(value, "reject"))
193                 action = MOD_ACTION_REJECT;
194
195         else if (strspn(value, "0123456789")==strlen(value)) {
196                 action = atoi(value);
197
198                 /*
199                  *      Don't allow priority zero, for future use.
200                  */
201                 if (action == 0) return 0;
202         } else {
203                 cf_log_err(cf_pairtoitem(cp), "Unknown action '%s'.\n",
204                            value);
205                 return 0;
206         }
207
208         if (strcasecmp(attr, "default") != 0) {
209                 int rcode;
210
211                 rcode = fr_str2int(rcode_table, attr, -1);
212                 if (rcode < 0) {
213                         cf_log_err(cf_pairtoitem(cp),
214                                    "Unknown module rcode '%s'.\n",
215                                    attr);
216                         return 0;
217                 }
218                 c->actions[rcode] = action;
219
220         } else {                /* set all unset values to the default */
221                 int i;
222
223                 for (i = 0; i < RLM_MODULE_NUMCODES; i++) {
224                         if (!c->actions[i]) c->actions[i] = action;
225                 }
226         }
227
228         return 1;
229 }
230
231 /* Some short names for debugging output */
232 static const char * const comp2str[] = {
233         "authenticate",
234         "authorize",
235         "preacct",
236         "accounting",
237         "session",
238         "pre-proxy",
239         "post-proxy",
240         "post-auth"
241 };
242
243 #ifdef HAVE_PTHREAD_H
244 /*
245  *      Lock the mutex for the module
246  */
247 static void safe_lock(module_instance_t *instance)
248 {
249         if (instance->mutex)
250                 pthread_mutex_lock(instance->mutex);
251 }
252
253 /*
254  *      Unlock the mutex for the module
255  */
256 static void safe_unlock(module_instance_t *instance)
257 {
258         if (instance->mutex)
259                 pthread_mutex_unlock(instance->mutex);
260 }
261 #else
262 /*
263  *      No threads: these functions become NULL's.
264  */
265 #define safe_lock(foo)
266 #define safe_unlock(foo)
267 #endif
268
269 static int call_modsingle(int component, modsingle *sp, REQUEST *request,
270                           int default_result)
271 {
272         int myresult = default_result;
273
274         RDEBUG3("  modsingle[%s]: calling %s (%s) for request %d",
275                comp2str[component], sp->modinst->name,
276                sp->modinst->entry->name, request->number);
277         safe_lock(sp->modinst);
278
279         /*
280          *      For logging unresponsive children.
281          */
282         request->module = sp->modinst->name;
283
284         myresult = sp->modinst->entry->module->methods[component](
285                         sp->modinst->insthandle, request);
286
287         request->module = "";
288         safe_unlock(sp->modinst);
289         RDEBUG3("  modsingle[%s]: returned from %s (%s) for request %d",
290                comp2str[component], sp->modinst->name,
291                sp->modinst->entry->name, request->number);
292
293         return myresult;
294 }
295
296
297 static int default_component_results[RLM_COMPONENT_COUNT] = {
298         RLM_MODULE_REJECT,      /* AUTH */
299         RLM_MODULE_NOTFOUND,    /* AUTZ */
300         RLM_MODULE_NOOP,        /* PREACCT */
301         RLM_MODULE_NOOP,        /* ACCT */
302         RLM_MODULE_FAIL,        /* SESS */
303         RLM_MODULE_NOOP,        /* PRE_PROXY */
304         RLM_MODULE_NOOP,        /* POST_PROXY */
305         RLM_MODULE_NOOP         /* POST_AUTH */
306 };
307
308
309 static const char *group_name[] = {
310         "",
311         "single",
312         "group",
313         "load-balance group",
314         "redundant-load-balance group",
315 #ifdef WITH_UNLANG
316         "if",
317         "else",
318         "elsif",
319         "update",
320         "switch",
321         "case",
322 #endif
323         "policy"
324 };
325
326 static const char *modcall_spaces = "++++++++++++++++++++++++++++++++";
327
328 #define MODCALL_STACK_MAX (32)
329
330 /*
331  *      Don't call the modules recursively.  Instead, do them
332  *      iteratively, and manage the call stack ourselves.
333  */
334 typedef struct modcall_stack {
335         int pointer;
336
337         int priority[MODCALL_STACK_MAX];
338         int result[MODCALL_STACK_MAX];
339         modcallable *children[MODCALL_STACK_MAX];
340         modcallable *start[MODCALL_STACK_MAX];
341 } modcall_stack;
342
343
344 /*
345  *      Call a module, iteratively, with a local stack, rather than
346  *      recursively.  What did Paul Graham say about Lisp...?
347  */
348 int modcall(int component, modcallable *c, REQUEST *request)
349 {
350         int myresult;
351         modcall_stack stack;
352         modcallable *parent, *child;
353         modsingle *sp;
354         int if_taken, was_if;
355
356         if ((component < 0) || (component >= RLM_COMPONENT_COUNT)) {
357                 return RLM_MODULE_FAIL;
358         }
359
360         stack.pointer = 0;
361         stack.priority[0] = 0;
362         stack.children[0] = c;
363         myresult = stack.result[0] = default_component_results[component];
364         was_if = if_taken = FALSE;
365
366         while (1) {
367                 /*
368                  *      A module has taken too long to process the request,
369                  *      and we've been told to stop processing it.
370                  */
371                 if ((request->master_state == REQUEST_STOP_PROCESSING) ||
372                     (request->parent &&
373                      (request->parent->master_state == REQUEST_STOP_PROCESSING))) {
374                         myresult = RLM_MODULE_FAIL;
375                         break;
376                 }
377
378                 child = stack.children[stack.pointer];
379                 if (!child) {
380                         myresult = stack.result[stack.pointer];
381                         break;
382                 }
383                 parent = child->parent;
384
385 #ifdef WITH_UNLANG
386                 if ((child->type == MOD_ELSE) || (child->type == MOD_ELSIF)) {
387                         myresult = stack.result[stack.pointer];
388
389                         if (!was_if) { /* error */
390                                 RDEBUG2("%.*s ... skipping %s for request %d: No preceding \"if\"",
391                                        stack.pointer + 1, modcall_spaces,
392                                        group_name[child->type],
393                                        request->number);
394                                 goto unroll;
395                         }
396                         if (if_taken) {
397                                 RDEBUG2("%.*s ... skipping %s for request %d: Preceding \"if\" was taken",
398                                        stack.pointer + 1, modcall_spaces,
399                                        group_name[child->type],
400                                        request->number);
401                                 goto unroll;
402                         }
403                 }
404
405                 /*
406                  *      "if" or "elsif".  Evaluate the condition.
407                  */
408                 if ((child->type == MOD_IF) || (child->type == MOD_ELSIF)) {
409                         int condition = TRUE;
410                         const char *p = child->name;
411
412                         RDEBUG2("%.*s? %s %s",
413                                stack.pointer + 1, modcall_spaces,
414                                (child->type == MOD_IF) ? "if" : "elsif",
415                                child->name);
416
417                         if (radius_evaluate_condition(request, myresult,
418                                                       0, &p, TRUE, &condition)) {
419                                 RDEBUG2("%.*s? %s %s -> %s",
420                                        stack.pointer + 1, modcall_spaces,
421                                        (child->type == MOD_IF) ? "if" : "elsif",
422                                        child->name, (condition != FALSE) ? "TRUE" : "FALSE");
423                         } else {
424                                 /*
425                                  *      This should never happen, the
426                                  *      condition is checked when the
427                                  *      module section is loaded.
428                                  */
429                                 condition = FALSE;
430                         }
431
432                         if (!condition) {
433                                 stack.result[stack.pointer] = myresult;
434                                 stack.children[stack.pointer] = NULL;
435                                 was_if = TRUE;
436                                 if_taken = FALSE;
437                                 goto next_section;
438                         } /* else process it as a simple group */
439                 }
440
441                 if (child->type == MOD_UPDATE) {
442                         int rcode;
443                         modgroup *g = mod_callabletogroup(child);
444
445                         rcode = radius_update_attrlist(request, g->cs,
446                                                        g->vps, child->name);
447                         if (rcode != RLM_MODULE_UPDATED) {
448                                 myresult = rcode;
449                         }
450                         goto handle_result;
451                 }
452 #endif
453         
454                 if (child->type == MOD_REFERENCE) {
455                         modref *mr = mod_callabletoref(child);
456                         const char *server = request->server;
457
458                         if (server == mr->ref_name) {
459                                 RDEBUG("WARNING: Suppressing recursive call to server %s", server);
460                                 myresult = RLM_MODULE_NOOP;
461                                 goto handle_result;
462                         }
463                         
464                         request->server = mr->ref_name;
465                         RDEBUG("server %s { # nested call", mr->ref_name);
466                         myresult = indexed_modcall(component, 0, request);
467                         RDEBUG("} # server %s with nested call", mr->ref_name);
468                         request->server = server;
469                         goto handle_result;
470                 }
471
472                 if (child->type == MOD_XLAT) {
473                         modxlat *mx = mod_callabletoxlat(child);
474                         char buffer[128];
475
476                         radius_xlat(buffer, sizeof(buffer), mx->xlat_name,
477                                     request, NULL);
478                         goto handle_result;
479                 }
480
481                 /*
482                  *      Child is a group that has children of it's own.
483                  */
484                 if (child->type != MOD_SINGLE) {
485                         int count = 1;
486                         modcallable *p, *q;
487 #ifdef WITH_UNLANG
488                         modcallable *null_case;
489 #endif
490                         modgroup *g = mod_callabletogroup(child);
491
492                         stack.pointer++;
493
494                         /*
495                          *      Catastrophic error.  This SHOULD have
496                          *      been caught when we were reading in the
497                          *      conf files.
498                          *
499                          *      FIXME: Do so.
500                          */
501                         if (stack.pointer >= MODCALL_STACK_MAX) {
502                                 radlog(L_ERR, "Internal sanity check failed: module stack is too deep");
503                                 exit(1);
504                         }
505
506                         stack.priority[stack.pointer] = 0;
507                         stack.result[stack.pointer] = default_component_results[component];
508                         switch (child->type) {
509 #ifdef WITH_UNLANG
510                                 char buffer[1024];
511
512                         case MOD_IF:
513                         case MOD_ELSE:
514                         case MOD_ELSIF:
515                         case MOD_CASE:
516 #endif
517                         case MOD_GROUP:
518                         case MOD_POLICY: /* same as MOD_GROUP */
519                                 stack.children[stack.pointer] = g->children;
520                                 break;
521
522                                 /*
523                                  *      See the "camel book" for why
524                                  *      this works.
525                                  *
526                                  *      If (rand(0..n) < 1), pick the
527                                  *      current realm.  We add a scale
528                                  *      factor of 65536, to avoid
529                                  *      floating point.
530                                  */
531                         case MOD_LOAD_BALANCE:
532                         case MOD_REDUNDANT_LOAD_BALANCE:
533                                 q = NULL;
534                                 for(p = g->children; p; p = p->next) {
535                                         if (!q) {
536                                                 q = p;
537                                                 count = 1;
538                                                 continue;
539                                         }
540
541                                         count++;
542
543                                         if ((count * (fr_rand() & 0xffff)) < (uint32_t) 0x10000) {
544                                                 q = p;
545                                         }
546                                 }
547                                 stack.children[stack.pointer] = q;
548                                 break;
549
550 #ifdef WITH_UNLANG
551                         case MOD_SWITCH:
552                                 radius_xlat(buffer, sizeof(buffer),
553                                             child->name, request, NULL);
554
555                                 null_case = q = NULL;
556                                 for(p = g->children; p; p = p->next) {
557                                         if (!p->name) {
558                                                 if (!null_case) null_case = p;
559                                                 continue;
560                                         }
561                                         if (strcmp(buffer, p->name) == 0) {
562                                                 q = p;
563                                                 break;
564                                         }
565                                 }
566
567                                 if (!q) q = null_case;
568
569                                 stack.children[stack.pointer] = q;
570                                 break;
571 #endif
572
573                         default:
574                                 RDEBUG2("Internal sanity check failed in modcall %d", child->type);
575                                 exit(1); /* internal sanity check failure */
576                                 break;
577                         }
578
579
580                         stack.start[stack.pointer] = stack.children[stack.pointer];
581
582                         RDEBUG2("%.*s- entering %s %s",
583                                stack.pointer, modcall_spaces,
584                                group_name[child->type],
585                                child->name ? child->name : "");
586
587                         /*
588                          *      Catch the special case of a NULL group.
589                          */
590                         if (!stack.children[stack.pointer]) {
591                                 /*
592                                  *      Print message for NULL group
593                                  */
594                                 RDEBUG2("%.*s- %s %s returns %s",
595                                        stack.pointer + 1, modcall_spaces,
596                                        group_name[child->type],
597                                        child->name ? child->name : "",
598                                        fr_int2str(rcode_table,
599                                                     stack.result[stack.pointer],
600                                                     "??"));
601                                 goto do_return;
602                         }
603
604                         /*
605                          *      The child may be a group, so we want to
606                          *      recurse into it's children, rather than
607                          *      falling through to the code below.
608                          */
609                         continue;
610                 }
611
612                 /*
613                  *      Process a stand-alone child, and fall through
614                  *      to dealing with it's parent.
615                  */
616                 sp = mod_callabletosingle(child);
617
618                 myresult = call_modsingle(child->method, sp, request,
619                                           default_component_results[component]);
620         handle_result:
621                 RDEBUG2("%.*s[%s] returns %s",
622                        stack.pointer + 1, modcall_spaces,
623                        child->name ? child->name : "",
624                        fr_int2str(rcode_table, myresult, "??"));
625
626                 /*
627                  *      This is a bit of a hack...
628                  */
629                 if (component != RLM_COMPONENT_SESS) request->simul_max = myresult;
630
631                 /*
632                  *      FIXME: Allow modules to push a modcallable
633                  *      onto this stack.  This should simplify
634                  *      configuration a LOT!
635                  *
636                  *      Once we do that, we can't do load-time
637                  *      checking of the maximum stack depth, and we've
638                  *      got to cache the stack pointer before storing
639                  *      myresult.
640                  *
641                  *      Also, if the stack changed, we need to set
642                  *      children[ptr] to NULL, and process the next
643                  *      entry on the stack, rather than falling
644                  *      through to finalize the processing of this
645                  *      entry.
646                  *
647                  *      Don't put "myresult" on the stack here,
648                  *      we have to do so with priority.
649                  */
650
651                 /*
652                  *      We roll back up the stack at this point.
653                  */
654         unroll:
655                 /*
656                  *      The child's action says return.  Do so.
657                  */
658                 if (child->actions[myresult] == MOD_ACTION_RETURN) {
659                         stack.result[stack.pointer] = myresult;
660                         stack.children[stack.pointer] = NULL;
661                         goto do_return;
662                 }
663
664                 /*
665                  *      If "reject", break out of the loop and return
666                  *      reject.
667                  */
668                 if (child->actions[myresult] == MOD_ACTION_REJECT) {
669                         stack.children[stack.pointer] = NULL;
670                         stack.result[stack.pointer] = RLM_MODULE_REJECT;
671                         goto do_return;
672                 }
673
674                 /*
675                  *      Otherwise, the action is a number, the
676                  *      preference level of this return code. If no
677                  *      higher preference has been seen yet, remember
678                  *      this one.
679                  */
680                 if (child->actions[myresult] >= stack.priority[stack.pointer]) {
681                         stack.result[stack.pointer] = myresult;
682                         stack.priority[stack.pointer] = child->actions[myresult];
683                 }
684
685
686 #ifdef WITH_UNLANG
687         next_section:
688 #endif
689                 /*
690                  *      No parent, we must be done.
691                  */
692                 if (!parent) {
693                         rad_assert(stack.pointer == 0);
694                         myresult = stack.result[0];
695                         break;
696                 }
697
698                 rad_assert(child != NULL);
699
700                 /*
701                  *      Go to the "next" child, whatever that is.
702                  */
703                 switch (parent->type) {
704 #ifdef WITH_UNLANG
705                         case MOD_IF:
706                         case MOD_ELSE:
707                         case MOD_ELSIF:
708                         case MOD_CASE:
709 #endif
710                         case MOD_GROUP:
711                         case MOD_POLICY: /* same as MOD_GROUP */
712                                 stack.children[stack.pointer] = child->next;
713                                 break;
714
715 #ifdef WITH_UNLANG
716                         case MOD_SWITCH:
717 #endif
718                         case MOD_LOAD_BALANCE:
719                                 stack.children[stack.pointer] = NULL;
720                                 break;
721
722                         case MOD_REDUNDANT_LOAD_BALANCE:
723                                 if (child->next) {
724                                         stack.children[stack.pointer] = child->next;
725                                 } else {
726                                         modgroup *g = mod_callabletogroup(parent);
727
728                                         stack.children[stack.pointer] = g->children;
729                                 }
730                                 if (stack.children[stack.pointer] == stack.start[stack.pointer]) {
731                                         stack.children[stack.pointer] = NULL;
732                                 }
733                                 break;
734                         default:
735                                 RDEBUG2("Internal sanity check failed in modcall  next %d", child->type);
736                                 exit(1);
737                 }
738
739                 /*
740                  *      No child, we're done this group, and we return
741                  *      "myresult" to the caller by pushing it back up
742                  *      the stack.
743                  */
744                 if (!stack.children[stack.pointer]) {
745                 do_return:
746                         rad_assert(stack.pointer > 0);
747                         myresult = stack.result[stack.pointer];
748                         stack.pointer--;
749
750                         if (stack.pointer == 0) break;
751
752                         RDEBUG2("%.*s- %s %s returns %s",
753                                stack.pointer + 1, modcall_spaces,
754                                group_name[parent->type],
755                                parent->name ? parent->name : "",
756                                fr_int2str(rcode_table, myresult, "??"));
757
758 #ifdef WITH_UNLANG
759                         if ((parent->type == MOD_IF) ||
760                             (parent->type == MOD_ELSIF)) {
761                                 if_taken = was_if = TRUE;
762                         } else {
763                                 if_taken = was_if = FALSE;
764                         }
765 #endif
766
767                         /*
768                          *      Unroll the stack.
769                          */
770                         child = stack.children[stack.pointer];
771                         parent = child->parent;
772                         goto unroll;
773                 }
774
775         } /* loop until done */
776
777         return myresult;
778 }
779
780
781 #if 0
782 static const char *action2str(int action)
783 {
784         static char buf[32];
785         if(action==MOD_ACTION_RETURN)
786                 return "return";
787         if(action==MOD_ACTION_REJECT)
788                 return "reject";
789         snprintf(buf, sizeof buf, "%d", action);
790         return buf;
791 }
792
793 /* If you suspect a bug in the parser, you'll want to use these dump
794  * functions. dump_tree should reproduce a whole tree exactly as it was found
795  * in radiusd.conf, but in long form (all actions explicitly defined) */
796 static void dump_mc(modcallable *c, int indent)
797 {
798         int i;
799
800         if(c->type==MOD_SINGLE) {
801                 modsingle *single = mod_callabletosingle(c);
802                 RDEBUG("%.*s%s {", indent, "\t\t\t\t\t\t\t\t\t\t\t",
803                         single->modinst->name);
804         } else {
805                 modgroup *g = mod_callabletogroup(c);
806                 modcallable *p;
807                 RDEBUG("%.*s%s {", indent, "\t\t\t\t\t\t\t\t\t\t\t",
808                       group_name[c->type]);
809                 for(p = g->children;p;p = p->next)
810                         dump_mc(p, indent+1);
811         }
812
813         for(i = 0; i<RLM_MODULE_NUMCODES; ++i) {
814                 RDEBUG("%.*s%s = %s", indent+1, "\t\t\t\t\t\t\t\t\t\t\t",
815                       fr_int2str(rcode_table, i, "??"),
816                       action2str(c->actions[i]));
817         }
818
819         RDEBUG("%.*s}", indent, "\t\t\t\t\t\t\t\t\t\t\t");
820 }
821
822 static void dump_tree(int comp, modcallable *c)
823 {
824         RDEBUG("[%s]", comp2str[comp]);
825         dump_mc(c, 0);
826 }
827 #else
828 #define dump_tree(a, b)
829 #endif
830
831 /* These are the default actions. For each component, the group{} block
832  * behaves like the code from the old module_*() function. redundant{} and
833  * append{} are based on my guesses of what they will be used for. --Pac. */
834 static const int
835 defaultactions[RLM_COMPONENT_COUNT][GROUPTYPE_COUNT][RLM_MODULE_NUMCODES] =
836 {
837         /* authenticate */
838         {
839                 /* group */
840                 {
841                         MOD_ACTION_RETURN,      /* reject   */
842                         1,                      /* fail     */
843                         MOD_ACTION_RETURN,      /* ok       */
844                         MOD_ACTION_RETURN,      /* handled  */
845                         1,                      /* invalid  */
846                         MOD_ACTION_RETURN,      /* userlock */
847                         MOD_ACTION_RETURN,      /* notfound */
848                         1,                      /* noop     */
849                         1                       /* updated  */
850                 },
851                 /* redundant */
852                 {
853                         MOD_ACTION_RETURN,      /* reject   */
854                         1,                      /* fail     */
855                         MOD_ACTION_RETURN,      /* ok       */
856                         MOD_ACTION_RETURN,      /* handled  */
857                         MOD_ACTION_RETURN,      /* invalid  */
858                         MOD_ACTION_RETURN,      /* userlock */
859                         MOD_ACTION_RETURN,      /* notfound */
860                         MOD_ACTION_RETURN,      /* noop     */
861                         MOD_ACTION_RETURN       /* updated  */
862                 },
863                 /* append */
864                 {
865                         MOD_ACTION_RETURN,      /* reject   */
866                         1,                      /* fail     */
867                         MOD_ACTION_RETURN,      /* ok       */
868                         MOD_ACTION_RETURN,      /* handled  */
869                         MOD_ACTION_RETURN,      /* invalid  */
870                         MOD_ACTION_RETURN,      /* userlock */
871                         2,                      /* notfound */
872                         MOD_ACTION_RETURN,      /* noop     */
873                         MOD_ACTION_RETURN       /* updated  */
874                 }
875         },
876         /* authorize */
877         {
878                 /* group */
879                 {
880                         MOD_ACTION_RETURN,      /* reject   */
881                         MOD_ACTION_RETURN,      /* fail     */
882                         3,                      /* ok       */
883                         MOD_ACTION_RETURN,      /* handled  */
884                         MOD_ACTION_RETURN,      /* invalid  */
885                         MOD_ACTION_RETURN,      /* userlock */
886                         1,                      /* notfound */
887                         2,                      /* noop     */
888                         4                       /* updated  */
889                 },
890                 /* redundant */
891                 {
892                         MOD_ACTION_RETURN,      /* reject   */
893                         1,                      /* fail     */
894                         MOD_ACTION_RETURN,      /* ok       */
895                         MOD_ACTION_RETURN,      /* handled  */
896                         MOD_ACTION_RETURN,      /* invalid  */
897                         MOD_ACTION_RETURN,      /* userlock */
898                         MOD_ACTION_RETURN,      /* notfound */
899                         MOD_ACTION_RETURN,      /* noop     */
900                         MOD_ACTION_RETURN       /* updated  */
901                 },
902                 /* append */
903                 {
904                         MOD_ACTION_RETURN,      /* reject   */
905                         1,                      /* fail     */
906                         MOD_ACTION_RETURN,      /* ok       */
907                         MOD_ACTION_RETURN,      /* handled  */
908                         MOD_ACTION_RETURN,      /* invalid  */
909                         MOD_ACTION_RETURN,      /* userlock */
910                         2,                      /* notfound */
911                         MOD_ACTION_RETURN,      /* noop     */
912                         MOD_ACTION_RETURN       /* updated  */
913                 }
914         },
915         /* preacct */
916         {
917                 /* group */
918                 {
919                         MOD_ACTION_RETURN,      /* reject   */
920                         MOD_ACTION_RETURN,      /* fail     */
921                         2,                      /* ok       */
922                         MOD_ACTION_RETURN,      /* handled  */
923                         MOD_ACTION_RETURN,      /* invalid  */
924                         MOD_ACTION_RETURN,      /* userlock */
925                         MOD_ACTION_RETURN,      /* notfound */
926                         1,                      /* noop     */
927                         3                       /* updated  */
928                 },
929                 /* redundant */
930                 {
931                         MOD_ACTION_RETURN,      /* reject   */
932                         1,                      /* fail     */
933                         MOD_ACTION_RETURN,      /* ok       */
934                         MOD_ACTION_RETURN,      /* handled  */
935                         MOD_ACTION_RETURN,      /* invalid  */
936                         MOD_ACTION_RETURN,      /* userlock */
937                         MOD_ACTION_RETURN,      /* notfound */
938                         MOD_ACTION_RETURN,      /* noop     */
939                         MOD_ACTION_RETURN       /* updated  */
940                 },
941                 /* append */
942                 {
943                         MOD_ACTION_RETURN,      /* reject   */
944                         1,                      /* fail     */
945                         MOD_ACTION_RETURN,      /* ok       */
946                         MOD_ACTION_RETURN,      /* handled  */
947                         MOD_ACTION_RETURN,      /* invalid  */
948                         MOD_ACTION_RETURN,      /* userlock */
949                         2,                      /* notfound */
950                         MOD_ACTION_RETURN,      /* noop     */
951                         MOD_ACTION_RETURN       /* updated  */
952                 }
953         },
954         /* accounting */
955         {
956                 /* group */
957                 {
958                         MOD_ACTION_RETURN,      /* reject   */
959                         MOD_ACTION_RETURN,      /* fail     */
960                         2,                      /* ok       */
961                         MOD_ACTION_RETURN,      /* handled  */
962                         MOD_ACTION_RETURN,      /* invalid  */
963                         MOD_ACTION_RETURN,      /* userlock */
964                         MOD_ACTION_RETURN,      /* notfound */
965                         1,                      /* noop     */
966                         3                       /* updated  */
967                 },
968                 /* redundant */
969                 {
970                         1,                      /* reject   */
971                         1,                      /* fail     */
972                         MOD_ACTION_RETURN,      /* ok       */
973                         MOD_ACTION_RETURN,      /* handled  */
974                         1,                      /* invalid  */
975                         1,                      /* userlock */
976                         1,                      /* notfound */
977                         2,                      /* noop     */
978                         4                       /* updated  */
979                 },
980                 /* append */
981                 {
982                         MOD_ACTION_RETURN,      /* reject   */
983                         1,                      /* fail     */
984                         MOD_ACTION_RETURN,      /* ok       */
985                         MOD_ACTION_RETURN,      /* handled  */
986                         MOD_ACTION_RETURN,      /* invalid  */
987                         MOD_ACTION_RETURN,      /* userlock */
988                         2,                      /* notfound */
989                         MOD_ACTION_RETURN,      /* noop     */
990                         MOD_ACTION_RETURN       /* updated  */
991                 }
992         },
993         /* checksimul */
994         {
995                 /* group */
996                 {
997                         MOD_ACTION_RETURN,      /* reject   */
998                         1,                      /* fail     */
999                         MOD_ACTION_RETURN,      /* ok       */
1000                         MOD_ACTION_RETURN,      /* handled  */
1001                         MOD_ACTION_RETURN,      /* invalid  */
1002                         MOD_ACTION_RETURN,      /* userlock */
1003                         MOD_ACTION_RETURN,      /* notfound */
1004                         MOD_ACTION_RETURN,      /* noop     */
1005                         MOD_ACTION_RETURN       /* updated  */
1006                 },
1007                 /* redundant */
1008                 {
1009                         MOD_ACTION_RETURN,      /* reject   */
1010                         1,                      /* fail     */
1011                         MOD_ACTION_RETURN,      /* ok       */
1012                         MOD_ACTION_RETURN,      /* handled  */
1013                         MOD_ACTION_RETURN,      /* invalid  */
1014                         MOD_ACTION_RETURN,      /* userlock */
1015                         MOD_ACTION_RETURN,      /* notfound */
1016                         MOD_ACTION_RETURN,      /* noop     */
1017                         MOD_ACTION_RETURN       /* updated  */
1018                 },
1019                 /* append */
1020                 {
1021                         MOD_ACTION_RETURN,      /* reject   */
1022                         1,                      /* fail     */
1023                         MOD_ACTION_RETURN,      /* ok       */
1024                         MOD_ACTION_RETURN,      /* handled  */
1025                         MOD_ACTION_RETURN,      /* invalid  */
1026                         MOD_ACTION_RETURN,      /* userlock */
1027                         MOD_ACTION_RETURN,      /* notfound */
1028                         MOD_ACTION_RETURN,      /* noop     */
1029                         MOD_ACTION_RETURN       /* updated  */
1030                 }
1031         },
1032         /* pre-proxy */
1033         {
1034                 /* group */
1035                 {
1036                         MOD_ACTION_RETURN,      /* reject   */
1037                         MOD_ACTION_RETURN,      /* fail     */
1038                         3,                      /* ok       */
1039                         MOD_ACTION_RETURN,      /* handled  */
1040                         MOD_ACTION_RETURN,      /* invalid  */
1041                         MOD_ACTION_RETURN,      /* userlock */
1042                         1,                      /* notfound */
1043                         2,                      /* noop     */
1044                         4                       /* updated  */
1045                 },
1046                 /* redundant */
1047                 {
1048                         MOD_ACTION_RETURN,      /* reject   */
1049                         1,                      /* fail     */
1050                         MOD_ACTION_RETURN,      /* ok       */
1051                         MOD_ACTION_RETURN,      /* handled  */
1052                         MOD_ACTION_RETURN,      /* invalid  */
1053                         MOD_ACTION_RETURN,      /* userlock */
1054                         MOD_ACTION_RETURN,      /* notfound */
1055                         MOD_ACTION_RETURN,      /* noop     */
1056                         MOD_ACTION_RETURN       /* updated  */
1057                 },
1058                 /* append */
1059                 {
1060                         MOD_ACTION_RETURN,      /* reject   */
1061                         1,                      /* fail     */
1062                         MOD_ACTION_RETURN,      /* ok       */
1063                         MOD_ACTION_RETURN,      /* handled  */
1064                         MOD_ACTION_RETURN,      /* invalid  */
1065                         MOD_ACTION_RETURN,      /* userlock */
1066                         2,                      /* notfound */
1067                         MOD_ACTION_RETURN,      /* noop     */
1068                         MOD_ACTION_RETURN       /* updated  */
1069                 }
1070         },
1071         /* post-proxy */
1072         {
1073                 /* group */
1074                 {
1075                         MOD_ACTION_RETURN,      /* reject   */
1076                         MOD_ACTION_RETURN,      /* fail     */
1077                         3,                      /* ok       */
1078                         MOD_ACTION_RETURN,      /* handled  */
1079                         MOD_ACTION_RETURN,      /* invalid  */
1080                         MOD_ACTION_RETURN,      /* userlock */
1081                         1,                      /* notfound */
1082                         2,                      /* noop     */
1083                         4                       /* updated  */
1084                 },
1085                 /* redundant */
1086                 {
1087                         MOD_ACTION_RETURN,      /* reject   */
1088                         1,                      /* fail     */
1089                         MOD_ACTION_RETURN,      /* ok       */
1090                         MOD_ACTION_RETURN,      /* handled  */
1091                         MOD_ACTION_RETURN,      /* invalid  */
1092                         MOD_ACTION_RETURN,      /* userlock */
1093                         MOD_ACTION_RETURN,      /* notfound */
1094                         MOD_ACTION_RETURN,      /* noop     */
1095                         MOD_ACTION_RETURN       /* updated  */
1096                 },
1097                 /* append */
1098                 {
1099                         MOD_ACTION_RETURN,      /* reject   */
1100                         1,                      /* fail     */
1101                         MOD_ACTION_RETURN,      /* ok       */
1102                         MOD_ACTION_RETURN,      /* handled  */
1103                         MOD_ACTION_RETURN,      /* invalid  */
1104                         MOD_ACTION_RETURN,      /* userlock */
1105                         2,                      /* notfound */
1106                         MOD_ACTION_RETURN,      /* noop     */
1107                         MOD_ACTION_RETURN       /* updated  */
1108                 }
1109         },
1110         /* post-auth */
1111         {
1112                 /* group */
1113                 {
1114                         MOD_ACTION_RETURN,      /* reject   */
1115                         MOD_ACTION_RETURN,      /* fail     */
1116                         3,                      /* ok       */
1117                         MOD_ACTION_RETURN,      /* handled  */
1118                         MOD_ACTION_RETURN,      /* invalid  */
1119                         MOD_ACTION_RETURN,      /* userlock */
1120                         1,                      /* notfound */
1121                         2,                      /* noop     */
1122                         4                       /* updated  */
1123                 },
1124                 /* redundant */
1125                 {
1126                         MOD_ACTION_RETURN,      /* reject   */
1127                         1,                      /* fail     */
1128                         MOD_ACTION_RETURN,      /* ok       */
1129                         MOD_ACTION_RETURN,      /* handled  */
1130                         MOD_ACTION_RETURN,      /* invalid  */
1131                         MOD_ACTION_RETURN,      /* userlock */
1132                         MOD_ACTION_RETURN,      /* notfound */
1133                         MOD_ACTION_RETURN,      /* noop     */
1134                         MOD_ACTION_RETURN       /* updated  */
1135                 },
1136                 /* append */
1137                 {
1138                         MOD_ACTION_RETURN,      /* reject   */
1139                         1,                      /* fail     */
1140                         MOD_ACTION_RETURN,      /* ok       */
1141                         MOD_ACTION_RETURN,      /* handled  */
1142                         MOD_ACTION_RETURN,      /* invalid  */
1143                         MOD_ACTION_RETURN,      /* userlock */
1144                         2,                      /* notfound */
1145                         MOD_ACTION_RETURN,      /* noop     */
1146                         MOD_ACTION_RETURN       /* updated  */
1147                 }
1148         }
1149 };
1150
1151
1152 #ifdef WITH_UNLANG
1153 static modcallable *do_compile_modupdate(modcallable *parent,
1154                                          int component, CONF_SECTION *cs,
1155                                          const char *name2)
1156 {
1157         int i, ok = FALSE;
1158         modgroup *g;
1159         modcallable *csingle;
1160         CONF_ITEM *ci;
1161         VALUE_PAIR *head, **tail;
1162
1163         static const char *attrlist_names[] = {
1164                 "request", "reply", "proxy-request", "proxy-reply",
1165                 "config", "control",
1166                 "outer.request", "outer.reply",
1167                 "outer.config", "outer.control",
1168                 NULL
1169         };
1170
1171         component = component;  /* -Wunused */
1172
1173         if (!cf_section_name2(cs)) {
1174                 cf_log_err(cf_sectiontoitem(cs),
1175                            "Require list name for 'update'.\n");
1176                 return NULL;
1177         }
1178
1179         for (i = 0; attrlist_names[i] != NULL; i++) {
1180                 if (strcmp(name2, attrlist_names[i]) == 0) {
1181                         ok = TRUE;
1182                         break;
1183                 }
1184         }
1185
1186         if (!ok) {
1187                 cf_log_err(cf_sectiontoitem(cs),
1188                            "Unknown attribute list \"%s\"",
1189                            name2);
1190                 return NULL;
1191         }
1192
1193         head = NULL;
1194         tail = &head;
1195
1196         /*
1197          *      Walk through the children of the update section,
1198          *      ensuring that they're all known attributes.
1199          */
1200         for (ci=cf_item_find_next(cs, NULL);
1201              ci != NULL;
1202              ci=cf_item_find_next(cs, ci)) {
1203                 CONF_PAIR *cp;
1204                 VALUE_PAIR *vp;
1205
1206                 if (cf_item_is_section(ci)) {
1207                         cf_log_err(ci, "\"update\" sections cannot have subsections");
1208                         return NULL;
1209                 }
1210
1211                 if (!cf_item_is_pair(ci)) continue;
1212
1213                 cp = cf_itemtopair(ci); /* can't return NULL */
1214                 vp = cf_pairtovp(cp);
1215                 if (!vp) {
1216                         pairfree(&head);
1217                         cf_log_err(ci, "ERROR: %s", librad_errstr);
1218                         return NULL;
1219                 }
1220
1221                 if ((vp->operator != T_OP_EQ) &&
1222                     (vp->operator != T_OP_CMP_EQ) &&
1223                     (vp->operator != T_OP_ADD) &&
1224                     (vp->operator != T_OP_SUB) &&
1225                     (vp->operator != T_OP_LE) &&
1226                     (vp->operator != T_OP_GE) &&
1227                     (vp->operator != T_OP_SET)) {
1228                         pairfree(&head);
1229                         pairfree(&vp);
1230                         cf_log_err(ci, "Invalid operator for attribute");
1231                         return NULL;
1232                 }
1233
1234                 /*
1235                  *      A few more sanity checks.  The enforcement of
1236                  *      <= or >= can only happen for integer
1237                  *      attributes.
1238                  */
1239                 if ((vp->operator == T_OP_LE) ||
1240                     (vp->operator == T_OP_GE)) {
1241                         if ((vp->type != PW_TYPE_BYTE) &&
1242                             (vp->type != PW_TYPE_SHORT) &&
1243                             (vp->type != PW_TYPE_INTEGER)) {
1244                                 pairfree(&head);
1245                                 pairfree(&vp);
1246                                 cf_log_err(ci, "Enforcment of <= or >= is possible only for integer attributes");
1247                                 return NULL;
1248                         }
1249                 }
1250
1251                 *tail = vp;
1252                 tail = &(vp->next);
1253         }
1254
1255         if (!head) {
1256                 cf_log_err(cf_sectiontoitem(cs),
1257                            "ERROR: update %s section cannot be empty",
1258                            name2);
1259                 return NULL;
1260         }
1261
1262         g = rad_malloc(sizeof(*g)); /* never fails */
1263         memset(g, 0, sizeof(*g));
1264         csingle = mod_grouptocallable(g);
1265         
1266         csingle->parent = parent;
1267         csingle->next = NULL;
1268         csingle->name = name2;
1269         csingle->type = MOD_UPDATE;
1270         csingle->method = component;
1271         
1272         g->grouptype = GROUPTYPE_SIMPLE;
1273         g->children = NULL;
1274         g->cs = cs;
1275         g->vps = head;
1276
1277         return csingle;
1278 }
1279
1280
1281 static modcallable *do_compile_modswitch(modcallable *parent,
1282                                          int component, CONF_SECTION *cs)
1283 {
1284         modcallable *csingle;
1285         CONF_ITEM *ci;
1286         int had_seen_default = FALSE;
1287
1288         component = component;  /* -Wunused */
1289
1290         if (!cf_section_name2(cs)) {
1291                 cf_log_err(cf_sectiontoitem(cs),
1292                            "You must specify a variable to switch over for 'switch'.");
1293                 return NULL;
1294         }
1295
1296         if (!cf_item_find_next(cs, NULL)) {
1297                 cf_log_err(cf_sectiontoitem(cs), "'switch' statments cannot be empty.");
1298                 return NULL;
1299         }
1300
1301         /*
1302          *      Walk through the children of the switch section,
1303          *      ensuring that they're all 'case' statements
1304          */
1305         for (ci=cf_item_find_next(cs, NULL);
1306              ci != NULL;
1307              ci=cf_item_find_next(cs, ci)) {
1308                 CONF_SECTION *subcs;
1309                 const char *name1, *name2;
1310
1311                 if (!cf_item_is_section(ci)) {
1312                         if (!cf_item_is_pair(ci)) continue;
1313
1314                         cf_log_err(ci, "\"switch\" sections can only have \"case\" subsections");
1315                         return NULL;
1316                 }
1317
1318                 subcs = cf_itemtosection(ci);   /* can't return NULL */
1319                 name1 = cf_section_name1(subcs);
1320
1321                 if (strcmp(name1, "case") != 0) {
1322                         cf_log_err(ci, "\"switch\" sections can only have \"case\" subsections");
1323                         return NULL;
1324                 }
1325
1326                 name2 = cf_section_name2(subcs);
1327                 if (!name2 && !had_seen_default) {
1328                         had_seen_default = TRUE;
1329                         continue;
1330                 }
1331
1332                 if (!name2 || (name2[0] == '\0')) {
1333                         cf_log_err(ci, "\"case\" sections must have a name");
1334                         return NULL;
1335                 }
1336         }
1337
1338         csingle= do_compile_modgroup(parent, component, cs,
1339                                      GROUPTYPE_SIMPLE, GROUPTYPE_SIMPLE);
1340         if (!csingle) return NULL;
1341         csingle->type = MOD_SWITCH;
1342         return csingle;
1343 }
1344 #endif
1345
1346 static modcallable *do_compile_modserver(modcallable *parent,
1347                                          int component, CONF_ITEM *ci,
1348                                          const char *name,
1349                                          CONF_SECTION *cs,
1350                                          const char *server)
1351 {
1352         modcallable *csingle;
1353         CONF_SECTION *subcs;
1354         modref *mr;
1355
1356         subcs = cf_section_sub_find_name2(cs, comp2str[component], NULL);
1357         if (!subcs) {
1358                 cf_log_err(ci, "Server %s has no %s section",
1359                            server, comp2str[component]);
1360                 return NULL;
1361         }
1362
1363         mr = rad_malloc(sizeof(*mr));
1364         memset(mr, 0, sizeof(*mr));
1365
1366         csingle = mod_reftocallable(mr);
1367         csingle->parent = parent;
1368         csingle->next = NULL;
1369         csingle->name = name;
1370         csingle->type = MOD_REFERENCE;
1371         csingle->method = component;
1372
1373         memcpy(csingle->actions, defaultactions[component][GROUPTYPE_SIMPLE],
1374                sizeof(csingle->actions));
1375         
1376         mr->ref_name = strdup(server);
1377         mr->ref_cs = cs;
1378
1379         return csingle;
1380 }
1381
1382 static modcallable *do_compile_modxlat(modcallable *parent,
1383                                        int component, const char *fmt)
1384 {
1385         modcallable *csingle;
1386         modxlat *mx;
1387
1388         mx = rad_malloc(sizeof(*mx));
1389         memset(mx, 0, sizeof(*mx));
1390
1391         csingle = mod_xlattocallable(mx);
1392         csingle->parent = parent;
1393         csingle->next = NULL;
1394         csingle->name = "expand";
1395         csingle->type = MOD_XLAT;
1396         csingle->method = component;
1397
1398         memcpy(csingle->actions, defaultactions[component][GROUPTYPE_SIMPLE],
1399                sizeof(csingle->actions));
1400         
1401         mx->xlat_name = strdup(fmt);
1402
1403         return csingle;
1404 }
1405
1406 /*
1407  *      redundant, etc. can refer to modules or groups, but not much else.
1408  */
1409 static int all_children_are_modules(CONF_SECTION *cs, const char *name)
1410 {
1411         CONF_ITEM *ci;
1412
1413         for (ci=cf_item_find_next(cs, NULL);
1414              ci != NULL;
1415              ci=cf_item_find_next(cs, ci)) {
1416                 /*
1417                  *      If we're a redundant, etc. group, then the
1418                  *      intention is to call modules, rather than
1419                  *      processing logic.  These checks aren't
1420                  *      *strictly* necessary, but they keep the users
1421                  *      from doing crazy things.
1422                  */
1423                 if (cf_item_is_section(ci)) {
1424                         CONF_SECTION *subcs = cf_itemtosection(ci);
1425                         const char *name1 = cf_section_name1(subcs);
1426
1427                         if ((strcmp(name1, "if") == 0) ||
1428                             (strcmp(name1, "else") == 0) ||
1429                             (strcmp(name1, "elsif") == 0) ||
1430                             (strcmp(name1, "update") == 0) ||
1431                             (strcmp(name1, "switch") == 0) ||
1432                             (strcmp(name1, "case") == 0)) {
1433                                 cf_log_err(ci, "%s sections cannot contain a \"%s\" statement",
1434                                        name, name1);
1435                                 return 0;
1436                         }
1437                         continue;
1438                 }
1439
1440                 if (cf_item_is_pair(ci)) {
1441                         CONF_PAIR *cp = cf_itemtopair(ci);
1442                         if (cf_pair_value(cp) != NULL) {
1443                                 cf_log_err(ci,
1444                                            "Entry with no value is invalid");
1445                                 return 0;
1446                         }
1447                 }
1448         }
1449
1450         return 1;
1451 }
1452
1453
1454 /*
1455  *      Compile one entry of a module call.
1456  */
1457 static modcallable *do_compile_modsingle(modcallable *parent,
1458                                          int component, CONF_ITEM *ci,
1459                                          int grouptype,
1460                                          const char **modname)
1461 {
1462 #ifdef WITH_UNLANG
1463         int result;
1464 #endif
1465         const char *modrefname;
1466         modsingle *single;
1467         modcallable *csingle;
1468         module_instance_t *this;
1469         CONF_SECTION *cs, *subcs, *modules;
1470
1471         if (cf_item_is_section(ci)) {
1472                 const char *name2;
1473
1474                 cs = cf_itemtosection(ci);
1475                 modrefname = cf_section_name1(cs);
1476                 name2 = cf_section_name2(cs);
1477                 if (!name2) name2 = "_UnNamedGroup";
1478
1479                 /*
1480                  *      group{}, redundant{}, or append{} may appear
1481                  *      where a single module instance was expected.
1482                  *      In that case, we hand it off to
1483                  *      compile_modgroup
1484                  */
1485                 if (strcmp(modrefname, "group") == 0) {
1486                         *modname = name2;
1487                         return do_compile_modgroup(parent, component, cs,
1488                                                    GROUPTYPE_SIMPLE,
1489                                                    grouptype);
1490
1491                 } else if (strcmp(modrefname, "redundant") == 0) {
1492                         *modname = name2;
1493
1494                         if (!all_children_are_modules(cs, modrefname)) {
1495                                 return NULL;
1496                         }
1497
1498                         return do_compile_modgroup(parent, component, cs,
1499                                                    GROUPTYPE_REDUNDANT,
1500                                                    grouptype);
1501
1502                 } else if (strcmp(modrefname, "append") == 0) {
1503                         *modname = name2;
1504                         return do_compile_modgroup(parent, component, cs,
1505                                                    GROUPTYPE_APPEND,
1506                                                    grouptype);
1507
1508                 } else if (strcmp(modrefname, "load-balance") == 0) {
1509                         *modname = name2;
1510
1511                         if (!all_children_are_modules(cs, modrefname)) {
1512                                 return NULL;
1513                         }
1514
1515                         csingle= do_compile_modgroup(parent, component, cs,
1516                                                      GROUPTYPE_SIMPLE,
1517                                                      grouptype);
1518                         if (!csingle) return NULL;
1519                         csingle->type = MOD_LOAD_BALANCE;
1520                         return csingle;
1521
1522                 } else if (strcmp(modrefname, "redundant-load-balance") == 0) {
1523                         *modname = name2;
1524
1525                         if (!all_children_are_modules(cs, modrefname)) {
1526                                 return NULL;
1527                         }
1528
1529                         csingle= do_compile_modgroup(parent, component, cs,
1530                                                      GROUPTYPE_REDUNDANT,
1531                                                      grouptype);
1532                         if (!csingle) return NULL;
1533                         csingle->type = MOD_REDUNDANT_LOAD_BALANCE;
1534                         return csingle;
1535
1536 #ifdef WITH_UNLANG
1537                 } else  if (strcmp(modrefname, "if") == 0) {
1538                         if (!cf_section_name2(cs)) {
1539                                 cf_log_err(ci, "'if' without condition.");
1540                                 return NULL;
1541                         }
1542
1543                         *modname = name2;
1544                         csingle= do_compile_modgroup(parent, component, cs,
1545                                                      GROUPTYPE_SIMPLE,
1546                                                      grouptype);
1547                         if (!csingle) return NULL;
1548                         csingle->type = MOD_IF;
1549
1550                         if (!radius_evaluate_condition(NULL, 0, 0, modname,
1551                                                        FALSE, &result)) {
1552                                 modcallable_free(&csingle);
1553                                 return NULL;
1554                         }
1555                         *modname = name2;
1556
1557                         return csingle;
1558
1559                 } else  if (strcmp(modrefname, "elsif") == 0) {
1560                         if (parent &&
1561                             ((parent->type == MOD_LOAD_BALANCE) ||
1562                              (parent->type == MOD_REDUNDANT_LOAD_BALANCE))) {
1563                                 cf_log_err(ci, "'elsif' cannot be used in this section section.");
1564                                 return NULL;
1565                         }
1566
1567                         if (!cf_section_name2(cs)) {
1568                                 cf_log_err(ci, "'elsif' without condition.");
1569                                 return NULL;
1570                         }
1571
1572                         *modname = name2;
1573                         csingle= do_compile_modgroup(parent, component, cs,
1574                                                      GROUPTYPE_SIMPLE,
1575                                                      grouptype);
1576                         if (!csingle) return NULL;
1577                         csingle->type = MOD_ELSIF;
1578
1579                         if (!radius_evaluate_condition(NULL, 0, 0, modname,
1580                                                        FALSE, &result)) {
1581                                 modcallable_free(&csingle);
1582                                 return NULL;
1583                         }
1584                         *modname = name2;
1585
1586                         return csingle;
1587
1588                 } else  if (strcmp(modrefname, "else") == 0) {
1589                         if (parent &&
1590                             ((parent->type == MOD_LOAD_BALANCE) ||
1591                              (parent->type == MOD_REDUNDANT_LOAD_BALANCE))) {
1592                                 cf_log_err(ci, "'else' cannot be used in this section section.");
1593                                 return NULL;
1594                         }
1595
1596                         if (cf_section_name2(cs)) {
1597                                 cf_log_err(ci, "Cannot have conditions on 'else'.");
1598                                 return NULL;
1599                         }
1600
1601                         *modname = name2;
1602                         csingle= do_compile_modgroup(parent, component, cs,
1603                                                      GROUPTYPE_SIMPLE,
1604                                                      grouptype);
1605                         if (!csingle) return NULL;
1606                         csingle->type = MOD_ELSE;
1607                         return csingle;
1608
1609                 } else  if (strcmp(modrefname, "update") == 0) {
1610                         *modname = name2;
1611
1612                         csingle = do_compile_modupdate(parent, component, cs,
1613                                                        name2);
1614                         if (!csingle) return NULL;
1615
1616                         return csingle;
1617
1618                 } else  if (strcmp(modrefname, "switch") == 0) {
1619                         *modname = name2;
1620
1621                         csingle = do_compile_modswitch(parent, component, cs);
1622                         if (!csingle) return NULL;
1623
1624                         return csingle;
1625
1626                 } else  if (strcmp(modrefname, "case") == 0) {
1627                         int i;
1628
1629                         *modname = name2;
1630
1631                         /*
1632                          *      FIXME: How to tell that the parent can only
1633                          *      be a "switch" statement?
1634                          */
1635                         if (!parent) {
1636                                 cf_log_err(ci, "\"case\" statements may only appear within a \"switch\" section");
1637                                 return NULL;
1638                         }
1639
1640                         csingle= do_compile_modgroup(parent, component, cs,
1641                                                      GROUPTYPE_SIMPLE,
1642                                                      grouptype);
1643                         if (!csingle) return NULL;
1644                         csingle->type = MOD_CASE;
1645                         csingle->name = cf_section_name2(cs); /* may be NULL */
1646
1647                         /*
1648                          *      Set all of it's codes to return, so that
1649                          *      when we pick a 'case' statement, we don't
1650                          *      fall through to processing the next one.
1651                          */
1652                         for (i = 0; i < RLM_MODULE_NUMCODES; i++) {
1653                                 csingle->actions[i] = MOD_ACTION_RETURN;
1654                         }
1655
1656                         return csingle;
1657 #endif
1658                 } /* else it's something like sql { fail = 1 ...} */
1659
1660         } else if (!cf_item_is_pair(ci)) { /* CONF_DATA or some such */
1661                 return NULL;
1662
1663                 /*
1664                  *      Else it's a module reference, with updated return
1665                  *      codes.
1666                  */
1667         } else {
1668                 CONF_PAIR *cp = cf_itemtopair(ci);
1669                 modrefname = cf_pair_attr(cp);
1670
1671                 /*
1672                  *      Actions (ok = 1), etc. are orthoganal to just
1673                  *      about everything else.
1674                  */
1675                 if (cf_pair_value(cp) != NULL) {
1676                         cf_log_err(ci, "Entry is not a reference to a module");
1677                         return NULL;
1678                 }
1679
1680                 if ((modrefname[0] == '%') && (modrefname[1] == '{')) {
1681                         return do_compile_modxlat(parent, component,
1682                                                   modrefname);
1683                 }
1684
1685                 /*
1686                  *      See if the module is a virtual one.  If so,
1687                  *      return that, rather than doing anything here.
1688                  */
1689                 subcs = NULL;
1690                 cs = cf_section_find("instantiate");
1691                 if (!subcs) {
1692                         cs = cf_section_find("policy");
1693                         if (cs) subcs = cf_section_sub_find_name2(cs, NULL,
1694                                                                   modrefname);
1695                 }
1696                 if (subcs) {
1697                         DEBUG2(" Module: Loading virtual module %s",
1698                                modrefname);
1699
1700                         /*
1701                          *      redundant foo {} is a single.
1702                          */
1703                         if (cf_section_name2(subcs)) {
1704                                 return do_compile_modsingle(parent,
1705                                                             component,
1706                                                             cf_sectiontoitem(subcs),
1707                                                             grouptype,
1708                                                             modname);
1709                         } else {
1710                                 /*
1711                                  *      foo {} is a group.
1712                                  */
1713                                 return do_compile_modgroup(parent,
1714                                                            component,
1715                                                            subcs,
1716                                                            GROUPTYPE_SIMPLE,
1717                                                            grouptype);
1718                         }
1719                 }
1720         }
1721
1722         /*
1723          *      Not a virtual module.  It must be a real module.
1724          */
1725         modules = cf_section_find("modules");
1726         this = NULL;
1727
1728         if (modules && cf_section_sub_find_name2(modules, NULL, modrefname)) {
1729                 this = find_module_instance(modules, modrefname);
1730         }
1731
1732         if (!this) do {
1733                 int i;
1734                 char *p;
1735           
1736                 /*
1737                  *      Maybe it's module.method
1738                  */
1739                 p = strrchr(modrefname, '.');
1740                 if (p) for (i = RLM_COMPONENT_AUTH;
1741                             i < RLM_COMPONENT_COUNT;
1742                             i++) {
1743                         if (strcmp(p + 1, comp2str[i]) == 0) {
1744                                 char buffer[256];
1745
1746                                 strlcpy(buffer, modrefname, sizeof(buffer));
1747                                 buffer[p - modrefname] = '\0';
1748                                 component = i;
1749                                 
1750                                 this = find_module_instance(cf_section_find("modules"), buffer);
1751                                 if (this &&
1752                                     !this->entry->module->methods[i]) {
1753                                         *modname = NULL;
1754                                         cf_log_err(ci, "Module %s has no such method %s", buffer, comp2str[i]);
1755                                         return NULL;
1756                                 }
1757                                 break;
1758                         }
1759                 }
1760                 if (this) break;
1761
1762                 if (strncmp(modrefname, "server[", 7) == 0) {
1763                         char buffer[256];
1764
1765                         strlcpy(buffer, modrefname + 7, sizeof(buffer));
1766                         p = strrchr(buffer, ']');
1767                         if (!p || p[1] != '\0' || (p == buffer)) {
1768                                 cf_log_err(ci, "Invalid server reference in \"%s\".", modrefname);
1769                                 return NULL;
1770                         }
1771                         *p = '\0';
1772
1773                         cs = cf_section_sub_find_name2(NULL, "server", buffer);
1774                         if (!cs) {
1775                                 cf_log_err(ci, "No such server \"%s\".", buffer);
1776                                 return NULL;
1777                         }
1778                         
1779                         return do_compile_modserver(parent, component, ci,
1780                                                     modrefname, cs, buffer);
1781                 }
1782                 
1783                 *modname = NULL;
1784                 cf_log_err(ci, "Failed to find module \"%s\".", modrefname);
1785                 return NULL;
1786         } while (0);
1787
1788         /*
1789          *      We know it's all OK, allocate the structures, and fill
1790          *      them in.
1791          */
1792         single = rad_malloc(sizeof(*single));
1793         memset(single, 0, sizeof(*single));
1794         csingle = mod_singletocallable(single);
1795         csingle->parent = parent;
1796         csingle->next = NULL;
1797         if (!parent || (component != RLM_COMPONENT_AUTH)) {
1798                 memcpy(csingle->actions, defaultactions[component][grouptype],
1799                        sizeof csingle->actions);
1800         } else { /* inside Auth-Type has different rules */
1801                 memcpy(csingle->actions, defaultactions[RLM_COMPONENT_AUTZ][grouptype],
1802                        sizeof csingle->actions);
1803         }
1804         rad_assert(modrefname != NULL);
1805         csingle->name = modrefname;
1806         csingle->type = MOD_SINGLE;
1807         csingle->method = component;
1808
1809         /*
1810          *      Singles can override the actions, virtual modules cannot.
1811          *
1812          *      FIXME: We may want to re-visit how to do this...
1813          *      maybe a csingle as a ref?
1814          */
1815         if (cf_item_is_section(ci)) {
1816                 cs = cf_itemtosection(ci);
1817
1818                 for (ci=cf_item_find_next(cs, NULL);
1819                      ci != NULL;
1820                      ci=cf_item_find_next(cs, ci)) {
1821
1822                         if (cf_item_is_section(ci)) {
1823                                 cf_log_err(ci, "Subsection of module instance call not allowed");
1824                                 modcallable_free(&csingle);
1825                                 return NULL;
1826                         }
1827
1828                         if (!cf_item_is_pair(ci)) continue;
1829
1830                         if (!compile_action(csingle, cf_itemtopair(ci))) {
1831                                 modcallable_free(&csingle);
1832                                 return NULL;
1833                         }
1834                 }
1835         }
1836
1837         /*
1838          *      Bail out if the module in question does not supply the
1839          *      wanted component
1840          */
1841         if (!this->entry->module->methods[component]) {
1842                 cf_log_err(ci, "\"%s\" modules aren't allowed in '%s' sections -- they have no such method.", this->entry->module->name,
1843                        comp2str[component]);
1844                 modcallable_free(&csingle);
1845                 return NULL;
1846         }
1847
1848         single->modinst = this;
1849         *modname = this->entry->module->name;
1850         return csingle;
1851 }
1852
1853 modcallable *compile_modsingle(modcallable *parent,
1854                                int component, CONF_ITEM *ci,
1855                                const char **modname)
1856 {
1857         modcallable *ret = do_compile_modsingle(parent, component, ci,
1858                                                 GROUPTYPE_SIMPLE,
1859                                                 modname);
1860         dump_tree(component, ret);
1861         return ret;
1862 }
1863
1864
1865 /*
1866  *      Internal compile group code.
1867  */
1868 static modcallable *do_compile_modgroup(modcallable *parent,
1869                                         int component, CONF_SECTION *cs,
1870                                         int grouptype, int parentgrouptype)
1871 {
1872         int i;
1873         modgroup *g;
1874         modcallable *c;
1875         CONF_ITEM *ci;
1876
1877         g = rad_malloc(sizeof(*g));
1878         memset(g, 0, sizeof(*g));
1879         g->grouptype = grouptype;
1880
1881         c = mod_grouptocallable(g);
1882         c->parent = parent;
1883         c->type = MOD_GROUP;
1884         c->next = NULL;
1885         memset(c->actions, 0, sizeof(c->actions));
1886
1887         /*
1888          *      Remember the name for printing, etc.
1889          *
1890          *      FIXME: We may also want to put the names into a
1891          *      rbtree, so that groups can reference each other...
1892          */
1893         c->name = cf_section_name2(cs);
1894         if (!c->name) {
1895                 c->name = cf_section_name1(cs);
1896                 if (strcmp(c->name, "group") == 0) {
1897                         c->name = "";
1898                 } else {
1899                         c->type = MOD_POLICY;
1900                 }
1901         }
1902         g->children = NULL;
1903
1904         /*
1905          *      Loop over the children of this group.
1906          */
1907         for (ci=cf_item_find_next(cs, NULL);
1908              ci != NULL;
1909              ci=cf_item_find_next(cs, ci)) {
1910
1911                 /*
1912                  *      Sections are references to other groups, or
1913                  *      to modules with updated return codes.
1914                  */
1915                 if (cf_item_is_section(ci)) {
1916                         const char *junk = NULL;
1917                         modcallable *single;
1918                         CONF_SECTION *subcs = cf_itemtosection(ci);
1919
1920                         single = do_compile_modsingle(c, component, ci,
1921                                                       grouptype, &junk);
1922                         if (!single) {
1923                                 cf_log_err(ci, "Failed to parse \"%s\" subsection.",
1924                                        cf_section_name1(subcs));
1925                                 modcallable_free(&c);
1926                                 return NULL;
1927                         }
1928                         add_child(g, single);
1929
1930                 } else if (!cf_item_is_pair(ci)) { /* CONF_DATA */
1931                         continue;
1932
1933                 } else {
1934                         const char *attr, *value;
1935                         CONF_PAIR *cp = cf_itemtopair(ci);
1936
1937                         attr = cf_pair_attr(cp);
1938                         value = cf_pair_value(cp);
1939
1940                         /*
1941                          *      A CONF_PAIR is either a module
1942                          *      instance with no actions
1943                          *      specified ...
1944                          */
1945                         if (!value) {
1946                                 modcallable *single;
1947                                 const char *junk = NULL;
1948
1949                                 single = do_compile_modsingle(c,
1950                                                               component,
1951                                                               ci,
1952                                                               grouptype,
1953                                                               &junk);
1954                                 if (!single) {
1955                                         cf_log_err(ci,
1956                                                    "Failed to parse \"%s\" entry.",
1957                                                    attr);
1958                                         modcallable_free(&c);
1959                                         return NULL;
1960                                 }
1961                                 add_child(g, single);
1962
1963                                 /*
1964                                  *      Or a module instance with action.
1965                                  */
1966                         } else if (!compile_action(c, cp)) {
1967                                 modcallable_free(&c);
1968                                 return NULL;
1969                         } /* else it worked */
1970                 }
1971         }
1972
1973         /*
1974          *      Set the default actions, if they haven't already been
1975          *      set.
1976          */
1977         for (i = 0; i < RLM_MODULE_NUMCODES; i++) {
1978                 if (!c->actions[i]) {
1979                         if (!parent || (component != RLM_COMPONENT_AUTH)) {
1980                                 c->actions[i] = defaultactions[component][parentgrouptype][i];
1981                         } else { /* inside Auth-Type has different rules */
1982                                 c->actions[i] = defaultactions[RLM_COMPONENT_AUTZ][parentgrouptype][i];
1983                         }
1984                 }
1985         }
1986
1987         /*
1988          *      FIXME: If there are no children, return NULL?
1989          */
1990         return mod_grouptocallable(g);
1991 }
1992
1993 modcallable *compile_modgroup(modcallable *parent,
1994                               int component, CONF_SECTION *cs)
1995 {
1996         modcallable *ret = do_compile_modgroup(parent, component, cs,
1997                                                GROUPTYPE_SIMPLE,
1998                                                GROUPTYPE_SIMPLE);
1999         dump_tree(component, ret);
2000         return ret;
2001 }
2002
2003 void add_to_modcallable(modcallable **parent, modcallable *this,
2004                         int component, const char *name)
2005 {
2006         modgroup *g;
2007
2008         rad_assert(this != NULL);
2009
2010         if (*parent == NULL) {
2011                 modcallable *c;
2012
2013                 g = rad_malloc(sizeof *g);
2014                 memset(g, 0, sizeof(*g));
2015                 g->grouptype = GROUPTYPE_SIMPLE;
2016                 c = mod_grouptocallable(g);
2017                 c->next = NULL;
2018                 memcpy(c->actions,
2019                        defaultactions[component][GROUPTYPE_SIMPLE],
2020                        sizeof(c->actions));
2021                 rad_assert(name != NULL);
2022                 c->name = name;
2023                 c->type = MOD_GROUP;
2024                 c->method = component;
2025                 g->children = NULL;
2026
2027                 *parent = mod_grouptocallable(g);
2028         } else {
2029                 g = mod_callabletogroup(*parent);
2030         }
2031
2032         add_child(g, this);
2033 }
2034
2035 void modcallable_free(modcallable **pc)
2036 {
2037         modcallable *c, *loop, *next;
2038         c = *pc;
2039         if (c->type != MOD_SINGLE) {
2040                 modgroup *g = mod_callabletogroup(c);
2041
2042                 for(loop = g->children;
2043                     loop ;
2044                     loop = next) {
2045                         next = loop->next;
2046                         modcallable_free(&loop);
2047                 }
2048                 pairfree(&g->vps);
2049         }
2050         free(c);
2051         *pc = NULL;
2052 }