28RCSID(
"$Id: 764dbff74487a6f02aafdeddd95805617881da3b $")
30#define LOG_PREFIX mctx->mi->name
32#include <freeradius-devel/server/base.h>
33#include <freeradius-devel/server/module_rlm.h>
34#include <freeradius-devel/server/pairmove.h>
35#include <freeradius-devel/util/debug.h>
36#include <freeradius-devel/util/lsan.h>
39#include <frameobject.h>
100 .path_include_default =
true
149#define A(x) { FR_CONF_OFFSET("mod_" #x, rlm_python_t, x.module_name), .dflt = "${.module}" }, \
150 { FR_CONF_OFFSET("func_" #x, rlm_python_t, x.function_name) },
170#define A(x) { #x, x },
209 if (!PyArg_ParseTuple(
args,
"is", &status, &
msg)) {
219 {
"log", &
mod_log, METH_VARARGS,
220 "freeradius.log(level, msg)\n\n" \
221 "Print a message using the freeradius daemon's logging system. level should be one of the\n" \
222 "following constants L_DBG, L_WARN, L_INFO, L_ERR, L_DBG_WARN, L_DBG_ERR, L_DBG_WARN_REQ, L_DBG_ERR_REQ\n"
224 { NULL, NULL, 0, NULL },
233 PyObject *p_type = NULL, *p_value = NULL, *p_traceback = NULL, *p_str_1 = NULL, *p_str_2 = NULL;
235 PyErr_Fetch(&p_type, &p_value, &p_traceback);
236 PyErr_NormalizeException(&p_type, &p_value, &p_traceback);
237 if (!p_type || !p_value)
goto failed;
239 if (((p_str_1 = PyObject_Str(p_type)) == NULL) || ((p_str_2 = PyObject_Str(p_value)) == NULL))
goto failed;
243 if (p_traceback != Py_None) {
244 PyTracebackObject *ptb = (PyTracebackObject*)p_traceback;
247 while (ptb != NULL) {
248 PyFrameObject *cur_frame = ptb->tb_frame;
249#if PY_VERSION_HEX >= 0x030A0000
250 PyCodeObject *code = PyFrame_GetCode(cur_frame);
254 PyUnicode_AsUTF8(code->co_filename),
255 PyFrame_GetLineNumber(cur_frame),
256 PyUnicode_AsUTF8(code->co_name)
262 PyUnicode_AsUTF8(cur_frame->f_code->co_filename),
263 PyFrame_GetLineNumber(cur_frame),
264 PyUnicode_AsUTF8(cur_frame->f_code->co_name)
278 Py_XDECREF(p_traceback);
282 fr_pair_list_t *vps, PyObject *p_value,
char const *funcname,
char const *list_name)
285 Py_ssize_t tuple_len;
296 if (p_value == Py_None)
return;
298 if (!PyTuple_CheckExact(p_value)) {
299 ERROR(
"%s - non-tuple passed to %s", funcname, list_name);
303 tuple_len = PyTuple_GET_SIZE(p_value);
304 for (i = 0; i < tuple_len; i++) {
305 PyObject *p_tuple_element = PyTuple_GET_ITEM(p_value, i);
312 if (!PyTuple_CheckExact(p_tuple_element)) {
313 ERROR(
"%s - Tuple element %d of %s is not a tuple", funcname, i, list_name);
318 pair_len = PyTuple_GET_SIZE(p_tuple_element);
319 if ((pair_len < 2) || (pair_len > 3)) {
320 ERROR(
"%s - Tuple element %d of %s is a tuple of size %zu. Must be 2 or 3",
321 funcname, i, list_name, pair_len);
325 p_str_1 = PyTuple_GET_ITEM(p_tuple_element, 0);
326 p_str_2 = PyTuple_GET_ITEM(p_tuple_element, pair_len - 1);
328 if ((!PyUnicode_CheckExact(p_str_1)) || (!PyUnicode_CheckExact(p_str_2))) {
329 ERROR(
"%s - Tuple element %d of %s must be as (str, str)",
330 funcname, i, list_name);
333 s1 = PyUnicode_AsUTF8(p_str_1);
334 s2 = PyUnicode_AsUTF8(p_str_2);
339 .dict_def = request->dict,
344 PERROR(
"%s - Failed to find attribute %s.%s", funcname, list_name, s1);
349 ERROR(
"%s - Attribute name %s.%s refers to outer request but not in a tunnel, skipping...",
350 funcname, list_name, s1);
359 DEBUG(
"%s - Failed: '%s.%s' = '%s'", funcname, list_name, s1, s2);
361 DEBUG(
"%s - '%s.%s' = '%s'", funcname, list_name, s1, s2);
376 PyObject *attribute = NULL;
377 PyObject *
value = NULL;
379 attribute = PyUnicode_FromString(
vp->
da->name);
380 if (!attribute)
return -1;
382 switch (
vp->vp_type) {
384 value = PyUnicode_FromStringAndSize(
vp->vp_strvalue,
vp->vp_length);
388 value = PyBytes_FromStringAndSize((
char const *)
vp->vp_octets,
vp->vp_length);
392 value = PyBool_FromLong(
vp->vp_bool);
396 value = PyLong_FromUnsignedLong(
vp->vp_uint8);
400 value = PyLong_FromUnsignedLong(
vp->vp_uint16);
404 value = PyLong_FromUnsignedLong(
vp->vp_uint32);
408 value = PyLong_FromUnsignedLongLong(
vp->vp_uint64);
412 value = PyLong_FromLong(
vp->vp_int8);
416 value = PyLong_FromLong(
vp->vp_int16);
420 value = PyLong_FromLong(
vp->vp_int32);
424 value = PyLong_FromLongLong(
vp->vp_int64);
428 value = PyFloat_FromDouble((
double)
vp->vp_float32);
432 value = PyFloat_FromDouble(
vp->vp_float64);
436 value = PyLong_FromSize_t(
vp->vp_size);
458 Py_XDECREF(attribute);
461 value = PyUnicode_FromStringAndSize(
buffer, (
size_t)slen);
468 int child_len, i = 0;
471 if (child_len == 0) {
477 if ((
value = PyTuple_New(child_len)) == NULL)
goto error;
484 if ((child_pp = PyTuple_New(2)) == NULL) {
490 PyTuple_SET_ITEM(
value, i, child_pp);
493 PyTuple_SET_ITEM(
value, i, Py_None);
501 if (
value == NULL)
goto error;
503 PyTuple_SET_ITEM(pp, 0, attribute);
504 PyTuple_SET_ITEM(pp, 1,
value);
510 request_t *request, PyObject *p_func,
char const *funcname)
513 PyObject *p_ret = NULL;
514 PyObject *p_arg = NULL;
527 if (request != NULL) {
531 if (tuple_len == 0) {
536 if ((p_arg = PyTuple_New(tuple_len)) == NULL) {
547 if ((pp = PyTuple_New(2)) == NULL) {
554 PyTuple_SET_ITEM(p_arg, i, pp);
557 PyTuple_SET_ITEM(p_arg, i, Py_None);
564 p_ret = PyObject_CallFunctionObjArgs(p_func, p_arg, NULL);
573 if (PyNumber_Check(p_ret)) rcode = PyLong_AsLong(p_ret);
590 if (PyTuple_CheckExact(p_ret)) {
591 PyObject *p_tuple_int;
593 if (PyTuple_GET_SIZE(p_ret) != 3) {
594 ERROR(
"%s - Tuple must be (return, replyTuple, configTuple)", funcname);
599 p_tuple_int = PyTuple_GET_ITEM(p_ret, 0);
600 if (!PyNumber_Check(p_tuple_int)) {
601 ERROR(
"%s - First tuple element not an integer", funcname);
606 rcode = PyLong_AsLong(p_tuple_int);
608 mod_vptuple(request->reply_ctx, mctx, request, &request->reply_pairs,
609 PyTuple_GET_ITEM(p_ret, 1), funcname,
"reply");
611 mod_vptuple(request->control_ctx, mctx, request, &request->control_pairs,
612 PyTuple_GET_ITEM(p_ret, 2), funcname,
"config");
614 }
else if (PyNumber_Check(p_ret)) {
616 rcode = PyLong_AsLong(p_ret);
618 }
else if (p_ret == Py_None) {
623 ERROR(
"%s - Function did not return a tuple or None", funcname);
641 request_t *request, PyObject *p_func,
char const *funcname)
653 PyEval_RestoreThread(t->
state);
661static unlang_action_t CC_HINT(nonnull) mod_##x(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request) \
663 rlm_python_t const *inst = talloc_get_type_abort_const(mctx->mi->data, rlm_python_t); \
664 return do_python(p_result, mctx, request, inst->x.function, #x);\
692 char const *funcname =
"python_function_load";
703 Py_XDECREF(def->module);
715 if (!PyCallable_Check(def->
function)) {
730 int indent_section = (lvl * 4);
731 int indent_item = (lvl + 1) * 4;
735 if (!cs || !dict)
return -1;
748 PyObject *sub_dict, *p_key;
750 p_key = PyUnicode_FromString(key);
752 ERROR(
"Failed converting config key \"%s\" to python string", key);
756 if (PyDict_Contains(dict, p_key)) {
757 WARN(
"Ignoring duplicate config section '%s'", key);
761 MEM(sub_dict = PyDict_New());
762 (void)PyDict_SetItem(dict, p_key, sub_dict);
770 PyObject *p_key, *p_value;
773 WARN(
"Skipping \"%s\" as it has no value", key);
777 p_key = PyUnicode_FromString(key);
778 p_value = PyUnicode_FromString(
value);
780 ERROR(
"Failed converting config key \"%s\" to python string", key);
784 ERROR(
"Failed converting config value \"%s\" to python string",
value);
792 if (PyDict_Contains(dict, p_key)) {
793 WARN(
"Ignoring duplicate config item '%s'", key);
797 (void)PyDict_SetItem(dict, p_key, p_value);
799 DEBUG(
"%*s%s = \"%s\"", indent_item,
" ", key,
value);
803 DEBUG(
"%*s}", indent_section,
" ");
820 inst->pythonconf_dict = PyDict_New();
821 if (!
inst->pythonconf_dict) {
822 ERROR(
"Unable to create python dict for config");
824 Py_XDECREF(
inst->pythonconf_dict);
825 inst->pythonconf_dict = NULL;
832 DEBUG(
"Inserting \"config\" section into python environment as radiusd.config");
839 if (PyModule_AddObject(module,
"config",
inst->pythonconf_dict) < 0)
goto error;
853 ERROR(
"Failed adding constant to module");
869 static struct PyModuleDef py_module_def = {
870 PyModuleDef_HEAD_INIT,
871 .m_name =
"freeradius",
872 .m_doc =
"freeRADIUS python module",
879 module = PyModule_Create(&py_module_def);
905 if (!
inst->interpreter) {
906 ERROR(
"Failed creating new interpreter");
909 DEBUG3(
"Created new interpreter %p",
inst->interpreter);
912 PyEval_RestoreThread(
inst->interpreter);
920 module = PyImport_ImportModule("freeradius");
922 ERROR(
"Failed importing \"freeradius\" module into interpreter %p",
inst->interpreter);
930 inst->module =
module;
942 Py_XDECREF(
inst->module);
944 PyEval_RestoreThread(interp);
945 Py_EndInterpreter(interp);
970 PyEval_RestoreThread(
inst->interpreter);
975#define PYTHON_FUNC_LOAD(_x) if (python_function_load(mctx, &inst->_x) < 0) goto error
987 if (
inst->instantiate.function) {
1022 if (!
inst->interpreter)
return 0;
1027 PyEval_RestoreThread(
inst->interpreter);
1032 if (
inst->detach.function) {
1038#define PYTHON_FUNC_DESTROY(_x) python_function_destroy(&inst->_x)
1047 Py_XDECREF(
inst->pythonconf_dict);
1048 PyEval_SaveThread();
1060 PyThreadState *state;
1064 state = PyThreadState_New(
inst->interpreter->interp);
1066 ERROR(
"Failed initialising local PyThreadState");
1070 DEBUG3(
"Initialised new thread state %p", state);
1080 PyEval_RestoreThread(t->
state);
1081 PyThreadState_Clear(t->
state);
1082 PyEval_SaveThread();
1084 PyThreadState_Delete(t->
state);
1091#define LOAD_INFO(_fmt, ...) fr_log(LOG_DST, L_INFO, __FILE__, __LINE__, "rlm_python - " _fmt, ## __VA_ARGS__)
1092#define LOAD_WARN(_fmt, ...) fr_log_perror(LOG_DST, L_WARN, __FILE__, __LINE__, \
1093 &(fr_log_perror_format_t){ \
1094 .first_prefix = "rlm_python - ", \
1095 .subsq_prefix = "rlm_python - ", \
1097 _fmt, ## __VA_ARGS__)
1105 LOAD_INFO(
"Python version: %s", Py_GetVersion());
1116 PyConfig_InitPythonConfig(&
config);
1123 status = PyConfig_SetString(&
config, &
config.program_name, wide_name);
1124 PyMem_RawFree(wide_name);
1126 if (PyStatus_Exception(status)) {
1149 status = PyConfig_SetString(&
config, &
config.pythonpath_env, wide_path);
1155 config.module_search_paths_set = 1;
1156 status = PyWideStringList_Append(&
config.module_search_paths, wide_path);
1158 PyMem_RawFree(wide_path);
1159 if (PyStatus_Exception(status))
goto fail;
1162 config.install_signal_handlers = 0;
1165 if (PyStatus_Exception(status))
goto fail;
1172 path = Py_EncodeLocale(Py_GetPath(), NULL);
1173 LOAD_INFO(
"Python path set to \"%s\"", path);
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
static int const char char buffer[256]
#define CONF_PARSER_TERMINATOR
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Defines a CONF_PAIR to C data type mapping.
Common header for all CONF_* types.
Configuration AVP similar to a fr_pair_t.
A section grouping multiple CONF_PAIR.
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
#define cf_item_next(_ci, _curr)
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
int dependency_version_number_add(CONF_SECTION *cs, char const *name, char const *version)
Add a library/server version pair to the main configuration.
void * dl_open_by_sym(char const *sym_name, int flags)
Utility function to dlopen the library containing a particular symbol.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
char const * name
Name of library and section within global config.
#define GLOBAL_LIB_TERMINATOR
Structure to define how to initialise libraries with global configuration.
#define ROPTIONAL(_l_request, _l_global, _fmt,...)
Use different logging functions depending on whether request is NULL or not.
void fr_log(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *fmt,...)
Send a server log message to its destination.
@ L_DBG_WARN_REQ
Less severe warning only displayed when debugging is enabled.
@ L_DBG_ERR
Error only displayed when debugging is enabled.
@ L_DBG_ERR_REQ
Less severe error only displayed when debugging is enabled.
@ L_DBG_WARN
Warning only displayed when debugging is enabled.
@ L_INFO
Informational message.
@ L_DBG
Only displayed when debugging is enabled.
main_config_t const * main_config
Main server configuration.
char const * name
Name of the daemon, usually 'radiusd'.
@ TMPL_ATTR_REF_PREFIX_AUTO
Attribute refs may have a '&' prefix.
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_FLOAT32
Single precision floating point.
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_INT8
8 Bit signed integer.
@ FR_TYPE_ETHERNET
48 Bit Mac-Address.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_INT64
64 Bit signed integer.
@ FR_TYPE_INT16
16 Bit signed integer.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_COMBO_IP_PREFIX
IPv4 or IPv6 address prefix depending on length.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_INT32
32 Bit signed integer.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
@ FR_TYPE_IFID
Interface ID.
@ FR_TYPE_OCTETS
Raw octets.
@ FR_TYPE_FLOAT64
Double precision floating point.
module_instance_t const * mi
Instance of the module being instantiated.
void * thread
Thread specific instance data.
module_instance_t * mi
Module instance to detach.
void * thread
Thread instance data.
#define MODULE_CTX_FROM_INST(_mctx)
Wrapper to create a module_ctx_t as a compound literal from a module_inst_ctx_t.
module_instance_t const * mi
Instance of the module being instantiated.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for detach calls.
Temporary structure to hold arguments for instantiation calls.
Temporary structure to hold arguments for thread_instantiation calls.
module_t common
Common fields presented by all modules.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
int fr_pair_value_from_str(fr_pair_t *vp, char const *value, size_t inlen, fr_sbuff_unescape_rules_t const *uerules, bool tainted)
Convert string value to native attribute value.
void radius_pairmove(request_t *request, fr_pair_list_t *to, fr_pair_list_t *from)
static const conf_parser_t config[]
static rc_request_t * current
#define RETURN_MODULE_NOOP
#define RETURN_MODULE_RCODE(_rcode)
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_INVALID
The module considers the request invalid.
@ RLM_MODULE_OK
The module is OK, continue.
@ RLM_MODULE_FAIL
Module failed, don't reply.
@ RLM_MODULE_DISALLOW
Reject the request (user is locked out).
@ RLM_MODULE_REJECT
Immediately reject the request.
@ RLM_MODULE_NOTFOUND
User not found.
@ RLM_MODULE_UPDATED
OK (pairs modified).
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
@ RLM_MODULE_NUMCODES
How many valid return codes there are.
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
fr_dict_attr_t const * request_attr_reply
static unlang_action_t mod_authenticate(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static unlang_action_t mod_authorize(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static unlang_action_t mod_accounting(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static unlang_action_t mod_post_auth(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static int libpython_init(void)
PyObject * pythonconf_dict
Configuration parameters defined in the module made available to the python script.
static int mod_detach(module_detach_ctx_t const *mctx)
PyObject *python_func_def_t authenticate
static void python_function_destroy(python_func_def_t *def)
static int python_parse_config(module_inst_ctx_t const *mctx, CONF_SECTION *cs, int lvl, PyObject *dict)
static int python_module_import_config(module_inst_ctx_t const *mctx, CONF_SECTION *conf, PyObject *module)
Make the current instance's config available within the module we're initialising.
PyObject *python_func_def_t accounting
PyObject *python_func_def_t preacct
static struct @167 freeradius_constants[]
static global_lib_autoinst_t rlm_python_autoinst
static void libpython_free(void)
PyThreadState * interpreter
The interpreter used for this instance of rlm_python.
PyObject *python_func_def_t detach
static void python_obj_destroy(PyObject **ob)
static void mod_vptuple(TALLOC_CTX *ctx, module_ctx_t const *mctx, request_t *request, fr_pair_list_t *vps, PyObject *p_value, char const *funcname, char const *list_name)
PyObject *python_func_def_t instantiate
< Local, interpreter specific module.
char const * module_name
String name of module.
PyThreadState * state
Module instance/thread specific state.
char const * name
Name of the module instance.
static PyThreadState * global_interpreter
Our first interpreter.
bool path_include_default
Include the default python path in path
static int mod_populate_vptuple(module_ctx_t const *mctx, request_t *request, PyObject *pp, fr_pair_t *vp)
#define LOAD_WARN(_fmt,...)
static unlang_action_t do_python(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request, PyObject *p_func, char const *funcname)
Thread safe call to a python function.
static PyObject * python_module_init(void)
PyObject *PyObject * function
< Python reference to module.
static conf_parser_t const python_global_config[]
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
static void python_interpreter_free(rlm_python_t *inst, PyThreadState *interp)
static int python_function_load(module_inst_ctx_t const *mctx, python_func_def_t *def)
Import a user module and load a function from it.
PyObject *python_func_def_t post_auth
static libpython_global_config_t libpython_global_config
char const * function_name
String name of function in module.
static module_ctx_t const * current_mctx
Used for communication with inittab functions.
static CONF_SECTION * current_conf
Used for communication with inittab functions.
static unlang_action_t do_python_single(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request, PyObject *p_func, char const *funcname)
#define LOAD_INFO(_fmt,...)
#define PYTHON_FUNC_LOAD(_x)
static void * python_dlhandle
PyObject *python_func_def_t authorize
static void python_error_log(module_ctx_t const *mctx, request_t *request)
Print out the current error.
static int python_interpreter_init(module_inst_ctx_t const *mctx)
char const * path
Path to search for python files in.
#define PYTHON_FUNC_DESTROY(_x)
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
static int mod_instantiate(module_inst_ctx_t const *mctx)
static int python_module_import_constants(module_inst_ctx_t const *mctx, PyObject *module)
Import integer constants into the module we're initialising.
global_lib_autoinst_t const *const rlm_python_lib[]
static conf_parser_t module_config[]
static PyMethodDef module_methods[]
static PyObject * mod_log(UNUSED PyObject *module, PyObject *args)
Allow fr_log to be called from python.
Global config for python library.
Specifies the module.function to load for processing a section.
An instance of the rlm_python module.
Tracks a python module inst/thread state pair.
static int instantiate(module_inst_ctx_t const *mctx)
static unlang_action_t mod_preacct(rlm_rcode_t *p_result, module_ctx_t const *mctx, UNUSED request_t *request)
#define FR_SBUFF_OUT(_start, _len_or_end)
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
CONF_SECTION * conf
Module's instance configuration.
size_t inst_size
Size of the module's instance data.
void * data
Module's instance data.
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Named methods exported by a module.
ssize_t tmpl_afrom_attr_str(TALLOC_CTX *ctx, tmpl_attr_error_t *err, tmpl_t **out, char const *name, tmpl_rules_t const *rules))
Parse a string into a TMPL_TYPE_ATTR_* type tmpl_t.
int tmpl_request_ptr(request_t **request, FR_DLIST_HEAD(tmpl_request_list) const *rql)
Resolve a tmpl_request_ref_t to a request_t.
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
Optional arguments passed to vp_tmpl functions.
eap_aka_sim_process_conf_t * inst
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
fr_pair_t * fr_pair_list_next(fr_pair_list_t const *list, fr_pair_t const *item))
Get the next item in a valuepair list after a specific entry.
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
size_t fr_pair_list_num_elements(fr_pair_list_t const *list)
Get the length of a list of fr_pair_t.
ssize_t fr_value_box_print(fr_sbuff_t *out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules)
Print one boxed value to a string.