📄 modules.c
字号:
* Try to compile one entry. */ this = compile_modsingle(NULL, comp, modref, &modname); if (!this) { cf_log_err(cf_sectiontoitem(cs), "Errors parsing %s section.\n", cf_section_name1(cs)); return -1; } /* * Look for Auth-Type foo {}, which are special * cases of named sections, and allowable ONLY * at the top-level. * * i.e. They're not allowed in a "group" or "redundant" * subsection. */ if (comp == RLM_COMPONENT_AUTH) { DICT_VALUE *dval; const char *modrefname = NULL; if (cp) { modrefname = cf_pair_attr(cp); } else { modrefname = cf_section_name2(scs); if (!modrefname) { modcallable_free(&this); cf_log_err(cf_sectiontoitem(cs), "Errors parsing %s sub-section.\n", cf_section_name1(scs)); return -1; } } dval = dict_valbyname(PW_AUTH_TYPE, modrefname); if (!dval) { /* * It's a section, but nothing we * recognize. Die! */ modcallable_free(&this); cf_log_err(cf_sectiontoitem(cs), "Unknown Auth-Type \"%s\" in %s sub-section.", modrefname, section_type_value[comp].section); return -1; } idx = dval->value; } else { /* See the comment in new_sublist() for explanation * of the special index 0 */ idx = 0; } subcomp = new_sublist(server, comp, idx); if (subcomp == NULL) { modcallable_free(&this); continue; } /* If subcomp->modulelist is NULL, add_to_modcallable will * create it */ visiblename = cf_section_name2(cs); if (visiblename == NULL) visiblename = cf_section_name1(cs); add_to_modcallable(&subcomp->modulelist, this, comp, visiblename); } return 0;}static int load_byserver(CONF_SECTION *cs){ int comp, flag; const char *server = cf_section_name2(cs); cf_log_info(cs, " modules {"); /* * Define types first. */ for (comp = 0; comp < RLM_COMPONENT_COUNT; ++comp) { CONF_SECTION *subcs; CONF_ITEM *modref; DICT_ATTR *dattr; subcs = cf_section_sub_find(cs, section_type_value[comp].section); if (!subcs) continue; if (cf_item_find_next(subcs, NULL) == NULL) continue; /* * Find the attribute used to store VALUEs for this section. */ dattr = dict_attrbyvalue(section_type_value[comp].attr); if (!dattr) { cf_log_err(cf_sectiontoitem(subcs), "No such attribute %s", section_type_value[comp].typename); cf_log_info(cs, " }"); return -1; } /* * Define dynamic types, so that others can reference * them. */ for (modref = cf_item_find_next(subcs, NULL); modref != NULL; modref = cf_item_find_next(subcs, modref)) { const char *name1; CONF_SECTION *subsubcs; /* * Create types for simple references * only when parsing the authenticate * section. */ if ((section_type_value[comp].attr == PW_AUTH_TYPE) && cf_item_is_pair(modref)) { CONF_PAIR *cp = cf_itemtopair(modref); if (!define_type(dattr, cf_pair_attr(cp))) { return -1; } continue; } if (!cf_item_is_section(modref)) continue; subsubcs = cf_itemtosection(modref); name1 = cf_section_name1(subsubcs); if (strcmp(name1, section_type_value[comp].typename) == 0) { if (!define_type(dattr, cf_section_name2(subsubcs))) { cf_log_info(cs, " }"); return -1; } } } } /* loop over components */ /* * Loop over all of the known components, finding their * configuration section, and loading it. */ flag = 0; for (comp = 0; comp < RLM_COMPONENT_COUNT; ++comp) { CONF_SECTION *subcs; subcs = cf_section_sub_find(cs, section_type_value[comp].section); if (!subcs) continue; if (cf_item_find_next(subcs, NULL) == NULL) continue; cf_log_module(cs, "Checking %s {...} for more modules to load", section_type_value[comp].section); if (load_component_section(subcs, server, comp) < 0) { cf_log_info(cs, " }"); return -1; } flag = 1; } /* loop over components */ /* * We haven't loaded any of the normal sections. Maybe we're * supposed to load the vmps section. * * This is a bit of a hack... */ if (!flag) { CONF_SECTION *subcs; subcs = cf_section_sub_find(cs, "vmps"); if (subcs) { cf_log_module(cs, "Checking vmps {...} for more modules to load"); if (load_component_section(subcs, server, RLM_COMPONENT_POST_AUTH) < 0) { return -1; } flag = 1; }#ifdef WITH_DHCP if (!flag) { const DICT_ATTR *dattr; dattr = dict_attrbyname("DHCP-Message-Type"); if (!dattr) { radlog(L_ERR, "No DHCP-Message-Type attribute"); return -1; } /* * Handle each DHCP Message type separately. */ for (subcs = cf_subsection_find_next(cs, NULL, "dhcp"); subcs != NULL; subcs = cf_subsection_find_next(cs, subcs, "dhcp")) { const char *name2 = cf_section_name2(subcs); DEBUG2(" Module: Checking dhcp %s {...} for more modules to load", name2); if (!load_subcomponent_section(NULL, subcs, server, dattr->attr, RLM_COMPONENT_POST_AUTH)) { return -1; /* FIXME: memleak? */ } flag = 1; } }#endif } cf_log_info(cs, " }"); if (!flag && server) { DEBUG("WARNING: Server %s is empty, and will do nothing!", server); } return 0;}int module_hup(CONF_SECTION *modules){ time_t when; CONF_ITEM *ci; CONF_SECTION *cs; module_instance_t *node; static int insthandle_counter = -1; static time_t hup_times[16]; if (!modules) return 0; if (insthandle_counter < 0) { memset(hup_times, 0, sizeof(hup_times)); insthandle_counter = 0; } when = time(NULL); /* * Loop over the modules */ for (ci=cf_item_find_next(modules, NULL); ci != NULL; ci=cf_item_find_next(modules, ci)) { int i; void *insthandle = NULL; const char *instname; module_instance_t myNode; /* * If it's not a section, ignore it. */ if (!cf_item_is_section(ci)) continue; cs = cf_itemtosection(ci); instname = cf_section_name2(cs); if (!instname) instname = cf_section_name1(cs); strlcpy(myNode.name, instname, sizeof(myNode.name)); node = rbtree_finddata(instance_tree, &myNode); if (!node || !node->entry->module->instantiate || ((node->entry->module->type & RLM_TYPE_HUP_SAFE) == 0)) { continue; } cf_log_module(cs, "Trying to reload module \"%s\"", node->name); if ((node->entry->module->instantiate)(cs, &insthandle) < 0) { cf_log_err(cf_sectiontoitem(cs), "HUP failed for module \"%s\". Using old configuration.", node->name); continue; } radlog(L_INFO, " Module: Reloaded module \"%s\"", node->name); /* * Free all configurations old enough to be * deleted. This is slightly wasteful, but easy * to do. * * We permit HUPs every 5s, and we cache the last * 16 configurations. So the current entry at * insthandle_counter will either be empty, OR will * be at least (5*16) = 80s old. The following check * ensures that it will be deleted. */ for (i = 0; i < 16; i++) { if ((int) (when - hup_times[insthandle_counter]) < 60) continue; if (!node->old_insthandle[i]) continue; cf_section_parse_free(cs, node->old_insthandle[i]); if (node->entry->module->detach) { (node->entry->module->detach)(node->old_insthandle[i]); } node->old_insthandle[i] = NULL; } /* * Save the old instance handle for later deletion. */ node->old_insthandle[insthandle_counter] = node->insthandle; node->insthandle = insthandle; /* * FIXME: Set a timeout to come back in 60s, so that * we can pro-actively clean up the old instances. */ } /* * Remember when we were last HUP'd. */ hup_times[insthandle_counter] = when; insthandle_counter++; insthandle_counter &= 0x0f; return 1;}/* * Parse the module config sections, and load * and call each module's init() function. * * Libtool makes your life a LOT easier, especially with libltdl. * see: http://www.gnu.org/software/libtool/ */int setup_modules(int reload, CONF_SECTION *config){ CONF_SECTION *cs, *modules; rad_listen_t *listener; int null_server = FALSE; if (reload) return 0; /* * If necessary, initialize libltdl. */ if (!reload) { /* * Set the default list of preloaded symbols. * This is used to initialize libltdl's list of * preloaded modules. * * i.e. Static modules. */ LTDL_SET_PRELOADED_SYMBOLS(); if (lt_dlinit() != 0) { radlog(L_ERR, "Failed to initialize libraries: %s\n", lt_dlerror()); return -1; } /* * Set the search path to ONLY our library directory. * This prevents the modules from being found from * any location on the disk. */ lt_dlsetsearchpath(radlib_dir); /* * Set up the internal module struct. */ module_tree = rbtree_create(module_entry_cmp, module_entry_free, 0); if (!module_tree) { radlog(L_ERR, "Failed to initialize modules\n"); return -1; } instance_tree = rbtree_create(module_instance_cmp, module_instance_free, 0); if (!instance_tree) { radlog(L_ERR, "Failed to initialize modules\n"); return -1; } } components = rbtree_create(indexed_modcallable_cmp, indexed_modcallable_free, 0); if (!components) { radlog(L_ERR, "Failed to initialize components\n"); return -1; } /* * Remember where the modules were stored. */ modules = cf_section_sub_find(config, "modules"); if (!modules) { radlog(L_ERR, "Cannot find a \"modules\" section in the configuration file!"); return -1; } DEBUG2("%s: #### Instantiating modules ####", mainconfig.name); /* * Look for the 'instantiate' section, which tells us * the instantiation order of the modules, and also allows * us to load modules with no authorize/authenticate/etc. * sections. */ cs = cf_section_sub_find(config, "instantiate"); if (cs != NULL) { CONF_ITEM *ci; CONF_PAIR *cp; module_instance_t *module; const char *name; cf_log_info(cs, " instantiate {"); /* * Loop over the items in the 'instantiate' section. */ for (ci=cf_item_find_next(cs, NULL); ci != NULL; ci=cf_item_find_next(cs, ci)) { /* * Skip sections and "other" stuff. * Sections will be handled later, if * they're referenced at all... */ if (!cf_item_is_pair(ci)) { continue; } cp = cf_itemtopair(ci); name = cf_pair_attr(cp); module = find_module_instance(modules, name); if (!module) { return -1; } } /* loop over items in the subsection */ cf_log_info(cs, " }"); } /* if there's an 'instantiate' section. */ /* * Loop over the listeners, figuring out which sections * to load. */ for (listener = mainconfig.listen; listener != NULL; listener = listener->next) { char buffer[256]; if (listener->type == RAD_LISTEN_PROXY) continue; cs = cf_section_sub_find_name2(config, "server", listener->server); if (!cs && (listener->server != NULL)) { listener->print(listener, buffer, sizeof(buffer)); radlog(L_ERR, "No server has been defined for %s", buffer); return -1; } } DEBUG2("%s: #### Loading Virtual Servers ####", mainconfig.name); /* * Load all of the virtual servers. */ for (cs = cf_subsection_find_next(config, NULL, "server"); cs != NULL; cs = cf_subsection_find_next(config, cs, "server")) { const char *name2 = cf_section_name2(cs); if (name2) { cf_log_info(cs, "server %s {", name2); } else { cf_log_info(cs, "server {"); null_server = TRUE; } if (load_byserver(cs) < 0) { cf_log_info(cs, "}"); return -1; } cf_log_info(cs, "}"); } /* * No empty server defined. Try to load an old-style * one for backwards compatibility. */ if (!null_server) { cf_log_info(cs, "server {"); if (load_byserver(config) < 0) { cf_log_info(cs, "}"); return -1; } cf_log_info(cs, "}"); } return 0;}/* * Call all authorization modules until one returns * somethings else than RLM_MODULE_OK */int module_authorize(int autz_type, REQUEST *request){ return indexed_modcall(RLM_COMPONENT_AUTZ, autz_type, request);}/* * Authenticate a user/password with various methods. */int module_authenticate(int auth_type, REQUEST *request){ return indexed_modcall(RLM_COMPONENT_AUTH, auth_type, request);}/* * Do pre-accounting for ALL configured sessions */int module_preacct(REQUEST *request){ return indexed_modcall(RLM_COMPONENT_PREACCT, 0, request);}/* * Do accounting for ALL configured sessions */int module_accounting(int acct_type, REQUEST *request){ return indexed_modcall(RLM_COMPONENT_ACCT, acct_type, request);}/* * See if a user is already logged in. * * Returns: 0 == OK, 1 == double logins, 2 == multilink attempt */int module_checksimul(int sess_type, REQUEST *request, int maxsimul){ int rcode; if(!request->username) return 0; request->simul_count = 0; request->simul_max = maxsimul; request->simul_mpp = 1; rcode = indexed_modcall(RLM_COMPONENT_SESS, sess_type, request); if (rcode != RLM_MODULE_OK) { /* FIXME: Good spot for a *rate-limited* warning to the log */ return 0; } return (request->simul_count < maxsimul) ? 0 : request->simul_mpp;}/* * Do pre-proxying for ALL configured sessions */int module_pre_proxy(int type, REQUEST *request){ return indexed_modcall(RLM_COMPONENT_PRE_PROXY, type, request);}/* * Do post-proxying for ALL configured sessions */int module_post_proxy(int type, REQUEST *request){ return indexed_modcall(RLM_COMPONENT_POST_PROXY, type, request);}/* * Do post-authentication for ALL configured sessions */int module_post_auth(int postauth_type, REQUEST *request){ return indexed_modcall(RLM_COMPONENT_POST_AUTH, postauth_type, request);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -