📄 modcall.c
字号:
/* group */ { MOD_ACTION_RETURN, /* reject */ MOD_ACTION_RETURN, /* fail */ 3, /* ok */ MOD_ACTION_RETURN, /* handled */ MOD_ACTION_RETURN, /* invalid */ MOD_ACTION_RETURN, /* userlock */ 1, /* notfound */ 2, /* noop */ 4 /* updated */ }, /* redundant */ { MOD_ACTION_RETURN, /* reject */ 1, /* fail */ MOD_ACTION_RETURN, /* ok */ MOD_ACTION_RETURN, /* handled */ MOD_ACTION_RETURN, /* invalid */ MOD_ACTION_RETURN, /* userlock */ MOD_ACTION_RETURN, /* notfound */ MOD_ACTION_RETURN, /* noop */ MOD_ACTION_RETURN /* updated */ }, /* append */ { MOD_ACTION_RETURN, /* reject */ 1, /* fail */ MOD_ACTION_RETURN, /* ok */ MOD_ACTION_RETURN, /* handled */ MOD_ACTION_RETURN, /* invalid */ MOD_ACTION_RETURN, /* userlock */ 2, /* notfound */ MOD_ACTION_RETURN, /* noop */ MOD_ACTION_RETURN /* updated */ } }, /* post-proxy */ { /* group */ { MOD_ACTION_RETURN, /* reject */ MOD_ACTION_RETURN, /* fail */ 3, /* ok */ MOD_ACTION_RETURN, /* handled */ MOD_ACTION_RETURN, /* invalid */ MOD_ACTION_RETURN, /* userlock */ 1, /* notfound */ 2, /* noop */ 4 /* updated */ }, /* redundant */ { MOD_ACTION_RETURN, /* reject */ 1, /* fail */ MOD_ACTION_RETURN, /* ok */ MOD_ACTION_RETURN, /* handled */ MOD_ACTION_RETURN, /* invalid */ MOD_ACTION_RETURN, /* userlock */ MOD_ACTION_RETURN, /* notfound */ MOD_ACTION_RETURN, /* noop */ MOD_ACTION_RETURN /* updated */ }, /* append */ { MOD_ACTION_RETURN, /* reject */ 1, /* fail */ MOD_ACTION_RETURN, /* ok */ MOD_ACTION_RETURN, /* handled */ MOD_ACTION_RETURN, /* invalid */ MOD_ACTION_RETURN, /* userlock */ 2, /* notfound */ MOD_ACTION_RETURN, /* noop */ MOD_ACTION_RETURN /* updated */ } }, /* post-auth */ { /* group */ { MOD_ACTION_RETURN, /* reject */ MOD_ACTION_RETURN, /* fail */ 3, /* ok */ MOD_ACTION_RETURN, /* handled */ MOD_ACTION_RETURN, /* invalid */ MOD_ACTION_RETURN, /* userlock */ 1, /* notfound */ 2, /* noop */ 4 /* updated */ }, /* redundant */ { MOD_ACTION_RETURN, /* reject */ 1, /* fail */ MOD_ACTION_RETURN, /* ok */ MOD_ACTION_RETURN, /* handled */ MOD_ACTION_RETURN, /* invalid */ MOD_ACTION_RETURN, /* userlock */ MOD_ACTION_RETURN, /* notfound */ MOD_ACTION_RETURN, /* noop */ MOD_ACTION_RETURN /* updated */ }, /* append */ { MOD_ACTION_RETURN, /* reject */ 1, /* fail */ MOD_ACTION_RETURN, /* ok */ MOD_ACTION_RETURN, /* handled */ MOD_ACTION_RETURN, /* invalid */ MOD_ACTION_RETURN, /* userlock */ 2, /* notfound */ MOD_ACTION_RETURN, /* noop */ MOD_ACTION_RETURN /* updated */ } }};static modcallable *do_compile_modupdate(modcallable *parent, int component, CONF_SECTION *cs, const char *name2){ int i, ok = FALSE; modgroup *g; modcallable *csingle; CONF_ITEM *ci; VALUE_PAIR *head, **tail; static const char *attrlist_names[] = { "request", "reply", "proxy-request", "proxy-reply", "config", "control", "outer.request", "outer.reply", "outer.config", "outer.control", NULL }; component = component; /* -Wunused */ if (!cf_section_name2(cs)) { cf_log_err(cf_sectiontoitem(cs), "Require list name for 'update'.\n"); return NULL; } for (i = 0; attrlist_names[i] != NULL; i++) { if (strcmp(name2, attrlist_names[i]) == 0) { ok = TRUE; break; } } if (!ok) { cf_log_err(cf_sectiontoitem(cs), "Unknown attribute list \"%s\"", name2); return NULL; } head = NULL; tail = &head; /* * Walk through the children of the update section, * ensuring that they're all known attributes. */ for (ci=cf_item_find_next(cs, NULL); ci != NULL; ci=cf_item_find_next(cs, ci)) { CONF_PAIR *cp; VALUE_PAIR *vp; if (cf_item_is_section(ci)) { cf_log_err(ci, "\"update\" sections cannot have subsections"); return NULL; } if (!cf_item_is_pair(ci)) continue; cp = cf_itemtopair(ci); /* can't return NULL */ vp = cf_pairtovp(cp); if (!vp) { pairfree(&head); cf_log_err(ci, "ERROR: %s", librad_errstr); return NULL; } if ((vp->operator != T_OP_EQ) && (vp->operator != T_OP_CMP_EQ) && (vp->operator != T_OP_ADD) && (vp->operator != T_OP_SUB) && (vp->operator != T_OP_LE) && (vp->operator != T_OP_GE) && (vp->operator != T_OP_SET)) { pairfree(&head); pairfree(&vp); cf_log_err(ci, "Invalid operator for attribute"); return NULL; } /* * A few more sanity checks. The enforcement of * <= or >= can only happen for integer * attributes. */ if ((vp->operator == T_OP_LE) || (vp->operator == T_OP_GE)) { if ((vp->type != PW_TYPE_BYTE) && (vp->type != PW_TYPE_SHORT) && (vp->type != PW_TYPE_INTEGER)) { pairfree(&head); pairfree(&vp); cf_log_err(ci, "Enforcment of <= or >= is possible only for integer attributes"); return NULL; } } *tail = vp; tail = &(vp->next); } if (!head) { cf_log_err(cf_sectiontoitem(cs), "ERROR: update %s section cannot be empty", name2); return NULL; } g = rad_malloc(sizeof(*g)); /* never fails */ memset(g, 0, sizeof(*g)); csingle = mod_grouptocallable(g); csingle->parent = parent; csingle->next = NULL; csingle->name = name2; csingle->type = MOD_UPDATE; csingle->method = component; g->grouptype = GROUPTYPE_SIMPLE; g->children = NULL; g->cs = cs; g->vps = head; return csingle;}static modcallable *do_compile_modswitch(modcallable *parent, int component, CONF_SECTION *cs){ modcallable *csingle; CONF_ITEM *ci; int had_seen_default = FALSE; component = component; /* -Wunused */ if (!cf_section_name2(cs)) { cf_log_err(cf_sectiontoitem(cs), "You must specify a variable to switch over for 'switch'."); return NULL; } if (!cf_item_find_next(cs, NULL)) { cf_log_err(cf_sectiontoitem(cs), "'switch' statments cannot be empty."); return NULL; } /* * Walk through the children of the switch section, * ensuring that they're all 'case' statements */ for (ci=cf_item_find_next(cs, NULL); ci != NULL; ci=cf_item_find_next(cs, ci)) { CONF_SECTION *subcs; const char *name1, *name2; if (!cf_item_is_section(ci)) { if (!cf_item_is_pair(ci)) continue; cf_log_err(ci, "\"switch\" sections can only have \"case\" subsections"); return NULL; } subcs = cf_itemtosection(ci); /* can't return NULL */ name1 = cf_section_name1(subcs); if (strcmp(name1, "case") != 0) { cf_log_err(ci, "\"switch\" sections can only have \"case\" subsections"); return NULL; } name2 = cf_section_name2(subcs); if (!name2 && !had_seen_default) { had_seen_default = TRUE; continue; } if (!name2 || (name2[0] == '\0')) { cf_log_err(ci, "\"case\" sections must have a name"); return NULL; } } csingle= do_compile_modgroup(parent, component, cs, GROUPTYPE_SIMPLE, GROUPTYPE_SIMPLE); if (!csingle) return NULL; csingle->type = MOD_SWITCH; return csingle;}static modcallable *do_compile_modserver(modcallable *parent, int component, CONF_ITEM *ci, const char *name, CONF_SECTION *cs, const char *server){ modcallable *csingle; CONF_SECTION *subcs; modref *mr; subcs = cf_section_sub_find_name2(cs, comp2str[component], NULL); if (!subcs) { cf_log_err(ci, "Server %s has no %s section", server, comp2str[component]); return NULL; } mr = rad_malloc(sizeof(*mr)); memset(mr, 0, sizeof(*mr)); csingle = mod_reftocallable(mr); csingle->parent = parent; csingle->next = NULL; csingle->name = name; csingle->type = MOD_REFERENCE; csingle->method = component; memcpy(csingle->actions, defaultactions[component][GROUPTYPE_SIMPLE], sizeof(csingle->actions)); mr->ref_name = strdup(server); mr->ref_cs = cs; return csingle;}/* * redundant, etc. can refer to modules or groups, but not much else. */static int all_children_are_modules(CONF_SECTION *cs, const char *name){ CONF_ITEM *ci; for (ci=cf_item_find_next(cs, NULL); ci != NULL; ci=cf_item_find_next(cs, ci)) { /* * If we're a redundant, etc. group, then the * intention is to call modules, rather than * processing logic. These checks aren't * *strictly* necessary, but they keep the users * from doing crazy things. */ if (cf_item_is_section(ci)) { CONF_SECTION *subcs = cf_itemtosection(ci); const char *name1 = cf_section_name1(subcs); if ((strcmp(name1, "if") == 0) || (strcmp(name1, "else") == 0) || (strcmp(name1, "elsif") == 0) || (strcmp(name1, "update") == 0) || (strcmp(name1, "switch") == 0) || (strcmp(name1, "case") == 0)) { cf_log_err(ci, "%s sections cannot contain a \"%s\" statement", name, name1); return 0; } continue; } if (cf_item_is_pair(ci)) { CONF_PAIR *cp = cf_itemtopair(ci); if (cf_pair_value(cp) != NULL) { cf_log_err(ci, "Entry with no value is invalid"); return 0; } } } return 1;}/* * Compile one entry of a module call. */static modcallable *do_compile_modsingle(modcallable *parent, int component, CONF_ITEM *ci, int grouptype, const char **modname){ int result; const char *modrefname; modsingle *single; modcallable *csingle; module_instance_t *this; CONF_SECTION *cs, *subcs, *modules; if (cf_item_is_section(ci)) { const char *name2; cs = cf_itemtosection(ci); modrefname = cf_section_name1(cs); name2 = cf_section_name2(cs); if (!name2) name2 = "_UnNamedGroup"; /* * group{}, redundant{}, or append{} may appear * where a single module instance was expected. * In that case, we hand it off to * compile_modgroup */ if (strcmp(modrefname, "group") == 0) { *modname = name2; return do_compile_modgroup(parent, component, cs, GROUPTYPE_SIMPLE, grouptype); } else if (strcmp(modrefname, "redundant") == 0) { *modname = name2; if (!all_children_are_modules(cs, modrefname)) { return NULL; } return do_compile_modgroup(parent, component, cs, GROUPTYPE_REDUNDANT, grouptype); } else if (strcmp(modrefname, "append") == 0) { *modname = name2; return do_compile_modgroup(parent, component, cs, GROUPTYPE_APPEND, grouptype); } else if (strcmp(modrefname, "load-balance") == 0) { *modname = name2; if (!all_children_are_modules(cs, modrefname)) { return NULL; } csingle= do_compile_modgroup(parent, component, cs, GROUPTYPE_SIMPLE, grouptype); if (!csingle) return NULL; csingle->type = MOD_LOAD_BALANCE; return csingle; } else if (strcmp(modrefname, "redundant-load-balance") == 0) { *modname = name2; if (!all_children_are_modules(cs, modrefname)) { return NULL; } csingle= do_compile_modgroup(parent, component, cs, GROUPTYPE_REDUNDANT, grouptype); if (!csingle) return NULL; csingle->type = MOD_REDUNDANT_LOAD_BALANCE; return csingle; } else if (strcmp(modrefname, "if") == 0) { if (!cf_section_name2(cs)) { cf_log_err(ci, "'if' without condition."); return NULL; } *modname = name2; csingle= do_compile_modgroup(parent, component, cs, GROUPTYPE_SIMPLE, grouptype); if (!csingle) return NULL; csingle->type = MOD_IF; if (!radius_evaluate_condition(NULL, 0, 0, modname, FALSE, &result)) { modcallable_free(&csingle); return NULL; } *modname = name2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -