Allow virtual modules to have method over-rides, too
authorAlan T. DeKok <aland@freeradius.org>
Fri, 4 Sep 2015 15:25:28 +0000 (11:25 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Fri, 4 Sep 2015 15:25:28 +0000 (11:25 -0400)
src/main/modcall.c
src/tests/keywords/radiusd.conf
src/tests/keywords/virtual-load-balance [new file with mode: 0644]
src/tests/keywords/virtual_policy [new file with mode: 0644]

index e503d85..e2ae38e 100644 (file)
@@ -2148,6 +2148,86 @@ static int all_children_are_modules(CONF_SECTION *cs, char const *name)
 
 
 /*
+ *     Load a named module from "instantiate" or "policy".
+ *
+ *     If it's "foo.method", look for "foo", and return "method" as the method
+ *     we wish to use, instead of the input component.
+ */
+static CONF_SECTION *virtual_module_find_cs(char const *virtual_name, char const *method_name,
+                                           rlm_components_t *pcomponent)
+{
+       CONF_SECTION *cs, *subcs;
+       rlm_components_t method = *pcomponent;
+       char buffer[256];
+
+       /*
+        *      Turn the method name into a method enum.
+        */
+       if (method_name) {
+               rlm_components_t i;
+
+               for (i = MOD_AUTHENTICATE; i < MOD_COUNT; i++) {
+                       if (strcmp(comp2str[i], method_name)) break;
+               }
+
+               if (i == MOD_COUNT) return NULL;
+       }
+
+       /*
+        *      Look for "foo" in the "instantiate" section.  If we
+        *      find it, AND there's no method name, we've found the
+        *      right thing.
+        *
+        *      Return it to the caller, with the updated method.
+        */
+       cs = cf_section_find("instantiate");
+       if (cs) {
+               /*
+                *      Found "foo".  Load it as "foo", or "foo.method".
+                */
+               subcs = cf_section_sub_find_name2(cs, NULL, virtual_name);
+               if (subcs) {
+                       *pcomponent = method;
+                       return subcs;
+               }
+       }
+
+       /*
+        *      Look for it in "policy".
+        *
+        *      If there's no policy section, we can't do anything else.
+        */
+       cs = cf_section_find("policy");
+       if (!cs) return NULL;
+
+       /*
+        *      "foo.authorize" means "load policy "foo" as method "authorize".
+        *
+        *      And bail out if there's no policy "foo".
+        */
+       if (method_name) {
+               subcs = cf_section_sub_find_name2(cs, NULL, virtual_name);
+               if (subcs) *pcomponent = method;
+
+               return subcs;
+       }
+
+       /*
+        *      "foo" means "look for foo.component" first, to allow
+        *      method overrides.  If that's not found, just look for
+        *      a policy "foo".
+        *
+        */
+       snprintf(buffer, sizeof(buffer), "%s.%s",
+                virtual_name, comp2str[method]);
+       subcs = cf_section_sub_find_name2(cs, NULL, buffer);
+       if (subcs) return subcs;
+
+       return cf_section_sub_find_name2(cs, NULL, virtual_name);
+}
+
+
+/*
  *     Compile one entry of a module call.
  */
 static modcallable *do_compile_modsingle(modcallable *parent,
@@ -2422,31 +2502,21 @@ static modcallable *do_compile_modsingle(modcallable *parent,
         *      policy { ... name { .. } .. }
         *      policy { ... name.method { .. } .. }
         *
-        *      The "instantiate" virtual modules are identical to the
-        *      policies at this point.  We should probably get rid of
-        *      the "instantiate" ones, as they're duplicate and
-        *      confusing.
+        *      The only difference between things in "instantiate"
+        *      and "policy" is that "instantiate" will cause modules
+        *      to be instantiated in a particular order.
         */
        subcs = NULL;
-       cs = cf_section_find("instantiate");
-       if (cs) subcs = cf_section_sub_find_name2(cs, NULL,
-                                                 modrefname);
-       if (!subcs &&
-           (cs = cf_section_find("policy")) != NULL) {
+       p = strrchr(modrefname, '.');
+       if (!p) {
+               subcs = virtual_module_find_cs(modrefname, NULL, &method);
+       } else {
                char buffer[256];
 
-               snprintf(buffer, sizeof(buffer), "%s.%s",
-                        modrefname, comp2str[component]);
+               strlcpy(buffer, modrefname, sizeof(buffer));
+               buffer[p - modrefname] = '\0';
 
-               /*
-                *      Prefer name.section, then name.
-                */
-               subcs = cf_section_sub_find_name2(cs, NULL,
-                                                         buffer);
-               if (!subcs) {
-                       subcs = cf_section_sub_find_name2(cs, NULL,
-                                                         modrefname);
-               }
+               subcs = virtual_module_find_cs(buffer, buffer + (p - modrefname) + 1, &method);
        }
 
        /*
@@ -2484,7 +2554,7 @@ static modcallable *do_compile_modsingle(modcallable *parent,
                 */
                if (cf_section_name2(subcs)) {
                        csingle = do_compile_modsingle(parent,
-                                                      component,
+                                                      method,
                                                       cf_section_to_item(subcs),
                                                       grouptype,
                                                       modname);
@@ -2499,7 +2569,7 @@ static modcallable *do_compile_modsingle(modcallable *parent,
                         *      group foo { ...
                         */
                        csingle = do_compile_modgroup(parent,
-                                                     component,
+                                                     method,
                                                      subcs,
                                                      GROUPTYPE_SIMPLE,
                                                      grouptype, MOD_GROUP);
index c5e0878..a57d709 100644 (file)
@@ -81,6 +81,23 @@ policy {
                debug_request
                debug_reply
        }
+
+       #
+       #  Just check that this can be referred to as "virtual_policy.post-auth"
+       #
+       virtual_policy {
+               ok
+       }
+}
+
+instantiate {
+       #
+       #  Just check that this can be referred to as "virtual_instantiate.post-auth"
+       #
+       load-balance virtual_instantiate {
+               ok
+               ok
+       }
 }
 
 server default {
diff --git a/src/tests/keywords/virtual-load-balance b/src/tests/keywords/virtual-load-balance
new file mode 100644 (file)
index 0000000..256c2ff
--- /dev/null
@@ -0,0 +1,14 @@
+# PRE: update if foreach
+#
+#  Virtual Load-Balance blocks.
+#
+
+#
+#  Both of these should parse.
+#
+virtual_instantiate
+virtual_instantiate.post-auth
+
+update reply {
+       Filter-Id := 'filter'
+}
diff --git a/src/tests/keywords/virtual_policy b/src/tests/keywords/virtual_policy
new file mode 100644 (file)
index 0000000..4ab00e2
--- /dev/null
@@ -0,0 +1,15 @@
+# PRE: update if foreach
+#
+#  Virtual policies
+#
+
+
+#
+#  Both of these should parse.
+#
+virtual_policy
+virtual_policy.post-auth
+
+update reply {
+       Filter-Id := 'filter'
+}