}
RDEBUG("server %s {", cf_section_name2(unlang_call_current(request)));
- request->async->process(&final, &(module_ctx_t){ .inst = dl_module_instance_by_data(request->async->process_inst) }, request);
+ request->async->process(&final,
+ MODULE_CTX(dl_module_instance_by_data(request->async->process_inst), NULL, NULL),
+ request);
RDEBUG("} # server %s", cf_section_name2(unlang_call_current(request)));
fr_cond_assert(final == RLM_MODULE_OK);
* @copyright 2016-2019 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
*/
RCSID("$Id$")
+#define _DL_MODULE_PRIVATE 1
+#include <freeradius-devel/server/dl_module.h>
+
#include <freeradius-devel/server/log.h>
#include <freeradius-devel/util/debug.h>
#include <ctype.h>
#include <unistd.h>
-#define _DL_MODULE_PRIVATE 1
-#include <freeradius-devel/server/dl_module.h>
-
#define DL_INIT_CHECK fr_assert(dl_module_loader)
/** Wrapper struct around dl_loader_t
}
DEBUG4("Worker alloced %s thread instance data (%p/%p)", ti->mi->module->name, ti, ti->data);
- if (mi->module->thread_instantiate) {
- if (mi->module->thread_instantiate(&(module_thread_inst_ctx_t){
- .inst = mi->dl_inst,
- .thread = ti->data,
- .el = el
- }) < 0) {
- PERROR("Thread instantiation failed for module \"%s\"", mi->name);
- TALLOC_FREE(module_thread_inst_array);
- return -1;
- }
+ if (mi->module->thread_instantiate &&
+ mi->module->thread_instantiate(MODULE_THREAD_INST_CTX(mi->dl_inst, ti->data, el)) < 0) {
+ PERROR("Thread instantiation failed for module \"%s\"", mi->name);
+ TALLOC_FREE(module_thread_inst_array);
+ return -1;
}
fr_assert(mi->number < talloc_array_length(module_thread_inst_array));
/*
* Call the module's instantiation routine.
*/
- if ((mi->module->instantiate)(&(module_inst_ctx_t){
- .inst = mi->dl_inst
- }) < 0) {
- cf_log_err(mi->dl_inst->conf, "Instantiation failed for module \"%s\"",
- mi->name);
+ if (mi->module->instantiate(MODULE_INST_CTX(mi->dl_inst)) < 0) {
+ cf_log_err(mi->dl_inst->conf, "Instantiation failed for module \"%s\"", mi->name);
return -1;
}
if (mi->module->bootstrap) {
cf_log_debug(mi->dl_inst->conf, "Bootstrapping module \"%s\"", mi->name);
- if ((mi->module->bootstrap)(&(module_inst_ctx_t){
- .inst = mi->dl_inst,
- }) < 0) {
+ if (mi->module->bootstrap(MODULE_INST_CTX(mi->dl_inst)) < 0) {
cf_log_err(cs, "Bootstrap failed for module \"%s\"", mi->name);
talloc_free(mi);
return NULL;
#include <freeradius-devel/server/cf_util.h>
#include <freeradius-devel/server/request.h>
+#include <freeradius-devel/server/module_ctx.h>
#include <freeradius-devel/unlang/action.h>
#include <freeradius-devel/unlang/compile.h>
#include <freeradius-devel/util/event.h>
typedef struct module_method_names_s module_method_names_t;
typedef struct module_instance_s module_instance_t;
typedef struct module_thread_instance_s module_thread_instance_t;
-typedef struct module_ctx_s module_ctx_t;
-typedef struct module_inst_ctx_s module_inst_ctx_t;
-typedef struct module_thread_inst_ctx_s module_thread_inst_ctx_t;
#define RLM_TYPE_THREAD_SAFE (0 << 0) //!< Module is threadsafe.
#define RLM_TYPE_THREAD_UNSAFE (1 << 0) //!< Module is not threadsafe.
module_method_t func; //!< State function.
} module_state_func_table_t;
-/** Temporary structure to hold arguments for module calls
- *
- */
-struct module_ctx_s {
- dl_module_inst_t const *inst; //!< Dynamic loader API handle for the module.
- void *thread; //!< Thread specific instance data.
- void *rctx; //!< Resume ctx that a module previously set.
-};
-
-/** Temporary structure to hold arguments for instantiation calls
- *
- */
-struct module_inst_ctx_s {
- dl_module_inst_t const *inst; //!< Dynamic loader API handle for the module.
-};
-
-/** Temporary structure to hold arguments for thread_instantiation calls
- *
- */
-struct module_thread_inst_ctx_s {
- dl_module_inst_t const *inst; //!< Dynamic loader API handle for the module.
- ///< Must come first to allow cast between
- ///< module_inst_ctx.
- void *thread; //!< Thread instance data.
- fr_event_list_t *el; //!< Event list to register any IO handlers
- ///< and timers against.
-};
/** @name Convenience wrappers around other internal APIs to make them easier to instantiate with modules
*
--- /dev/null
+#pragma once
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * $Id$
+ *
+ * @file lib/server/module_call_ctx.h
+ * @brief Temporary argument structures for module calls.
+ *
+ * These get used in various places where we may not want to include
+ * the full module.h.
+ *
+ * @copyright 2021 Arran Cudbard-bell <a.cudbardb@freeradius.org>
+ */
+RCSIDH(module_ctx_h, "$Id$")
+
+#include <freeradius-devel/server/dl_module.h>
+#include <freeradius-devel/util/event.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Temporary structure to hold arguments for module calls
+ *
+ */
+typedef struct {
+ dl_module_inst_t const *inst; //!< Dynamic loader API handle for the module.
+ void *thread; //!< Thread specific instance data.
+ void *rctx; //!< Resume ctx that a module previously set.
+} module_ctx_t;
+
+/** Temporary structure to hold arguments for instantiation calls
+ *
+ */
+typedef struct {
+ dl_module_inst_t const *inst; //!< Dynamic loader API handle for the module.
+} module_inst_ctx_t;
+
+/** Temporary structure to hold arguments for thread_instantiation calls
+ *
+ */
+typedef struct {
+ dl_module_inst_t const *inst; //!< Dynamic loader API handle for the module.
+ ///< Must come first to allow cast between
+ ///< module_inst_ctx.
+ void *thread; //!< Thread instance data.
+ fr_event_list_t *el; //!< Event list to register any IO handlers
+ ///< and timers against.
+} module_thread_inst_ctx_t;
+
+DIAG_OFF(unused-function)
+/** Allocate a module calling ctx on the heap based on an instance ctx
+ *
+ */
+static module_ctx_t *module_ctx_from_inst(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx)
+{
+ module_ctx_t *nmctx;
+
+ MEM(nmctx = talloc_zero(ctx, module_ctx_t));
+ nmctx->inst = mctx->inst;
+
+ return nmctx;
+}
+
+/** Allocate a module calling ctx on the heap based on an instance ctx
+ *
+ */
+static module_ctx_t *module_ctx_from_thread_inst(TALLOC_CTX *ctx, module_thread_inst_ctx_t const *mctx)
+{
+ module_ctx_t *nmctx;
+
+ MEM(nmctx = talloc_zero(ctx, module_ctx_t));
+ nmctx->inst = mctx->inst;
+ nmctx->thread = mctx->thread;
+
+ return nmctx;
+}
+
+/** Duplicate a stack based module_ctx_t on the heap
+ *
+ */
+static module_ctx_t *module_ctx_dup(TALLOC_CTX *ctx, module_ctx_t const *mctx)
+{
+ module_ctx_t *nmctx;
+
+ nmctx = talloc_zero(ctx, module_ctx_t);
+ memcpy(nmctx, mctx, sizeof(*nmctx));
+
+ return nmctx;
+}
+DIAG_ON(unused-function)
+
+/** Wrapper to create a module_ctx_t as a compound literal
+ *
+ * This is used so that the compiler will flag any uses of (module_ctx_t)
+ * which don't set the required fields. Additional arguments should be added
+ * to this macro whenever the module_ctx_t fields are altered.
+ *
+ * @param[in] _dl_inst of the module being called.
+ * @param[in] _thread instance of the module being called.
+ * @param[in] _rctx Resume ctx (if any).
+ */
+#define MODULE_CTX(_dl_inst, _thread, _rctx) &(module_ctx_t){ .inst = _dl_inst, .thread = _thread, .rctx = _rctx }
+
+/** Wrapper to create a module_ctx_t as a compound literal from a module_inst_ctx_t
+ *
+ * This is used so that the compiler will flag any uses of (module_ctx_t)
+ * which don't set the required fields. Additional arguments should be added
+ * to this macro whenever the module_ctx_t fields are altered.
+ *
+ * @param[in] _mctx to copy fields from.
+ */
+#define MODULE_CTX_FROM_INST(_mctx) &(module_ctx_t){ .inst = (_mctx)->inst }
+
+/** Wrapper to create a module_ctx_t as a compound literal from a module_inst_ctx_t
+ *
+ * This is used so that the compiler will flag any uses of (module_ctx_t)
+ * which don't set the required fields. Additional arguments should be added
+ * to this macro whenever the module_ctx_t fields are altered.
+ *
+ * @param[in] _mctx to copy fields from.
+ */
+#define MODULE_CTX_FROM_THREAD_INST(_mctx) &(module_ctx_t){ .inst = (_mctx)->inst, .thread = (_mctx)->thread }
+
+/** Wrapper to create a module_inst_ctx_t as a compound literal
+ *
+ * This is used so that the compiler will flag any uses of (module_inst_ctx_t)
+ * which don't set the required fields. Additional arguments should be added
+ * to this macro whenever the module_inst_ctx_t fields are altered.
+ *
+ * @param[in] _dl_inst of the module being called..
+ */
+#define MODULE_INST_CTX(_dl_inst) &(module_inst_ctx_t){ .inst = _dl_inst }
+
+/** Wrapper to create a module_thread_inst_ctx_t as a compound literal
+ *
+ * This is used so that the compiler will flag any uses of (module_thread_inst_ctx_t)
+ * which don't set the required fields. Additional arguments should be added
+ * to this macro whenever the module_thread_inst_ctx_t fields are altered.
+ *
+ * @param[in] _dl_inst of the module being called.
+ * @param[in] _thread instance of the module being called.
+ * @param[in] _el Thread specific event list.
+ */
+#define MODULE_THREAD_INST_CTX(_dl_inst, _thread, _el) &(module_thread_inst_ctx_t){ .inst = _dl_inst, .thread = _thread, .el = _el }
+
+/** Wrapper to create a module_inst_ctx_t as a comound listeral from a module_thread_ctx_t
+ *
+ * Extract the dl_module_inst_t from a module_thread_inst_ctx_t.
+ *
+ * @param[in] _mctx to extract module_thread_inst_ctx_t from.
+ */
+#define MODULE_THREAD_INST_CTX_FROM_INST_CTX(_mctx) &(module_ctx_t){ .inst = (_mctx)->inst }
+
+#ifdef __cplusplus
+}
+#endif
fr_process_module_t const *process = (fr_process_module_t const *) dl_inst->module->common;
if (process->instantiate &&
- (process->instantiate(&(module_inst_ctx_t){
- .inst = dl_inst
- }) < 0)) {
+ (process->instantiate(MODULE_INST_CTX(dl_inst)) < 0)) {
cf_log_err(dl_inst->conf, "Instantiate failed");
return -1;
}
fr_process_module_t const *process = (fr_process_module_t const *) dl_inst->module->common;
if (process->bootstrap &&
- (process->bootstrap(&(module_inst_ctx_t){
- .inst = dl_inst
- }) < 0)) {
+ (process->bootstrap(MODULE_INST_CTX(dl_inst)) < 0)) {
cf_log_err(dl_inst->conf, "Bootstrap failed");
return -1;
}
fr_assert(ev->fd == fd);
- ev->fd_read(&(module_ctx_t){
- .inst = ev->dl_inst,
- .thread = ev->thread,
- .rctx = UNCONST(void *, ev->ctx) },
- ev->request, fd);
+ ev->fd_read(MODULE_CTX(ev->dl_inst, ev->thread, UNCONST(void *, ev->ctx)), ev->request, fd);
}
/** Frees an unlang event, removing it from the request's event loop
{
unlang_module_event_t *ev = talloc_get_type_abort(ctx, unlang_module_event_t);
- ev->timeout(&(module_ctx_t){
- .inst = ev->dl_inst,
- .thread = ev->thread,
- .rctx = UNCONST(void *, ev->ctx)
- }, ev->request, now);
+ ev->timeout(MODULE_CTX(ev->dl_inst, ev->thread, UNCONST(void *, ev->ctx)), ev->request, now);
talloc_free(ev);
}
unlang_module_event_t *ev = talloc_get_type_abort(ctx, unlang_module_event_t);
fr_assert(ev->fd == fd);
- ev->fd_write(&(module_ctx_t){
- .inst = ev->dl_inst,
- .thread = ev->thread,
- .rctx = UNCONST(void *, ev->ctx) },
- ev->request, fd);
+ ev->fd_write(MODULE_CTX(ev->dl_inst, ev->thread, UNCONST(void *, ev->ctx)), ev->request, fd);
}
/** Call the callback registered for an I/O error event
fr_assert(ev->fd == fd);
- ev->fd_error(&(module_ctx_t){
- .inst = ev->dl_inst,
- .thread = ev->thread,
- .rctx = UNCONST(void *, ev->ctx)
- }, ev->request, fd);
+ ev->fd_error(MODULE_CTX(ev->dl_inst, ev->thread, UNCONST(void *, ev->ctx)), ev->request, fd);
}
stack->result = frame->result = default_rcode;
return resume(p_result,
- &(module_ctx_t){
- .inst = mc->instance->dl_inst,
- .thread = module_thread(mc->instance)->data,
- .rctx = rctx
- }, request);
+ MODULE_CTX(mc->instance->dl_inst, module_thread(mc->instance)->data, rctx),
+ request);
}
/*
caller = request->module;
request->module = mc->instance->name;
safe_lock(mc->instance);
- state->signal(&(module_ctx_t){
- .inst = mc->instance->dl_inst,
- .thread = state->thread->data,
- .rctx = state->rctx
- },
- request, action);
+ state->signal(MODULE_CTX(mc->instance->dl_inst, state->thread->data, state->rctx), request, action);
safe_unlock(mc->instance);
request->module = caller;
state->resume = NULL;
safe_lock(mc->instance);
- ua = resume(&state->rcode,
- &(module_ctx_t){
- .inst = mc->instance->dl_inst,
- .thread = state->thread->data,
- .rctx = state->rctx,
- }, request);
+ ua = resume(&state->rcode, MODULE_CTX(mc->instance->dl_inst, state->thread->data, state->rctx), request);
safe_unlock(mc->instance);
request->rcode = state->rcode;
request->module = mc->instance->name;
safe_lock(mc->instance); /* Noop unless instance->mutex set */
ua = mc->method(&state->rcode,
- &(module_ctx_t){
- .inst = mc->instance->dl_inst,
- .thread = state->thread->data
- },
+ MODULE_CTX(mc->instance->dl_inst, state->thread->data, NULL),
request);
safe_unlock(mc->instance);
request->module = caller;
case FR_EAP_METHOD_AKA:
case FR_EAP_METHOD_SIM:
{
- module_inst_ctx_t *mctx = &(module_inst_ctx_t){
- .inst = ((dl_module_inst_t *)cf_data_value(cf_data_find(eap_cs,
- dl_module_inst_t, "rlm_eap")))
- };
+ module_inst_ctx_t *mctx = MODULE_INST_CTX(
+ ((dl_module_inst_t *)cf_data_value(cf_data_find(eap_cs,
+ dl_module_inst_t, "rlm_eap"))));
WARN("Ignoring EAP method %s because we don't have OpenSSL support", name);
talloc_free(our_name);
rlm_lua_t const *inst = talloc_get_type_abort_const(mctx->inst->data, rlm_lua_t);
lua_State *L;
- fr_lua_util_set_mctx(&(module_ctx_t){ .inst = mctx->inst });
+ fr_lua_util_set_mctx(MODULE_CTX_FROM_INST(mctx));
L = luaL_newstate();
if (!L) {
*/
if (inst->interpreter) {
if (inst->func_detach) {
- fr_lua_run(&ret, &(module_ctx_t){
- .inst = mctx->inst,
- .thread = &(rlm_lua_thread_t){
+ fr_lua_run(&ret,
+ MODULE_CTX(mctx->inst,
+ &(rlm_lua_thread_t){
.interpreter = inst->interpreter
- }
- },
- NULL, inst->func_detach);
+ },
+ NULL),
+ NULL, inst->func_detach);
}
lua_close(inst->interpreter);
}
DEBUG("Using %s interpreter", fr_lua_version(inst->interpreter));
if (inst->func_instantiate) {
- fr_lua_run(&rcode, &(module_ctx_t){
- .inst = mctx->inst,
- .thread = &(rlm_lua_thread_t){
- .interpreter = inst->interpreter
- }
- },
- NULL, inst->func_instantiate);
+ fr_lua_run(&rcode,
+ MODULE_CTX(mctx->inst,
+ &(rlm_lua_thread_t){
+ .interpreter = inst->interpreter
+ },
+ NULL),
+ NULL, inst->func_instantiate);
}
return 0;
static void *mod_conn_create(TALLOC_CTX *ctx, void *instance, UNUSED fr_time_delta_t timeout)
{
struct wbcContext **wb_ctx;
- module_inst_ctx_t *mctx = &(module_inst_ctx_t){ .inst = dl_module_instance_by_data(instance) };
+ module_inst_ctx_t *mctx = MODULE_INST_CTX(dl_module_instance_by_data(instance));
wb_ctx = talloc_zero(ctx, struct wbcContext *);
*wb_ctx = wbcCtxCreate();
if (!def->module) {
ERROR("%s - Module '%s' load failed", funcname, def->module_name);
error:
- python_error_log(&(module_ctx_t){ .inst = mctx->inst }, NULL);
+ python_error_log(MODULE_CTX_FROM_INST(mctx), NULL);
Py_XDECREF(def->function);
def->function = NULL;
Py_XDECREF(def->module);
error:
Py_XDECREF(inst->pythonconf_dict);
inst->pythonconf_dict = NULL;
- python_error_log(&(module_ctx_t){ .inst = mctx->inst }, NULL);
+ python_error_log(MODULE_CTX_FROM_INST(mctx), NULL);
return -1;
}
for (i = 0; freeradius_constants[i].name; i++) {
if ((PyModule_AddIntConstant(module, freeradius_constants[i].name, freeradius_constants[i].value)) < 0) {
ERROR("Failed adding constant to module");
- python_error_log(&(module_ctx_t){ .inst = mctx->inst }, NULL);
+ python_error_log(MODULE_CTX_FROM_INST(mctx), NULL);
return -1;
}
}
* called during interpreter initialisation
* it can get at the current instance config.
*/
- current_mctx = &(module_ctx_t){ .inst = mctx->inst };
+ current_mctx = MODULE_CTX_FROM_INST(mctx);
current_conf = conf;
PyEval_RestoreThread(global_interpreter);
if (inst->instantiate.function) {
rlm_rcode_t rcode;
- do_python_single(&rcode, &(module_ctx_t){ .inst = mctx->inst }, NULL, inst->instantiate.function, "instantiate");
+ do_python_single(&rcode, MODULE_CTX_FROM_INST(mctx), NULL, inst->instantiate.function, "instantiate");
switch (rcode) {
case RLM_MODULE_FAIL:
case RLM_MODULE_REJECT:
if (inst->detach.function) {
rlm_rcode_t rcode;
- (void)do_python_single(&rcode, &(module_ctx_t){ .inst = mctx->inst }, NULL, inst->detach.function, "detach");
+ (void)do_python_single(&rcode, MODULE_CTX_FROM_INST(mctx), NULL, inst->detach.function, "detach");
}
#define PYTHON_FUNC_DESTROY(_x) python_function_destroy(&inst->_x)
if (!inst->io->signal) return;
- inst->io->signal(&(module_ctx_t){
- .inst = inst->io_submodule,
- .thread = t->io_thread,
- .rctx = mctx->rctx
- }, request, action);
+ inst->io->signal(MODULE_CTX(inst->io_submodule, t->io_thread, mctx->rctx), request, action);
}
rlm_radius_t const *inst = talloc_get_type_abort_const(mctx->inst->data, rlm_radius_t);
rlm_radius_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_radius_thread_t);
- return inst->io->resume(p_result,
- &(module_ctx_t){
- .inst = inst->io_submodule,
- .thread = t->io_thread,
- .rctx = mctx->rctx
- }, request);
+ return inst->io->resume(p_result, MODULE_CTX(inst->io_submodule, t->io_thread, mctx->rctx), request);
}
/** Do any RADIUS-layer fixups for proxying.
* connections.
*/
if (inst->io->thread_detach &&
- (inst->io->thread_detach(&(module_thread_inst_ctx_t){
- .inst = inst->io_submodule,
- .thread = t->io_thread,
- .el = mctx->el
- }) < 0)) {
+ (inst->io->thread_detach(MODULE_THREAD_INST_CTX(inst->io_submodule,
+ t->io_thread, mctx->el)) < 0)) {
return -1;
}
* sockets, set timers, etc.
*/
if (inst->io->thread_instantiate &&
- inst->io->thread_instantiate(&(module_thread_inst_ctx_t){
- .inst = inst->io_submodule,
- .thread = t->io_thread,
- .el = mctx->el
- }) < 0) return -1;
+ inst->io->thread_instantiate(MODULE_THREAD_INST_CTX(inst->io_submodule,
+ t->io_thread, mctx->el)) < 0) return -1;
return 0;
}
rlm_radius_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_radius_t);
if (inst->io->instantiate &&
- inst->io->instantiate(&(module_inst_ctx_t){
- .inst = inst->io_submodule
- }) < 0) return -1;
+ inst->io->instantiate(MODULE_INST_CTX(inst->io_submodule)) < 0) return -1;
return 0;
}
* Bootstrap the submodule.
*/
if (inst->io->bootstrap &&
- inst->io->bootstrap(&(module_inst_ctx_t){
- .inst = inst->io_submodule
- }) < 0) return -1;
+ inst->io->bootstrap(MODULE_INST_CTX(inst->io_submodule)) < 0) return -1;
return 0;
}
rlm_rest_xlat_rctx_t *our_rctx = talloc_get_type_abort(rctx, rlm_rest_xlat_rctx_t);
fr_curl_io_request_t *randle = talloc_get_type_abort(our_rctx->handle, fr_curl_io_request_t);
- rest_io_module_action(&(module_ctx_t){ .inst = dl_module_instance_by_data(mod_inst), .thread = t, .rctx = randle }, request, action);
+ rest_io_module_action(MODULE_CTX(dl_module_instance_by_data(mod_inst), t, randle), request, action);
}
*
* @todo We could extract the User-Name and password from the URL string.
*/
- ret = rest_request_config(&(module_ctx_t){ .inst = dl_module_instance_by_data(mod_inst), .thread = t },
+ ret = rest_request_config(MODULE_CTX(dl_module_instance_by_data(mod_inst), t, NULL),
section, request, randle, section->method,
section->body, uri_vb->vb_strvalue, NULL, NULL);
if (ret < 0) goto error;
#ifndef HAVE_YUBIKEY
if (inst->decrypt) {
- cf_log_err(conf, "Requires libyubikey for OTP decryption");
+ cf_log_err(mctx->inst->conf, "Requires libyubikey for OTP decryption");
return -1;
}
#endif