📄 modcall.c
字号:
return csingle; } else if (strcmp(modrefname, "elsif") == 0) { if (parent && ((parent->type == MOD_LOAD_BALANCE) || (parent->type == MOD_REDUNDANT_LOAD_BALANCE))) { cf_log_err(ci, "'elsif' cannot be used in this section section."); return NULL; } if (!cf_section_name2(cs)) { cf_log_err(ci, "'elsif' without condition."); return NULL; } *modname = name2; csingle= do_compile_modgroup(parent, component, cs, GROUPTYPE_SIMPLE, grouptype); if (!csingle) return NULL; csingle->type = MOD_ELSIF; if (!radius_evaluate_condition(NULL, 0, 0, modname, FALSE, &result)) { modcallable_free(&csingle); return NULL; } *modname = name2; return csingle; } else if (strcmp(modrefname, "else") == 0) { if (parent && ((parent->type == MOD_LOAD_BALANCE) || (parent->type == MOD_REDUNDANT_LOAD_BALANCE))) { cf_log_err(ci, "'else' cannot be used in this section section."); return NULL; } if (cf_section_name2(cs)) { cf_log_err(ci, "Cannot have conditions on 'else'."); return NULL; } *modname = name2; csingle= do_compile_modgroup(parent, component, cs, GROUPTYPE_SIMPLE, grouptype); if (!csingle) return NULL; csingle->type = MOD_ELSE; return csingle; } else if (strcmp(modrefname, "update") == 0) { *modname = name2; csingle = do_compile_modupdate(parent, component, cs, name2); if (!csingle) return NULL; return csingle; } else if (strcmp(modrefname, "switch") == 0) { *modname = name2; csingle = do_compile_modswitch(parent, component, cs); if (!csingle) return NULL; return csingle; } else if (strcmp(modrefname, "case") == 0) { int i; *modname = name2; /* * FIXME: How to tell that the parent can only * be a "switch" statement? */ if (!parent) { cf_log_err(ci, "\"case\" statements may only appear within a \"switch\" section"); return NULL; } csingle= do_compile_modgroup(parent, component, cs, GROUPTYPE_SIMPLE, grouptype); if (!csingle) return NULL; csingle->type = MOD_CASE; csingle->name = cf_section_name2(cs); /* may be NULL */ /* * Set all of it's codes to return, so that * when we pick a 'case' statement, we don't * fall through to processing the next one. */ for (i = 0; i < RLM_MODULE_NUMCODES; i++) { csingle->actions[i] = MOD_ACTION_RETURN; } return csingle; } /* else it's something like sql { fail = 1 ...} */ } else if (!cf_item_is_pair(ci)) { /* CONF_DATA or some such */ return NULL; /* * Else it's a module reference, with updated return * codes. */ } else { CONF_PAIR *cp = cf_itemtopair(ci); modrefname = cf_pair_attr(cp); /* * Actions (ok = 1), etc. are orthoganal to just * about everything else. */ if (cf_pair_value(cp) != NULL) { cf_log_err(ci, "Entry is not a reference to a module"); return NULL; } /* * See if the module is a virtual one. If so, * return that, rather than doing anything here. */ subcs = NULL; cs = cf_section_find("instantiate"); if (!subcs) { cs = cf_section_find("policy"); if (cs) subcs = cf_section_sub_find_name2(cs, NULL, modrefname); } if (subcs) { DEBUG2(" Module: Loading virtual module %s", modrefname); /* * redundant foo {} is a single. */ if (cf_section_name2(subcs)) { return do_compile_modsingle(parent, component, cf_sectiontoitem(subcs), grouptype, modname); } else { /* * foo {} is a group. */ return do_compile_modgroup(parent, component, subcs, GROUPTYPE_SIMPLE, grouptype); } } } /* * Not a virtual module. It must be a real module. */ modules = cf_section_find("modules"); this = NULL; if (modules && cf_section_sub_find_name2(modules, NULL, modrefname)) { this = find_module_instance(modules, modrefname); } if (!this) do { int i; char *p; /* * Maybe it's module.method */ p = strrchr(modrefname, '.'); if (p) for (i = RLM_COMPONENT_AUTH; i < RLM_COMPONENT_COUNT; i++) { if (strcmp(p + 1, comp2str[i]) == 0) { char buffer[256]; strlcpy(buffer, modrefname, sizeof(buffer)); buffer[p - modrefname] = '\0'; component = i; this = find_module_instance(cf_section_find("modules"), buffer); if (this && !this->entry->module->methods[i]) { *modname = NULL; cf_log_err(ci, "Module %s has no such method %s", buffer, comp2str[i]); return NULL; } break; } } if (this) break; if (strncmp(modrefname, "server[", 7) == 0) { char buffer[256]; strlcpy(buffer, modrefname + 7, sizeof(buffer)); p = strrchr(buffer, ']'); if (!p || p[1] != '\0' || (p == buffer)) { cf_log_err(ci, "Invalid server reference in \"%s\".", modrefname); return NULL; } *p = '\0'; cs = cf_section_sub_find_name2(NULL, "server", buffer); if (!cs) { cf_log_err(ci, "No such server \"%s\".", buffer); return NULL; } return do_compile_modserver(parent, component, ci, modrefname, cs, buffer); } *modname = NULL; cf_log_err(ci, "Failed to find module \"%s\".", modrefname); return NULL; } while (0); /* * We know it's all OK, allocate the structures, and fill * them in. */ single = rad_malloc(sizeof(*single)); memset(single, 0, sizeof(*single)); csingle = mod_singletocallable(single); csingle->parent = parent; csingle->next = NULL; if (!parent || (component != RLM_COMPONENT_AUTH)) { memcpy(csingle->actions, defaultactions[component][grouptype], sizeof csingle->actions); } else { /* inside Auth-Type has different rules */ memcpy(csingle->actions, defaultactions[RLM_COMPONENT_AUTZ][grouptype], sizeof csingle->actions); } rad_assert(modrefname != NULL); csingle->name = modrefname; csingle->type = MOD_SINGLE; csingle->method = component; /* * Singles can override the actions, virtual modules cannot. * * FIXME: We may want to re-visit how to do this... * maybe a csingle as a ref? */ if (cf_item_is_section(ci)) { cs = cf_itemtosection(ci); for (ci=cf_item_find_next(cs, NULL); ci != NULL; ci=cf_item_find_next(cs, ci)) { if (cf_item_is_section(ci)) { cf_log_err(ci, "Subsection of module instance call not allowed"); modcallable_free(&csingle); return NULL; } if (!cf_item_is_pair(ci)) continue; if (!compile_action(csingle, cf_itemtopair(ci))) { modcallable_free(&csingle); return NULL; } } } /* * Bail out if the module in question does not supply the * wanted component */ if (!this->entry->module->methods[component]) { cf_log_err(ci, "\"%s\" modules aren't allowed in '%s' sections -- they have no such method.", this->entry->module->name, comp2str[component]); modcallable_free(&csingle); return NULL; } single->modinst = this; *modname = this->entry->module->name; return csingle;}modcallable *compile_modsingle(modcallable *parent, int component, CONF_ITEM *ci, const char **modname){ modcallable *ret = do_compile_modsingle(parent, component, ci, GROUPTYPE_SIMPLE, modname); dump_tree(component, ret); return ret;}/* * Internal compile group code. */static modcallable *do_compile_modgroup(modcallable *parent, int component, CONF_SECTION *cs, int grouptype, int parentgrouptype){ int i; modgroup *g; modcallable *c; CONF_ITEM *ci; g = rad_malloc(sizeof(*g)); memset(g, 0, sizeof(*g)); g->grouptype = grouptype; c = mod_grouptocallable(g); c->parent = parent; c->type = MOD_GROUP; c->next = NULL; memset(c->actions, 0, sizeof(c->actions)); /* * Remember the name for printing, etc. * * FIXME: We may also want to put the names into a * rbtree, so that groups can reference each other... */ c->name = cf_section_name2(cs); if (!c->name) { c->name = cf_section_name1(cs); if (strcmp(c->name, "group") == 0) { c->name = ""; } else { c->type = MOD_POLICY; } } g->children = NULL; /* * Loop over the children of this group. */ for (ci=cf_item_find_next(cs, NULL); ci != NULL; ci=cf_item_find_next(cs, ci)) { /* * Sections are references to other groups, or * to modules with updated return codes. */ if (cf_item_is_section(ci)) { const char *junk = NULL; modcallable *single; CONF_SECTION *subcs = cf_itemtosection(ci); single = do_compile_modsingle(c, component, ci, grouptype, &junk); if (!single) { cf_log_err(ci, "Failed to parse \"%s\" subsection.", cf_section_name1(subcs)); modcallable_free(&c); return NULL; } add_child(g, single); } else if (!cf_item_is_pair(ci)) { /* CONF_DATA */ continue; } else { const char *attr, *value; CONF_PAIR *cp = cf_itemtopair(ci); attr = cf_pair_attr(cp); value = cf_pair_value(cp); /* * A CONF_PAIR is either a module * instance with no actions * specified ... */ if (!value) { modcallable *single; const char *junk = NULL; single = do_compile_modsingle(c, component, ci, grouptype, &junk); if (!single) { cf_log_err(ci, "Failed to parse \"%s\" entry.", attr); modcallable_free(&c); return NULL; } add_child(g, single); /* * Or a module instance with action. */ } else if (!compile_action(c, cp)) { modcallable_free(&c); return NULL; } /* else it worked */ } } /* * Set the default actions, if they haven't already been * set. */ for (i = 0; i < RLM_MODULE_NUMCODES; i++) { if (!c->actions[i]) { if (!parent || (component != RLM_COMPONENT_AUTH)) { c->actions[i] = defaultactions[component][parentgrouptype][i]; } else { /* inside Auth-Type has different rules */ c->actions[i] = defaultactions[RLM_COMPONENT_AUTZ][parentgrouptype][i]; } } } /* * FIXME: If there are no children, return NULL? */ return mod_grouptocallable(g);}modcallable *compile_modgroup(modcallable *parent, int component, CONF_SECTION *cs){ modcallable *ret = do_compile_modgroup(parent, component, cs, GROUPTYPE_SIMPLE, GROUPTYPE_SIMPLE); dump_tree(component, ret); return ret;}void add_to_modcallable(modcallable **parent, modcallable *this, int component, const char *name){ modgroup *g; rad_assert(this != NULL); if (*parent == NULL) { modcallable *c; g = rad_malloc(sizeof *g); memset(g, 0, sizeof(*g)); g->grouptype = GROUPTYPE_SIMPLE; c = mod_grouptocallable(g); c->next = NULL; memcpy(c->actions, defaultactions[component][GROUPTYPE_SIMPLE], sizeof(c->actions)); rad_assert(name != NULL); c->name = name; c->type = MOD_GROUP; c->method = component; g->children = NULL; *parent = mod_grouptocallable(g); } else { g = mod_callabletogroup(*parent); } add_child(g, this);}void modcallable_free(modcallable **pc){ modcallable *c, *loop, *next; c = *pc; if (c->type != MOD_SINGLE) { modgroup *g = mod_callabletogroup(c); for(loop = g->children; loop ; loop = next) { next = loop->next; modcallable_free(&loop); } pairfree(&g->vps); } free(c); *pc = NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -