33
33
extern int check_config;
35
35
typedef struct indexed_modcallable {
39
38
modcallable *modulelist;
40
39
} indexed_modcallable;
41
typedef struct virtual_server_t {
47
modcallable *mc[RLM_COMPONENT_COUNT];
48
CONF_SECTION *subcs[RLM_COMPONENT_COUNT];
49
struct virtual_server_t *next;
43
* For each component, keep an ordered list of ones to call.
53
* Keep a hash of virtual servers, so that we can reload them.
45
static rbtree_t *components = NULL;
55
#define VIRTUAL_SERVER_HASH_SIZE (256)
56
static virtual_server_t *virtual_servers[VIRTUAL_SERVER_HASH_SIZE];
47
58
static rbtree_t *module_tree = NULL;
49
60
static rbtree_t *instance_tree = NULL;
62
struct fr_module_hup_t {
63
module_instance_t *mi;
66
fr_module_hup_t *next;
51
70
typedef struct section_type_value_t {
52
71
const char *section;
53
72
const char *typename;
55
74
} section_type_value_t;
59
77
* Ordered by component
66
84
{ "session", "Session-Type", PW_SESSION_TYPE },
67
85
{ "pre-proxy", "Pre-Proxy-Type", PW_PRE_PROXY_TYPE },
68
86
{ "post-proxy", "Post-Proxy-Type", PW_POST_PROXY_TYPE },
69
{ "post-auth", "Post-Auth-Type", PW_POST_AUTH_TYPE },
87
{ "post-auth", "Post-Auth-Type", PW_POST_AUTH_TYPE }
90
{ "recv-coa", "Recv-CoA-Type", PW_RECV_COA_TYPE },
91
{ "send-coa", "Send-CoA-Type", PW_SEND_COA_TYPE }
96
#ifdef WITHOUT_LIBLTDL
104
#define RTLD_LOCAL (0)
107
lt_dlhandle lt_dlopenext(const char *name)
111
strlcpy(buffer, name, sizeof(buffer));
114
* FIXME: Make this configurable...
116
strlcat(buffer, ".so", sizeof(buffer));
118
return dlopen(buffer, RTLD_NOW | RTLD_LOCAL);
121
void *lt_dlsym(lt_dlhandle handle, UNUSED const char *symbol)
123
return dlsym(handle, symbol);
126
int lt_dlclose(lt_dlhandle handle)
128
return dlclose(handle);
131
const char *lt_dlerror(void)
137
#else /* without dlopen */
138
typedef struct lt_dlmodule_t {
143
typedef struct eap_type_t EAP_TYPE;
144
typedef struct rlm_sql_module_t rlm_sql_module_t;
147
* FIXME: Write hackery to auto-generate this data.
148
* We only need to do this on systems that don't have dlopen.
150
extern module_t rlm_pap;
151
extern module_t rlm_chap;
152
extern module_t rlm_eap;
153
extern module_t rlm_sql;
156
extern EAP_TYPE rlm_eap_md5;
157
extern rlm_sql_module_t rlm_sql_mysql;
160
static const lt_dlmodule_t lt_dlmodules[] = {
161
{ "rlm_pap", &rlm_pap },
162
{ "rlm_chap", &rlm_chap },
163
{ "rlm_eap", &rlm_eap },
166
{ "rlm_eap_md5", &rlm_eap_md5 },
169
{ "rlm_sql_mysql", &rlm_sql_mysql },
175
lt_dlhandle lt_dlopenext(const char *name)
179
for (i = 0; lt_dlmodules[i].name != NULL; i++) {
180
if (strcmp(name, lt_dlmodules[i].name) == 0) {
181
return lt_dlmodules[i].ref;
188
void *lt_dlsym(lt_dlhandle handle, UNUSED const char *symbol)
193
int lt_dlclose(lt_dlhandle handle)
198
const char *lt_dlerror(void)
200
return "Unspecified error";
203
#endif /* WITH_DLOPEN */
204
#endif /* WITHOUT_LIBLTDL */
206
static int virtual_server_idx(const char *name)
212
hash = fr_hash_string(name);
214
return hash & (VIRTUAL_SERVER_HASH_SIZE - 1);
217
static void virtual_server_free(virtual_server_t *server)
221
if (server->components) rbtree_free(server->components);
222
server->components = NULL;
227
void virtual_servers_free(time_t when)
230
virtual_server_t **last;
232
for (i = 0; i < VIRTUAL_SERVER_HASH_SIZE; i++) {
233
virtual_server_t *server, *next;
235
last = &virtual_servers[i];
236
for (server = virtual_servers[i];
242
* If we delete it, fix the links so that
243
* we don't orphan anything. Also,
244
* delete it if it's old, AND a newer one
247
* Otherwise, the last pointer gets set to
248
* the one we didn't delete.
251
((server->created < when) && server->can_free)) {
252
*last = server->next;
253
virtual_server_free(server);
255
last = &(server->next);
72
261
static void indexed_modcallable_free(void *data)
430
649
int indexed_modcall(int comp, int idx, REQUEST *request)
433
indexed_modcallable *this;
434
652
modcallable *list = NULL;
436
this = lookup_by_index(request->server, comp, idx);
438
if (idx != 0) DEBUG2(" WARNING: Unknown value specified for %s. Cannot perform requested action.",
439
section_type_value[comp].typename);
653
virtual_server_t *server;
656
* Hack to find the correct virtual server.
658
rcode = virtual_server_idx(request->server);
659
for (server = virtual_servers[rcode];
661
server = server->next) {
662
if (!request->server && !server->name) break;
664
if ((request->server && server->name) &&
665
(strcmp(request->server, server->name) == 0)) break;
669
RDEBUG("No such virtual server %s", request->server);
670
return RLM_MODULE_FAIL;
674
list = server->mc[comp];
675
if (!list) RDEBUG2(" WARNING: Empty section. Using default return values.");
441
list = this->modulelist;
678
indexed_modcallable *this;
680
this = lookup_by_index(server->components, comp, idx);
682
list = this->modulelist;
684
RDEBUG2(" WARNING: Unknown value specified for %s. Cannot perform requested action.",
685
section_type_value[comp].typename);
444
689
request->component = section_type_value[comp].section;
446
691
rcode = modcall(comp, list, request);
448
request->module = "<server-core>";
449
request->component = "<server-core>";
693
request->module = "";
694
request->component = "";
672
917
static int load_byserver(CONF_SECTION *cs)
675
const char *server = cf_section_name2(cs);
920
const char *name = cf_section_name2(cs);
921
rbtree_t *components;
922
virtual_server_t *server = NULL;
923
indexed_modcallable *c;
926
cf_log_info(cs, "server %s {", name);
928
cf_log_info(cs, "server {");
677
931
cf_log_info(cs, " modules {");
933
components = rbtree_create(indexed_modcallable_cmp,
934
indexed_modcallable_free, 0);
936
radlog(L_ERR, "Failed to initialize components\n");
940
server = rad_malloc(sizeof(*server));
941
memset(server, 0, sizeof(*server));
944
server->created = time(NULL);
946
server->components = components;
680
949
* Define types first.
759
1032
cf_log_module(cs, "Checking %s {...} for more modules to load",
760
1033
section_type_value[comp].section);
762
if (load_component_section(subcs, server, comp) < 0) {
763
cf_log_info(cs, " }");
1037
* Skip pre/post-proxy sections if we're not
1040
if (!mainconfig.proxy_requests &&
1041
((comp == PW_PRE_PROXY_TYPE) ||
1042
(comp == PW_PRE_PROXY_TYPE))) {
1047
if (load_component_section(subcs, components, comp) < 0) {
1052
* Cache a default, if it exists. Some people
1053
* put empty sections for some reason...
1055
c = lookup_by_index(components, comp, 0);
1056
if (c) server->mc[comp] = c->modulelist;
1058
server->subcs[comp] = subcs;
767
1061
} /* loop over components */
790
1087
const DICT_ATTR *dattr;
792
1089
dattr = dict_attrbyname("DHCP-Message-Type");
794
radlog(L_ERR, "No DHCP-Message-Type attribute");
799
1092
* Handle each DHCP Message type separately.
801
for (subcs = cf_subsection_find_next(cs, NULL,
804
subcs = cf_subsection_find_next(cs, subcs,
1094
if (dattr) for (subcs = cf_subsection_find_next(cs, NULL, "dhcp");
1096
subcs = cf_subsection_find_next(cs, subcs,
806
1098
const char *name2 = cf_section_name2(subcs);
808
1100
DEBUG2(" Module: Checking dhcp %s {...} for more modules to load", name2);
809
1101
if (!load_subcomponent_section(NULL, subcs,
812
1104
RLM_COMPONENT_POST_AUTH)) {
813
return -1; /* FIXME: memleak? */
1105
goto error; /* FIXME: memleak? */
1107
c = lookup_by_index(components,
1108
RLM_COMPONENT_POST_AUTH, 0);
1109
if (c) server->mc[RLM_COMPONENT_POST_AUTH] = c->modulelist;
821
cf_log_info(cs, " }");
1116
cf_log_info(cs, " } # modules");
1117
cf_log_info(cs, "} # server");
823
if (!flag && server) {
1119
if (!flag && name) {
824
1120
DEBUG("WARNING: Server %s is empty, and will do nothing!",
1124
if (debug_flag == 0) {
1125
radlog(L_INFO, "Loaded virtual server %s",
1126
(name != NULL) ? name : "<default>");
1130
* Now that it is OK, insert it into the list.
1132
* This is thread-safe...
1134
comp = virtual_server_idx(name);
1135
server->next = virtual_servers[comp];
1136
virtual_servers[comp] = server;
1139
* Mark OLDER ones of the same name as being unused.
1141
server = server->next;
1143
if ((!name && !server->name) ||
1144
(name && server->name &&
1145
(strcmp(server->name, name) == 0))) {
1146
server->can_free = TRUE;
1149
server = server->next;
1157
* Load all of the virtual servers.
1159
int virtual_servers_load(CONF_SECTION *config)
1161
int null_server = FALSE;
1163
static int first_time = TRUE;
1165
DEBUG2("%s: #### Loading Virtual Servers ####", mainconfig.name);
1168
* Load all of the virtual servers.
1170
for (cs = cf_subsection_find_next(config, NULL, "server");
1172
cs = cf_subsection_find_next(config, cs, "server")) {
1173
if (!cf_section_name2(cs)) null_server = TRUE;
1175
if (load_byserver(cs) < 0) {
1177
* Once we successfully staryed once,
1178
* continue loading the OTHER servers,
1179
* even if one fails.
1181
if (!first_time) continue;
1187
* No empty server defined. Try to load an old-style
1188
* one for backwards compatibility.
1191
if (load_byserver(config) < 0) {
1197
* If we succeed the first time around, remember that.
1204
int module_hup_module(CONF_SECTION *cs, module_instance_t *node, time_t when)
1206
void *insthandle = NULL;
1207
fr_module_hup_t *mh;
1210
!node->entry->module->instantiate ||
1211
((node->entry->module->type & RLM_TYPE_HUP_SAFE) == 0)) {
1215
cf_log_module(cs, "Trying to reload module \"%s\"", node->name);
1217
if ((node->entry->module->instantiate)(cs, &insthandle) < 0) {
1218
cf_log_err(cf_sectiontoitem(cs),
1219
"HUP failed for module \"%s\". Using old configuration.",
1224
radlog(L_INFO, " Module: Reloaded module \"%s\"", node->name);
1226
module_instance_free_old(cs, node, when);
1229
* Save the old instance handle for later deletion.
1231
mh = rad_malloc(sizeof(*mh));
1234
mh->insthandle = node->insthandle;
1235
mh->next = node->mh;
1238
node->insthandle = insthandle;
1241
* FIXME: Set a timeout to come back in 60s, so that
1242
* we can pro-actively clean up the old instances.
871
1278
strlcpy(myNode.name, instname, sizeof(myNode.name));
872
1279
node = rbtree_finddata(instance_tree, &myNode);
874
!node->entry->module->instantiate ||
875
((node->entry->module->type & RLM_TYPE_HUP_SAFE) == 0)) {
879
cf_log_module(cs, "Trying to reload module \"%s\"", node->name);
881
if ((node->entry->module->instantiate)(cs, &insthandle) < 0) {
882
cf_log_err(cf_sectiontoitem(cs),
883
"HUP failed for module \"%s\". Using old configuration.",
888
radlog(L_INFO, " Module: Reloaded module \"%s\"", node->name);
891
* Free all configurations old enough to be
892
* deleted. This is slightly wasteful, but easy
895
* We permit HUPs every 5s, and we cache the last
896
* 16 configurations. So the current entry at
897
* insthandle_counter will either be empty, OR will
898
* be at least (5*16) = 80s old. The following check
899
* ensures that it will be deleted.
901
for (i = 0; i < 16; i++) {
902
if ((int) (when - hup_times[insthandle_counter]) < 60)
905
if (!node->old_insthandle[i]) continue;
907
cf_section_parse_free(cs, node->old_insthandle[i]);
909
if (node->entry->module->detach) {
910
(node->entry->module->detach)(node->old_insthandle[i]);
912
node->old_insthandle[i] = NULL;
916
* Save the old instance handle for later deletion.
918
node->old_insthandle[insthandle_counter] = node->insthandle;
919
node->insthandle = insthandle;
922
* FIXME: Set a timeout to come back in 60s, so that
923
* we can pro-actively clean up the old instances.
1281
module_hup_module(cs, node, when);
928
* Remember when we were last HUP'd.
930
hup_times[insthandle_counter] = when;
931
insthandle_counter++;
932
insthandle_counter &= 0x0f;
1307
* This line works around a completely
1309
* RIDICULOUS INSANE IDIOTIC
1311
* bug in libltdl on certain systems. The "set
1312
* preloaded symbols" macro below ends up
1313
* referencing this name, but it isn't defined
1314
* anywhere in the libltdl source. As a result,
1315
* any program STUPID enough to rely on libltdl
1316
* fails to link, because the symbol isn't
1319
* It's like libtool and libltdl are some kind
1322
#ifdef IE_LIBTOOL_DIE
1323
#define lt__PROGRAM__LTX_preloaded_symbols lt_libltdl_LTX_preloaded_symbols
958
1327
* Set the default list of preloaded symbols.
959
1328
* This is used to initialize libltdl's list of
960
1329
* preloaded modules.
1078
DEBUG2("%s: #### Loading Virtual Servers ####", mainconfig.name);
1081
* Load all of the virtual servers.
1083
for (cs = cf_subsection_find_next(config, NULL, "server");
1085
cs = cf_subsection_find_next(config, cs, "server")) {
1086
const char *name2 = cf_section_name2(cs);
1089
cf_log_info(cs, "server %s {", name2);
1091
cf_log_info(cs, "server {");
1094
if (load_byserver(cs) < 0) {
1095
cf_log_info(cs, "}");
1098
cf_log_info(cs, "}");
1102
* No empty server defined. Try to load an old-style
1103
* one for backwards compatibility.
1106
cf_log_info(cs, "server {");
1107
if (load_byserver(config) < 0) {
1108
cf_log_info(cs, "}");
1111
cf_log_info(cs, "}");
1442
if (virtual_servers_load(config) < 0) return -1;