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.
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.
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
20 * Copyright 2000,2006 The FreeRADIUS server project
23 #include <freeradius-devel/ident.h>
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>
32 /* mutually-recursive static functions need a prototype up front */
33 static modcallable *do_compile_modgroup(modcallable *,
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)
45 /* Here are our basic types: modcallable, modgroup, and modsingle. For an
46 * explanation of what they are all about, see ../../doc/README.failover */
49 struct modcallable *next;
51 enum { MOD_SINGLE = 1, MOD_GROUP, MOD_LOAD_BALANCE, MOD_REDUNDANT_LOAD_BALANCE,
53 MOD_IF, MOD_ELSE, MOD_ELSIF, MOD_UPDATE, MOD_SWITCH, MOD_CASE,
55 MOD_POLICY, MOD_REFERENCE, MOD_XLAT } type;
57 int actions[RLM_MODULE_NUMCODES];
60 #define GROUPTYPE_SIMPLE 0
61 #define GROUPTYPE_REDUNDANT 1
62 #define GROUPTYPE_APPEND 2
63 #define GROUPTYPE_COUNT 3
66 modcallable mc; /* self */
67 int grouptype; /* after mc */
68 modcallable *children;
75 module_instance_t *modinst;
86 const char *xlat_name;
89 static const FR_NAME_NUMBER grouptype_table[] = {
90 { "", GROUPTYPE_SIMPLE },
91 { "redundant ", GROUPTYPE_REDUNDANT },
92 { "append ", GROUPTYPE_APPEND },
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)
100 rad_assert(p->type==MOD_SINGLE);
101 return (modsingle *)p;
103 static modgroup *mod_callabletogroup(modcallable *p)
105 rad_assert((p->type > MOD_SINGLE) && (p->type <= MOD_POLICY));
107 return (modgroup *)p;
109 static modcallable *mod_singletocallable(modsingle *p)
111 return (modcallable *)p;
113 static modcallable *mod_grouptocallable(modgroup *p)
115 return (modcallable *)p;
118 static modref *mod_callabletoref(modcallable *p)
120 rad_assert(p->type==MOD_REFERENCE);
123 static modcallable *mod_reftocallable(modref *p)
125 return (modcallable *)p;
128 static modxlat *mod_callabletoxlat(modcallable *p)
130 rad_assert(p->type==MOD_XLAT);
133 static modcallable *mod_xlattocallable(modxlat *p)
135 return (modcallable *)p;
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)
142 modcallable **head = &g->children;
143 modcallable *node = *head;
144 modcallable **last = head;
153 rad_assert(c->next == NULL);
155 c->parent = mod_grouptocallable(g);
158 /* Here's where we recognize all of our keywords: first the rcodes, then the
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 },
175 * Compile action && rcode for later use.
177 static int compile_action(modcallable *c, CONF_PAIR *cp)
180 const char *attr, *value;
182 attr = cf_pair_attr(cp);
183 value = cf_pair_value(cp);
184 if (!value) return 0;
186 if (!strcasecmp(value, "return"))
187 action = MOD_ACTION_RETURN;
189 else if (!strcasecmp(value, "break"))
190 action = MOD_ACTION_RETURN;
192 else if (!strcasecmp(value, "reject"))
193 action = MOD_ACTION_REJECT;
195 else if (strspn(value, "0123456789")==strlen(value)) {
196 action = atoi(value);
199 * Don't allow priority zero, for future use.
201 if (action == 0) return 0;
203 cf_log_err(cf_pairtoitem(cp), "Unknown action '%s'.\n",
208 if (strcasecmp(attr, "default") != 0) {
211 rcode = fr_str2int(rcode_table, attr, -1);
213 cf_log_err(cf_pairtoitem(cp),
214 "Unknown module rcode '%s'.\n",
218 c->actions[rcode] = action;
220 } else { /* set all unset values to the default */
223 for (i = 0; i < RLM_MODULE_NUMCODES; i++) {
224 if (!c->actions[i]) c->actions[i] = action;
231 /* Some short names for debugging output */
232 static const char * const comp2str[] = {
243 #ifdef HAVE_PTHREAD_H
245 * Lock the mutex for the module
247 static void safe_lock(module_instance_t *instance)
250 pthread_mutex_lock(instance->mutex);
254 * Unlock the mutex for the module
256 static void safe_unlock(module_instance_t *instance)
259 pthread_mutex_unlock(instance->mutex);
263 * No threads: these functions become NULL's.
265 #define safe_lock(foo)
266 #define safe_unlock(foo)
269 static int call_modsingle(int component, modsingle *sp, REQUEST *request,
272 int myresult = default_result;
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);
280 * For logging unresponsive children.
282 request->module = sp->modinst->name;
284 myresult = sp->modinst->entry->module->methods[component](
285 sp->modinst->insthandle, request);
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);
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 */
309 static const char *group_name[] = {
313 "load-balance group",
314 "redundant-load-balance group",
326 static const char *modcall_spaces = "++++++++++++++++++++++++++++++++";
328 #define MODCALL_STACK_MAX (32)
331 * Don't call the modules recursively. Instead, do them
332 * iteratively, and manage the call stack ourselves.
334 typedef struct modcall_stack {
337 int priority[MODCALL_STACK_MAX];
338 int result[MODCALL_STACK_MAX];
339 modcallable *children[MODCALL_STACK_MAX];
340 modcallable *start[MODCALL_STACK_MAX];
345 * Call a module, iteratively, with a local stack, rather than
346 * recursively. What did Paul Graham say about Lisp...?
348 int modcall(int component, modcallable *c, REQUEST *request)
352 modcallable *parent, *child;
354 int if_taken, was_if;
356 if ((component < 0) || (component >= RLM_COMPONENT_COUNT)) {
357 return RLM_MODULE_FAIL;
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;
368 * A module has taken too long to process the request,
369 * and we've been told to stop processing it.
371 if ((request->master_state == REQUEST_STOP_PROCESSING) ||
373 (request->parent->master_state == REQUEST_STOP_PROCESSING))) {
374 myresult = RLM_MODULE_FAIL;
378 child = stack.children[stack.pointer];
380 myresult = stack.result[stack.pointer];
383 parent = child->parent;
386 if ((child->type == MOD_ELSE) || (child->type == MOD_ELSIF)) {
387 myresult = stack.result[stack.pointer];
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],
397 RDEBUG2("%.*s ... skipping %s for request %d: Preceding \"if\" was taken",
398 stack.pointer + 1, modcall_spaces,
399 group_name[child->type],
406 * "if" or "elsif". Evaluate the condition.
408 if ((child->type == MOD_IF) || (child->type == MOD_ELSIF)) {
409 int condition = TRUE;
410 const char *p = child->name;
412 RDEBUG2("%.*s? %s %s",
413 stack.pointer + 1, modcall_spaces,
414 (child->type == MOD_IF) ? "if" : "elsif",
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");
425 * This should never happen, the
426 * condition is checked when the
427 * module section is loaded.
433 stack.result[stack.pointer] = myresult;
434 stack.children[stack.pointer] = NULL;
438 } /* else process it as a simple group */
441 if (child->type == MOD_UPDATE) {
443 modgroup *g = mod_callabletogroup(child);
445 rcode = radius_update_attrlist(request, g->cs,
446 g->vps, child->name);
447 if (rcode != RLM_MODULE_UPDATED) {
454 if (child->type == MOD_REFERENCE) {
455 modref *mr = mod_callabletoref(child);
456 const char *server = request->server;
458 if (server == mr->ref_name) {
459 RDEBUG("WARNING: Suppressing recursive call to server %s", server);
460 myresult = RLM_MODULE_NOOP;
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;
472 if (child->type == MOD_XLAT) {
473 modxlat *mx = mod_callabletoxlat(child);
476 radius_xlat(buffer, sizeof(buffer), mx->xlat_name,
482 * Child is a group that has children of it's own.
484 if (child->type != MOD_SINGLE) {
488 modcallable *null_case;
490 modgroup *g = mod_callabletogroup(child);
495 * Catastrophic error. This SHOULD have
496 * been caught when we were reading in the
501 if (stack.pointer >= MODCALL_STACK_MAX) {
502 radlog(L_ERR, "Internal sanity check failed: module stack is too deep");
506 stack.priority[stack.pointer] = 0;
507 stack.result[stack.pointer] = default_component_results[component];
508 switch (child->type) {
518 case MOD_POLICY: /* same as MOD_GROUP */
519 stack.children[stack.pointer] = g->children;
523 * See the "camel book" for why
526 * If (rand(0..n) < 1), pick the
527 * current realm. We add a scale
528 * factor of 65536, to avoid
531 case MOD_LOAD_BALANCE:
532 case MOD_REDUNDANT_LOAD_BALANCE:
534 for(p = g->children; p; p = p->next) {
543 if ((count * (fr_rand() & 0xffff)) < (uint32_t) 0x10000) {
547 stack.children[stack.pointer] = q;
552 radius_xlat(buffer, sizeof(buffer),
553 child->name, request, NULL);
555 null_case = q = NULL;
556 for(p = g->children; p; p = p->next) {
558 if (!null_case) null_case = p;
561 if (strcmp(buffer, p->name) == 0) {
567 if (!q) q = null_case;
569 stack.children[stack.pointer] = q;
574 RDEBUG2("Internal sanity check failed in modcall %d", child->type);
575 exit(1); /* internal sanity check failure */
580 stack.start[stack.pointer] = stack.children[stack.pointer];
582 RDEBUG2("%.*s- entering %s %s",
583 stack.pointer, modcall_spaces,
584 group_name[child->type],
585 child->name ? child->name : "");
588 * Catch the special case of a NULL group.
590 if (!stack.children[stack.pointer]) {
592 * Print message for NULL group
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],
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.
613 * Process a stand-alone child, and fall through
614 * to dealing with it's parent.
616 sp = mod_callabletosingle(child);
618 myresult = call_modsingle(child->method, sp, request,
619 default_component_results[component]);
621 RDEBUG2("%.*s[%s] returns %s",
622 stack.pointer + 1, modcall_spaces,
623 child->name ? child->name : "",
624 fr_int2str(rcode_table, myresult, "??"));
627 * This is a bit of a hack...
629 if (component != RLM_COMPONENT_SESS) request->simul_max = myresult;
632 * FIXME: Allow modules to push a modcallable
633 * onto this stack. This should simplify
634 * configuration a LOT!
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
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
647 * Don't put "myresult" on the stack here,
648 * we have to do so with priority.
652 * We roll back up the stack at this point.
656 * The child's action says return. Do so.
658 if (child->actions[myresult] == MOD_ACTION_RETURN) {
659 stack.result[stack.pointer] = myresult;
660 stack.children[stack.pointer] = NULL;
665 * If "reject", break out of the loop and return
668 if (child->actions[myresult] == MOD_ACTION_REJECT) {
669 stack.children[stack.pointer] = NULL;
670 stack.result[stack.pointer] = RLM_MODULE_REJECT;
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
680 if (child->actions[myresult] >= stack.priority[stack.pointer]) {
681 stack.result[stack.pointer] = myresult;
682 stack.priority[stack.pointer] = child->actions[myresult];
690 * No parent, we must be done.
693 rad_assert(stack.pointer == 0);
694 myresult = stack.result[0];
698 rad_assert(child != NULL);
701 * Go to the "next" child, whatever that is.
703 switch (parent->type) {
711 case MOD_POLICY: /* same as MOD_GROUP */
712 stack.children[stack.pointer] = child->next;
718 case MOD_LOAD_BALANCE:
719 stack.children[stack.pointer] = NULL;
722 case MOD_REDUNDANT_LOAD_BALANCE:
724 stack.children[stack.pointer] = child->next;
726 modgroup *g = mod_callabletogroup(parent);
728 stack.children[stack.pointer] = g->children;
730 if (stack.children[stack.pointer] == stack.start[stack.pointer]) {
731 stack.children[stack.pointer] = NULL;
735 RDEBUG2("Internal sanity check failed in modcall next %d", child->type);
740 * No child, we're done this group, and we return
741 * "myresult" to the caller by pushing it back up
744 if (!stack.children[stack.pointer]) {
746 rad_assert(stack.pointer > 0);
747 myresult = stack.result[stack.pointer];
750 if (stack.pointer == 0) break;
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, "??"));
759 if ((parent->type == MOD_IF) ||
760 (parent->type == MOD_ELSIF)) {
761 if_taken = was_if = TRUE;
763 if_taken = was_if = FALSE;
770 child = stack.children[stack.pointer];
771 parent = child->parent;
775 } /* loop until done */
782 static const char *action2str(int action)
785 if(action==MOD_ACTION_RETURN)
787 if(action==MOD_ACTION_REJECT)
789 snprintf(buf, sizeof buf, "%d", action);
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)
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);
805 modgroup *g = mod_callabletogroup(c);
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);
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]));
819 RDEBUG("%.*s}", indent, "\t\t\t\t\t\t\t\t\t\t\t");
822 static void dump_tree(int comp, modcallable *c)
824 RDEBUG("[%s]", comp2str[comp]);
828 #define dump_tree(a, b)
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. */
835 defaultactions[RLM_COMPONENT_COUNT][GROUPTYPE_COUNT][RLM_MODULE_NUMCODES] =
841 MOD_ACTION_RETURN, /* reject */
843 MOD_ACTION_RETURN, /* ok */
844 MOD_ACTION_RETURN, /* handled */
846 MOD_ACTION_RETURN, /* userlock */
847 MOD_ACTION_RETURN, /* notfound */
853 MOD_ACTION_RETURN, /* reject */
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 */
865 MOD_ACTION_RETURN, /* reject */
867 MOD_ACTION_RETURN, /* ok */
868 MOD_ACTION_RETURN, /* handled */
869 MOD_ACTION_RETURN, /* invalid */
870 MOD_ACTION_RETURN, /* userlock */
872 MOD_ACTION_RETURN, /* noop */
873 MOD_ACTION_RETURN /* updated */
880 MOD_ACTION_RETURN, /* reject */
881 MOD_ACTION_RETURN, /* fail */
883 MOD_ACTION_RETURN, /* handled */
884 MOD_ACTION_RETURN, /* invalid */
885 MOD_ACTION_RETURN, /* userlock */
892 MOD_ACTION_RETURN, /* reject */
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 */
904 MOD_ACTION_RETURN, /* reject */
906 MOD_ACTION_RETURN, /* ok */
907 MOD_ACTION_RETURN, /* handled */
908 MOD_ACTION_RETURN, /* invalid */
909 MOD_ACTION_RETURN, /* userlock */
911 MOD_ACTION_RETURN, /* noop */
912 MOD_ACTION_RETURN /* updated */
919 MOD_ACTION_RETURN, /* reject */
920 MOD_ACTION_RETURN, /* fail */
922 MOD_ACTION_RETURN, /* handled */
923 MOD_ACTION_RETURN, /* invalid */
924 MOD_ACTION_RETURN, /* userlock */
925 MOD_ACTION_RETURN, /* notfound */
931 MOD_ACTION_RETURN, /* reject */
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 */
943 MOD_ACTION_RETURN, /* reject */
945 MOD_ACTION_RETURN, /* ok */
946 MOD_ACTION_RETURN, /* handled */
947 MOD_ACTION_RETURN, /* invalid */
948 MOD_ACTION_RETURN, /* userlock */
950 MOD_ACTION_RETURN, /* noop */
951 MOD_ACTION_RETURN /* updated */
958 MOD_ACTION_RETURN, /* reject */
959 MOD_ACTION_RETURN, /* fail */
961 MOD_ACTION_RETURN, /* handled */
962 MOD_ACTION_RETURN, /* invalid */
963 MOD_ACTION_RETURN, /* userlock */
964 MOD_ACTION_RETURN, /* notfound */
972 MOD_ACTION_RETURN, /* ok */
973 MOD_ACTION_RETURN, /* handled */
982 MOD_ACTION_RETURN, /* reject */
984 MOD_ACTION_RETURN, /* ok */
985 MOD_ACTION_RETURN, /* handled */
986 MOD_ACTION_RETURN, /* invalid */
987 MOD_ACTION_RETURN, /* userlock */
989 MOD_ACTION_RETURN, /* noop */
990 MOD_ACTION_RETURN /* updated */
997 MOD_ACTION_RETURN, /* reject */
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 */
1009 MOD_ACTION_RETURN, /* reject */
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 */
1021 MOD_ACTION_RETURN, /* reject */
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 */
1036 MOD_ACTION_RETURN, /* reject */
1037 MOD_ACTION_RETURN, /* fail */
1039 MOD_ACTION_RETURN, /* handled */
1040 MOD_ACTION_RETURN, /* invalid */
1041 MOD_ACTION_RETURN, /* userlock */
1048 MOD_ACTION_RETURN, /* reject */
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 */
1060 MOD_ACTION_RETURN, /* reject */
1062 MOD_ACTION_RETURN, /* ok */
1063 MOD_ACTION_RETURN, /* handled */
1064 MOD_ACTION_RETURN, /* invalid */
1065 MOD_ACTION_RETURN, /* userlock */
1067 MOD_ACTION_RETURN, /* noop */
1068 MOD_ACTION_RETURN /* updated */
1075 MOD_ACTION_RETURN, /* reject */
1076 MOD_ACTION_RETURN, /* fail */
1078 MOD_ACTION_RETURN, /* handled */
1079 MOD_ACTION_RETURN, /* invalid */
1080 MOD_ACTION_RETURN, /* userlock */
1087 MOD_ACTION_RETURN, /* reject */
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 */
1099 MOD_ACTION_RETURN, /* reject */
1101 MOD_ACTION_RETURN, /* ok */
1102 MOD_ACTION_RETURN, /* handled */
1103 MOD_ACTION_RETURN, /* invalid */
1104 MOD_ACTION_RETURN, /* userlock */
1106 MOD_ACTION_RETURN, /* noop */
1107 MOD_ACTION_RETURN /* updated */
1114 MOD_ACTION_RETURN, /* reject */
1115 MOD_ACTION_RETURN, /* fail */
1117 MOD_ACTION_RETURN, /* handled */
1118 MOD_ACTION_RETURN, /* invalid */
1119 MOD_ACTION_RETURN, /* userlock */
1126 MOD_ACTION_RETURN, /* reject */
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 */
1138 MOD_ACTION_RETURN, /* reject */
1140 MOD_ACTION_RETURN, /* ok */
1141 MOD_ACTION_RETURN, /* handled */
1142 MOD_ACTION_RETURN, /* invalid */
1143 MOD_ACTION_RETURN, /* userlock */
1145 MOD_ACTION_RETURN, /* noop */
1146 MOD_ACTION_RETURN /* updated */
1153 static modcallable *do_compile_modupdate(modcallable *parent,
1154 int component, CONF_SECTION *cs,
1159 modcallable *csingle;
1161 VALUE_PAIR *head, **tail;
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",
1171 component = component; /* -Wunused */
1173 if (!cf_section_name2(cs)) {
1174 cf_log_err(cf_sectiontoitem(cs),
1175 "Require list name for 'update'.\n");
1179 for (i = 0; attrlist_names[i] != NULL; i++) {
1180 if (strcmp(name2, attrlist_names[i]) == 0) {
1187 cf_log_err(cf_sectiontoitem(cs),
1188 "Unknown attribute list \"%s\"",
1197 * Walk through the children of the update section,
1198 * ensuring that they're all known attributes.
1200 for (ci=cf_item_find_next(cs, NULL);
1202 ci=cf_item_find_next(cs, ci)) {
1206 if (cf_item_is_section(ci)) {
1207 cf_log_err(ci, "\"update\" sections cannot have subsections");
1211 if (!cf_item_is_pair(ci)) continue;
1213 cp = cf_itemtopair(ci); /* can't return NULL */
1214 vp = cf_pairtovp(cp);
1217 cf_log_err(ci, "ERROR: %s", librad_errstr);
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)) {
1230 cf_log_err(ci, "Invalid operator for attribute");
1235 * A few more sanity checks. The enforcement of
1236 * <= or >= can only happen for integer
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)) {
1246 cf_log_err(ci, "Enforcment of <= or >= is possible only for integer attributes");
1256 cf_log_err(cf_sectiontoitem(cs),
1257 "ERROR: update %s section cannot be empty",
1262 g = rad_malloc(sizeof(*g)); /* never fails */
1263 memset(g, 0, sizeof(*g));
1264 csingle = mod_grouptocallable(g);
1266 csingle->parent = parent;
1267 csingle->next = NULL;
1268 csingle->name = name2;
1269 csingle->type = MOD_UPDATE;
1270 csingle->method = component;
1272 g->grouptype = GROUPTYPE_SIMPLE;
1281 static modcallable *do_compile_modswitch(modcallable *parent,
1282 int component, CONF_SECTION *cs)
1284 modcallable *csingle;
1286 int had_seen_default = FALSE;
1288 component = component; /* -Wunused */
1290 if (!cf_section_name2(cs)) {
1291 cf_log_err(cf_sectiontoitem(cs),
1292 "You must specify a variable to switch over for 'switch'.");
1296 if (!cf_item_find_next(cs, NULL)) {
1297 cf_log_err(cf_sectiontoitem(cs), "'switch' statments cannot be empty.");
1302 * Walk through the children of the switch section,
1303 * ensuring that they're all 'case' statements
1305 for (ci=cf_item_find_next(cs, NULL);
1307 ci=cf_item_find_next(cs, ci)) {
1308 CONF_SECTION *subcs;
1309 const char *name1, *name2;
1311 if (!cf_item_is_section(ci)) {
1312 if (!cf_item_is_pair(ci)) continue;
1314 cf_log_err(ci, "\"switch\" sections can only have \"case\" subsections");
1318 subcs = cf_itemtosection(ci); /* can't return NULL */
1319 name1 = cf_section_name1(subcs);
1321 if (strcmp(name1, "case") != 0) {
1322 cf_log_err(ci, "\"switch\" sections can only have \"case\" subsections");
1326 name2 = cf_section_name2(subcs);
1327 if (!name2 && !had_seen_default) {
1328 had_seen_default = TRUE;
1332 if (!name2 || (name2[0] == '\0')) {
1333 cf_log_err(ci, "\"case\" sections must have a name");
1338 csingle= do_compile_modgroup(parent, component, cs,
1339 GROUPTYPE_SIMPLE, GROUPTYPE_SIMPLE);
1340 if (!csingle) return NULL;
1341 csingle->type = MOD_SWITCH;
1346 static modcallable *do_compile_modserver(modcallable *parent,
1347 int component, CONF_ITEM *ci,
1352 modcallable *csingle;
1353 CONF_SECTION *subcs;
1356 subcs = cf_section_sub_find_name2(cs, comp2str[component], NULL);
1358 cf_log_err(ci, "Server %s has no %s section",
1359 server, comp2str[component]);
1363 mr = rad_malloc(sizeof(*mr));
1364 memset(mr, 0, sizeof(*mr));
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;
1373 memcpy(csingle->actions, defaultactions[component][GROUPTYPE_SIMPLE],
1374 sizeof(csingle->actions));
1376 mr->ref_name = strdup(server);
1382 static modcallable *do_compile_modxlat(modcallable *parent,
1383 int component, const char *fmt)
1385 modcallable *csingle;
1388 mx = rad_malloc(sizeof(*mx));
1389 memset(mx, 0, sizeof(*mx));
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;
1398 memcpy(csingle->actions, defaultactions[component][GROUPTYPE_SIMPLE],
1399 sizeof(csingle->actions));
1401 mx->xlat_name = strdup(fmt);
1407 * redundant, etc. can refer to modules or groups, but not much else.
1409 static int all_children_are_modules(CONF_SECTION *cs, const char *name)
1413 for (ci=cf_item_find_next(cs, NULL);
1415 ci=cf_item_find_next(cs, ci)) {
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.
1423 if (cf_item_is_section(ci)) {
1424 CONF_SECTION *subcs = cf_itemtosection(ci);
1425 const char *name1 = cf_section_name1(subcs);
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",
1440 if (cf_item_is_pair(ci)) {
1441 CONF_PAIR *cp = cf_itemtopair(ci);
1442 if (cf_pair_value(cp) != NULL) {
1444 "Entry with no value is invalid");
1455 * Compile one entry of a module call.
1457 static modcallable *do_compile_modsingle(modcallable *parent,
1458 int component, CONF_ITEM *ci,
1460 const char **modname)
1465 const char *modrefname;
1467 modcallable *csingle;
1468 module_instance_t *this;
1469 CONF_SECTION *cs, *subcs, *modules;
1471 if (cf_item_is_section(ci)) {
1474 cs = cf_itemtosection(ci);
1475 modrefname = cf_section_name1(cs);
1476 name2 = cf_section_name2(cs);
1477 if (!name2) name2 = "_UnNamedGroup";
1480 * group{}, redundant{}, or append{} may appear
1481 * where a single module instance was expected.
1482 * In that case, we hand it off to
1485 if (strcmp(modrefname, "group") == 0) {
1487 return do_compile_modgroup(parent, component, cs,
1491 } else if (strcmp(modrefname, "redundant") == 0) {
1494 if (!all_children_are_modules(cs, modrefname)) {
1498 return do_compile_modgroup(parent, component, cs,
1499 GROUPTYPE_REDUNDANT,
1502 } else if (strcmp(modrefname, "append") == 0) {
1504 return do_compile_modgroup(parent, component, cs,
1508 } else if (strcmp(modrefname, "load-balance") == 0) {
1511 if (!all_children_are_modules(cs, modrefname)) {
1515 csingle= do_compile_modgroup(parent, component, cs,
1518 if (!csingle) return NULL;
1519 csingle->type = MOD_LOAD_BALANCE;
1522 } else if (strcmp(modrefname, "redundant-load-balance") == 0) {
1525 if (!all_children_are_modules(cs, modrefname)) {
1529 csingle= do_compile_modgroup(parent, component, cs,
1530 GROUPTYPE_REDUNDANT,
1532 if (!csingle) return NULL;
1533 csingle->type = MOD_REDUNDANT_LOAD_BALANCE;
1537 } else if (strcmp(modrefname, "if") == 0) {
1538 if (!cf_section_name2(cs)) {
1539 cf_log_err(ci, "'if' without condition.");
1544 csingle= do_compile_modgroup(parent, component, cs,
1547 if (!csingle) return NULL;
1548 csingle->type = MOD_IF;
1550 if (!radius_evaluate_condition(NULL, 0, 0, modname,
1552 modcallable_free(&csingle);
1559 } else if (strcmp(modrefname, "elsif") == 0) {
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.");
1567 if (!cf_section_name2(cs)) {
1568 cf_log_err(ci, "'elsif' without condition.");
1573 csingle= do_compile_modgroup(parent, component, cs,
1576 if (!csingle) return NULL;
1577 csingle->type = MOD_ELSIF;
1579 if (!radius_evaluate_condition(NULL, 0, 0, modname,
1581 modcallable_free(&csingle);
1588 } else if (strcmp(modrefname, "else") == 0) {
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.");
1596 if (cf_section_name2(cs)) {
1597 cf_log_err(ci, "Cannot have conditions on 'else'.");
1602 csingle= do_compile_modgroup(parent, component, cs,
1605 if (!csingle) return NULL;
1606 csingle->type = MOD_ELSE;
1609 } else if (strcmp(modrefname, "update") == 0) {
1612 csingle = do_compile_modupdate(parent, component, cs,
1614 if (!csingle) return NULL;
1618 } else if (strcmp(modrefname, "switch") == 0) {
1621 csingle = do_compile_modswitch(parent, component, cs);
1622 if (!csingle) return NULL;
1626 } else if (strcmp(modrefname, "case") == 0) {
1632 * FIXME: How to tell that the parent can only
1633 * be a "switch" statement?
1636 cf_log_err(ci, "\"case\" statements may only appear within a \"switch\" section");
1640 csingle= do_compile_modgroup(parent, component, cs,
1643 if (!csingle) return NULL;
1644 csingle->type = MOD_CASE;
1645 csingle->name = cf_section_name2(cs); /* may be NULL */
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.
1652 for (i = 0; i < RLM_MODULE_NUMCODES; i++) {
1653 csingle->actions[i] = MOD_ACTION_RETURN;
1658 } /* else it's something like sql { fail = 1 ...} */
1660 } else if (!cf_item_is_pair(ci)) { /* CONF_DATA or some such */
1664 * Else it's a module reference, with updated return
1668 CONF_PAIR *cp = cf_itemtopair(ci);
1669 modrefname = cf_pair_attr(cp);
1672 * Actions (ok = 1), etc. are orthoganal to just
1673 * about everything else.
1675 if (cf_pair_value(cp) != NULL) {
1676 cf_log_err(ci, "Entry is not a reference to a module");
1680 if ((modrefname[0] == '%') && (modrefname[1] == '{')) {
1681 return do_compile_modxlat(parent, component,
1686 * See if the module is a virtual one. If so,
1687 * return that, rather than doing anything here.
1690 cs = cf_section_find("instantiate");
1692 cs = cf_section_find("policy");
1693 if (cs) subcs = cf_section_sub_find_name2(cs, NULL,
1697 DEBUG2(" Module: Loading virtual module %s",
1701 * redundant foo {} is a single.
1703 if (cf_section_name2(subcs)) {
1704 return do_compile_modsingle(parent,
1706 cf_sectiontoitem(subcs),
1711 * foo {} is a group.
1713 return do_compile_modgroup(parent,
1723 * Not a virtual module. It must be a real module.
1725 modules = cf_section_find("modules");
1728 if (modules && cf_section_sub_find_name2(modules, NULL, modrefname)) {
1729 this = find_module_instance(modules, modrefname);
1737 * Maybe it's module.method
1739 p = strrchr(modrefname, '.');
1740 if (p) for (i = RLM_COMPONENT_AUTH;
1741 i < RLM_COMPONENT_COUNT;
1743 if (strcmp(p + 1, comp2str[i]) == 0) {
1746 strlcpy(buffer, modrefname, sizeof(buffer));
1747 buffer[p - modrefname] = '\0';
1750 this = find_module_instance(cf_section_find("modules"), buffer);
1752 !this->entry->module->methods[i]) {
1754 cf_log_err(ci, "Module %s has no such method %s", buffer, comp2str[i]);
1762 if (strncmp(modrefname, "server[", 7) == 0) {
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);
1773 cs = cf_section_sub_find_name2(NULL, "server", buffer);
1775 cf_log_err(ci, "No such server \"%s\".", buffer);
1779 return do_compile_modserver(parent, component, ci,
1780 modrefname, cs, buffer);
1784 cf_log_err(ci, "Failed to find module \"%s\".", modrefname);
1789 * We know it's all OK, allocate the structures, and fill
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);
1804 rad_assert(modrefname != NULL);
1805 csingle->name = modrefname;
1806 csingle->type = MOD_SINGLE;
1807 csingle->method = component;
1810 * Singles can override the actions, virtual modules cannot.
1812 * FIXME: We may want to re-visit how to do this...
1813 * maybe a csingle as a ref?
1815 if (cf_item_is_section(ci)) {
1816 cs = cf_itemtosection(ci);
1818 for (ci=cf_item_find_next(cs, NULL);
1820 ci=cf_item_find_next(cs, ci)) {
1822 if (cf_item_is_section(ci)) {
1823 cf_log_err(ci, "Subsection of module instance call not allowed");
1824 modcallable_free(&csingle);
1828 if (!cf_item_is_pair(ci)) continue;
1830 if (!compile_action(csingle, cf_itemtopair(ci))) {
1831 modcallable_free(&csingle);
1838 * Bail out if the module in question does not supply the
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);
1848 single->modinst = this;
1849 *modname = this->entry->module->name;
1853 modcallable *compile_modsingle(modcallable *parent,
1854 int component, CONF_ITEM *ci,
1855 const char **modname)
1857 modcallable *ret = do_compile_modsingle(parent, component, ci,
1860 dump_tree(component, ret);
1866 * Internal compile group code.
1868 static modcallable *do_compile_modgroup(modcallable *parent,
1869 int component, CONF_SECTION *cs,
1870 int grouptype, int parentgrouptype)
1877 g = rad_malloc(sizeof(*g));
1878 memset(g, 0, sizeof(*g));
1879 g->grouptype = grouptype;
1881 c = mod_grouptocallable(g);
1883 c->type = MOD_GROUP;
1885 memset(c->actions, 0, sizeof(c->actions));
1888 * Remember the name for printing, etc.
1890 * FIXME: We may also want to put the names into a
1891 * rbtree, so that groups can reference each other...
1893 c->name = cf_section_name2(cs);
1895 c->name = cf_section_name1(cs);
1896 if (strcmp(c->name, "group") == 0) {
1899 c->type = MOD_POLICY;
1905 * Loop over the children of this group.
1907 for (ci=cf_item_find_next(cs, NULL);
1909 ci=cf_item_find_next(cs, ci)) {
1912 * Sections are references to other groups, or
1913 * to modules with updated return codes.
1915 if (cf_item_is_section(ci)) {
1916 const char *junk = NULL;
1917 modcallable *single;
1918 CONF_SECTION *subcs = cf_itemtosection(ci);
1920 single = do_compile_modsingle(c, component, ci,
1923 cf_log_err(ci, "Failed to parse \"%s\" subsection.",
1924 cf_section_name1(subcs));
1925 modcallable_free(&c);
1928 add_child(g, single);
1930 } else if (!cf_item_is_pair(ci)) { /* CONF_DATA */
1934 const char *attr, *value;
1935 CONF_PAIR *cp = cf_itemtopair(ci);
1937 attr = cf_pair_attr(cp);
1938 value = cf_pair_value(cp);
1941 * A CONF_PAIR is either a module
1942 * instance with no actions
1946 modcallable *single;
1947 const char *junk = NULL;
1949 single = do_compile_modsingle(c,
1956 "Failed to parse \"%s\" entry.",
1958 modcallable_free(&c);
1961 add_child(g, single);
1964 * Or a module instance with action.
1966 } else if (!compile_action(c, cp)) {
1967 modcallable_free(&c);
1969 } /* else it worked */
1974 * Set the default actions, if they haven't already been
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];
1988 * FIXME: If there are no children, return NULL?
1990 return mod_grouptocallable(g);
1993 modcallable *compile_modgroup(modcallable *parent,
1994 int component, CONF_SECTION *cs)
1996 modcallable *ret = do_compile_modgroup(parent, component, cs,
1999 dump_tree(component, ret);
2003 void add_to_modcallable(modcallable **parent, modcallable *this,
2004 int component, const char *name)
2008 rad_assert(this != NULL);
2010 if (*parent == NULL) {
2013 g = rad_malloc(sizeof *g);
2014 memset(g, 0, sizeof(*g));
2015 g->grouptype = GROUPTYPE_SIMPLE;
2016 c = mod_grouptocallable(g);
2019 defaultactions[component][GROUPTYPE_SIMPLE],
2020 sizeof(c->actions));
2021 rad_assert(name != NULL);
2023 c->type = MOD_GROUP;
2024 c->method = component;
2027 *parent = mod_grouptocallable(g);
2029 g = mod_callabletogroup(*parent);
2035 void modcallable_free(modcallable **pc)
2037 modcallable *c, *loop, *next;
2039 if (c->type != MOD_SINGLE) {
2040 modgroup *g = mod_callabletogroup(c);
2042 for(loop = g->children;
2046 modcallable_free(&loop);