27RCSID(
"$Id: 7bc08eda6b3a69329bcb8f1578906e3ef93ed693 $")
29#define LOG_PREFIX inst->name
31#include <freeradius-devel/server/base.h>
32#include <freeradius-devel/server/module_rlm.h>
33#include <freeradius-devel/util/debug.h>
34#include <freeradius-devel/util/lsan.h>
37#include <structmember.h>
38#include <frameobject.h>
148 .path_include_default =
true
190#define A(x) { FR_CONF_OFFSET("mod_" #x, rlm_python_t, x.module_name), .dflt = "${.module}" }, \
191 { FR_CONF_OFFSET("func_" #x, rlm_python_t, x.function_name) },
208#define A(x) { #x, x },
244 PyVarObject_HEAD_INIT(NULL, 0)
245 .tp_name =
"freeradius.Pair",
246 .tp_doc =
"An attribute value pair",
249 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
250 .tp_new = PyType_GenericNew,
271 PyVarObject_HEAD_INIT(NULL, 0)
272 .tp_name =
"freeradius.ValuePair",
273 .tp_doc =
"A value pair, i.e. one of the type string, integer, ipaddr etc...)",
274 .tp_flags = Py_TPFLAGS_DEFAULT,
278 .tp_as_mapping = &(PyMappingMethods) {
291 PyVarObject_HEAD_INIT(NULL, 0)
292 .tp_name =
"freeradius.GroupingPair",
293 .tp_doc =
"A grouping pair, i.e. one of the type group, tlv, vsa or vendor. "
294 "Children are accessible via the mapping protocol i.e. foo['child-of-foo]",
295 .tp_flags = Py_TPFLAGS_DEFAULT,
297 .tp_as_mapping = &(PyMappingMethods){
306 PyVarObject_HEAD_INIT(NULL, 0)
307 .tp_name =
"freeradius.PairList",
308 .tp_doc =
"A list of objects of freeradius.GroupingPairList and freeradius.ValuePair",
309 .tp_flags = Py_TPFLAGS_DEFAULT,
311 .tp_as_mapping = &(PyMappingMethods){
323 .doc =
"Pairs in the request list - received from the network"
330 .doc =
"Pairs in the reply list - sent to the network"
337 .doc =
"Pairs in the control list - control the behaviour of subsequently called modules"
340 .name =
"session-state",
344 .doc =
"Pairs in the session-state list - persists for the length of the session"
350 PyVarObject_HEAD_INIT(NULL, 0)
351 .tp_name =
"freeradius.Request",
352 .tp_doc =
"freeradius request handle",
355 .tp_flags = Py_TPFLAGS_DEFAULT,
356 .tp_new = PyType_GenericNew,
361 PyVarObject_HEAD_INIT(NULL, 0)
362 .tp_name =
"freeradius.State",
363 .tp_doc =
"Private state data",
366 .tp_flags = Py_TPFLAGS_DEFAULT,
367 .tp_new = PyType_GenericNew,
371#ifndef _PyCFunction_CAST
372#define _PyCFunction_CAST(func) (PyCFunction)((void(*)(void))(func))
380 "freeradius.log(msg[, type, lvl])\n\n"
381 "Print a message using the freeradius daemon's logging system.\n"
382 "type should be one of the following constants:\n"
383 " freeradius.L_DBG\n"
384 " freeradius.L_INFO\n"
385 " freeradius.L_WARN\n"
386 " freeradius.L_ERR\n"
387 "lvl should be one of the following constants:\n"
388 " freeradius.L_DBG_LVL_OFF\n"
389 " freeradius.L_DBG_LVL_1\n"
390 " freeradius.L_DBG_LVL_2\n"
391 " freeradius.L_DBG_LVL_3\n"
392 " freeradius.L_DBG_LVL_4\n"
393 " freeradius.L_DBG_LVL_MAX\n"
395 { NULL, NULL, 0, NULL },
399 PyModuleDef_HEAD_INIT,
400 .m_name =
"freeradius",
401 .m_doc =
"FreeRADIUS python module",
414 ret = strcmp(a->
name1, b->name1);
415 if (ret != 0)
return CMP(ret, 0);
418 ret = strcmp(a->
name2, b->name2);
429 dict = PyThreadState_GetDict();
433 module = PyState_FindModule(&py_freeradius_def);
436 dict = PyModule_GetDict(module);
451 if (
unlikely(!p_state))
return NULL;
452 return p_state->
inst;
463 if (
unlikely(!p_state))
return NULL;
486 static char const *kwlist[] = {
"msg",
"type",
"lvl", NULL };
494 if (!PyArg_ParseTupleAndKeywords(
args, kwds,
"s|ii", (
char **)((uintptr_t)kwlist),
495 &
msg, &
type, &lvl)) Py_RETURN_NONE;
510 DEBUG3(
"Populating __State data with %p/%p", our_self->
inst, our_self->
t);
524 if (!PyLong_CheckExact(attr)) Py_RETURN_NONE;
525 idx = PyLong_AsLong(attr);
528 PyErr_SetString(PyExc_AttributeError,
"Cannot use negative attribute instance values");
531 if (idx == 0)
return self;
539 PyErr_SetString(PyExc_AttributeError,
"Unsupported data type");
543 PyErr_SetString(PyExc_MemoryError,
"Failed to allocate PyObject");
547 Py_INCREF(init_pair->
parent);
548 pair->
da = init_pair->
da;
551 return (PyObject *)pair;
565 char const *attr_name;
577 if (!PyUnicode_CheckExact(attr)) {
578 PyErr_Format(PyExc_AttributeError,
"Invalid type '%s' for map attribute",
579 ((PyTypeObject *)PyObject_Type(attr))->tp_name);
582 attr_name = PyUnicode_AsUTF8AndSize(attr, &
len);
590 if (our_self->
vp) list = &our_self->
vp->vp_group;
593 PyErr_Format(PyExc_AttributeError,
"Invalid attribute name '%.*s'", (
int)
len, attr_name);
602 PyErr_SetString(PyExc_AttributeError,
"Unsupported data type");
606 PyErr_SetString(PyExc_MemoryError,
"Failed to allocate PyObject");
616 return (PyObject *)pair;
635 if (obj_pair->
idx > 0) {
637 if (count < obj_pair->idx) {
638 PyErr_Format(PyExc_AttributeError,
"Attempt to set instance %d when only %d exist", obj_pair->
idx,
count);
674 bool del = (
value ? false :
true);
677 PyErr_Format(PyExc_AttributeError,
"Invalid value type '%s'", ((PyTypeObject *)PyObject_Type(
value))->tp_name);
685 if (PyUnicode_CheckExact(attr)) {
686 char const *attr_name;
690 attr_name = PyUnicode_AsUTF8AndSize(attr, &
len);
700 PyErr_Format(PyExc_AttributeError,
"Invalid attribute name %.*s", (
int)
len, attr_name);
709 if (!our_self->
vp)
return -1;
711 list = &our_self->
vp->vp_group;
718 PyErr_Format(PyExc_MemoryError,
"Failed to add attribute %s", da->name);
729 }
else if (PyLong_CheckExact(attr)) {
730 long idx = PyLong_AsLong(attr);
734 PyErr_SetString(PyExc_AttributeError,
"Cannot use negative attribute instance values");
742 if (!
parent->vp)
return -1;
744 list = &
parent->vp->vp_group;
749 PyErr_Format(PyExc_MemoryError,
"Failed to add attribute %s", our_self->
da->name);
763 PyErr_Format(PyExc_AttributeError,
"Attempt to set instance %ld when only %d exist", idx,
count);
767 PyErr_Format(PyExc_MemoryError,
"Failed to add attribute %s", our_self->
da->name);
773 PyErr_Format(PyExc_AttributeError,
"Invalid object type '%s'", ((PyTypeObject *)PyObject_Type(attr))->tp_name);
779 vstr = PyUnicode_AsUTF8AndSize(
value, &vlen);
782 PyErr_Format(PyExc_AttributeError,
"Failed setting '%s' = '%.*s",
vp->
da->name, (
int)vlen, vstr);
807 PyObject *
value = NULL;
810 if (!
vp) Py_RETURN_NONE;
812 switch(
vp->vp_type) {
814 value = PyUnicode_FromStringAndSize(
vp->vp_strvalue,
vp->vp_length);
818 value = PyBytes_FromStringAndSize((
char const *)
vp->vp_octets,
vp->vp_length);
822 value = PyBool_FromLong(
vp->vp_bool);
826 value = PyLong_FromUnsignedLong(
vp->vp_uint8);
830 value = PyLong_FromUnsignedLong(
vp->vp_uint16);
834 value = PyLong_FromUnsignedLong(
vp->vp_uint32);
838 value = PyLong_FromUnsignedLongLong(
vp->vp_uint64);
842 value = PyLong_FromLong(
vp->vp_int8);
846 value = PyLong_FromLong(
vp->vp_int16);
850 value = PyLong_FromLong(
vp->vp_int32);
854 value = PyLong_FromLongLong(
vp->vp_int64);
858 value = PyFloat_FromDouble((
double)
vp->vp_float32);
862 value = PyFloat_FromDouble(
vp->vp_float64);
866 value = PyLong_FromSize_t(
vp->vp_size);
887 PyErr_Format(PyExc_MemoryError,
"Failed marshalling %s to Python value",
vp->
da->name);
890 value = PyUnicode_FromStringAndSize(
buffer, (
size_t)slen);
899 if (
value == NULL)
goto error;
925 if (!
parent->vp)
return -1;
927 list = &
parent->vp->vp_group;
929 if (count < own_self->idx) {
930 PyErr_Format(PyExc_AttributeError,
"Attempt to set instance %d when only %d exist", own_self->
idx,
count);
937 switch (
vp->
da->type) {
942 if (!PyUnicode_CheckExact(
value)){
944 PyErr_Format(PyExc_AttributeError,
"Incorrect Python type '%s' for attribute type '%s'",
948 val = PyUnicode_AsUTF8AndSize(
value, &
len);
958 if (!PyObject_IsInstance(
value, (PyObject *)&PyBytes_Type))
goto wrong_type;
959 PyBytes_AsStringAndSize(
value, (
char **)&val, &
len);
977 if (!PyLong_CheckExact(
value))
goto wrong_type;
978 val = PyLong_AsLongLong(
value);
980 switch (
vp->
da->type) {
994 vp->vp_uint64 = (uint64_t)val;
997 vp->vp_int8 = (int8_t)val;
1000 vp->vp_int16 = (int16_t)val;
1003 vp->vp_int32 = (int32_t)val;
1006 vp->vp_int64 = (int64_t)val;
1021 if (!PyFloat_CheckExact(
value))
goto wrong_type;
1022 val = PyFloat_AsDouble(
value);
1025 vp->vp_float32 = (float)val;
1027 vp->vp_float64 = val;
1047 if (!PyUnicode_CheckExact(
value))
goto wrong_type;
1049 val = PyUnicode_AsUTF8AndSize(
value, &
len);
1051 PyErr_Format(PyExc_AttributeError,
"Failed parsing %.*s as %s", (
int)
len, val,
fr_type_to_str(
vp->
da->type));
1072 PyObject *
value = NULL;
1075 if (!
vp)
return PyObject_Str(Py_None);
1077 switch(
vp->vp_type) {
1079 value = PyUnicode_FromStringAndSize(
vp->vp_strvalue,
vp->vp_length);
1094 PyErr_Format(PyExc_MemoryError,
"Failed casting %s to Python string",
vp->
da->name);
1097 value = PyUnicode_FromStringAndSize(
buffer, (
size_t)slen);
1102 if (
value == NULL)
goto error;
1113 PyObject *p_type = NULL, *p_value = NULL, *p_traceback = NULL, *p_str_1 = NULL, *p_str_2 = NULL;
1115 PyErr_Fetch(&p_type, &p_value, &p_traceback);
1116 PyErr_NormalizeException(&p_type, &p_value, &p_traceback);
1117 if (!p_type || !p_value)
goto failed;
1119 if (((p_str_1 = PyObject_Str(p_type)) == NULL) || ((p_str_2 = PyObject_Str(p_value)) == NULL))
goto failed;
1123 if (p_traceback != Py_None) {
1124 PyTracebackObject *ptb = (PyTracebackObject*)p_traceback;
1127 while (ptb != NULL) {
1128 PyFrameObject *cur_frame = ptb->tb_frame;
1129#if PY_VERSION_HEX >= 0x030A0000
1130 PyCodeObject *code = PyFrame_GetCode(cur_frame);
1134 PyUnicode_AsUTF8(code->co_filename),
1135 PyFrame_GetLineNumber(cur_frame),
1136 PyUnicode_AsUTF8(code->co_name)
1142 PyUnicode_AsUTF8(cur_frame->f_code->co_filename),
1143 PyFrame_GetLineNumber(cur_frame),
1144 PyUnicode_AsUTF8(cur_frame->f_code->co_name)
1154 Py_XDECREF(p_str_1);
1155 Py_XDECREF(p_str_2);
1157 Py_XDECREF(p_value);
1158 Py_XDECREF(p_traceback);
1178 if (
unlikely(!py_list))
return NULL;
1181 our_list->
da = list;
1199 ERROR(
"Python function returned %ld, which is not a valid return code",
value);
1212 PyObject *p_ret = NULL;
1213 PyObject *py_request;
1234 Py_DECREF(py_request);
1249 p_ret = PyObject_CallFunctionObjArgs(p_func, py_request, NULL);
1251 RERROR(
"Python function returned no value");
1266 if (PyNumber_Check(p_ret)) {
1270 }
else if (p_ret == Py_None) {
1275 ERROR(
"%s - Function did not return a tuple or None", funcname);
1285 Py_XDECREF(py_request);
1306 PyEval_RestoreThread(t->
state);
1333 char const *funcname =
"python_function_load";
1344 Py_XDECREF(def->module);
1368 if (!PyCallable_Check(def->
function)) {
1383 int indent_section = (lvl * 4);
1384 int indent_item = (lvl + 1) * 4;
1388 if (!cs || !
dict)
return -1;
1401 PyObject *sub_dict, *p_key;
1403 p_key = PyUnicode_FromString(key);
1405 ERROR(
"Failed converting config key \"%s\" to python string", key);
1409 if (PyDict_Contains(
dict, p_key)) {
1410 WARN(
"Ignoring duplicate config section '%s'", key);
1415 MEM(sub_dict = PyDict_New());
1416 (void)PyDict_SetItem(
dict, p_key, sub_dict);
1418 Py_DECREF(sub_dict);
1426 PyObject *p_key, *p_value;
1429 WARN(
"Skipping \"%s\" as it has no value", key);
1433 p_key = PyUnicode_FromString(key);
1434 p_value = PyUnicode_FromString(
value);
1436 ERROR(
"Failed converting config key \"%s\" to python string", key);
1437 Py_XDECREF(p_value);
1441 ERROR(
"Failed converting config value \"%s\" to python string",
value);
1450 if (PyDict_Contains(
dict, p_key)) {
1451 WARN(
"Ignoring duplicate config item '%s'", key);
1457 (void)PyDict_SetItem(
dict, p_key, p_value);
1461 DEBUG(
"%*s%s = \"%s\"", indent_item,
" ", key,
value);
1465 DEBUG(
"%*s}", indent_section,
" ");
1481 inst->pythonconf_dict = PyDict_New();
1482 if (!
inst->pythonconf_dict) {
1483 ERROR(
"Unable to create python dict for config");
1485 Py_XDECREF(
inst->pythonconf_dict);
1486 inst->pythonconf_dict = NULL;
1493 DEBUG(
"Inserting \"config\" section into python environment as radiusd.config");
1500 if (PyModule_AddObject(module,
"config",
inst->pythonconf_dict) < 0)
goto error;
1514 ERROR(
"Failed adding constant to module");
1530 static pthread_mutex_t init_lock = PTHREAD_MUTEX_INITIALIZER;
1531 static bool type_ready =
false;
1540 pthread_mutex_lock(&init_lock);
1556 pthread_mutex_unlock(&init_lock);
1577 module = PyModule_Create(&py_freeradius_def);
1605 if (PyModule_AddObject(module,
"__State", p_state) < 0) {
1623 pthread_mutex_unlock(&init_lock);
1644 if (!
inst->interpreter) {
1645 ERROR(
"Failed creating new interpreter");
1648 DEBUG3(
"Created new interpreter %p",
inst->interpreter);
1649 PyEval_SaveThread();
1651 PyEval_RestoreThread(
inst->interpreter);
1659 module = PyImport_ImportModule("freeradius");
1661 ERROR(
"Failed importing \"freeradius\" module into interpreter %p",
inst->interpreter);
1669 inst->module =
module;
1670 PyEval_SaveThread();
1677 PyEval_RestoreThread(interp);
1683 Py_XDECREF(
inst->module);
1685 Py_EndInterpreter(interp);
1687 PyEval_SaveThread();
1709 if (
inst->interpreter)
return 0;
1716 PyEval_RestoreThread(
inst->interpreter);
1721#define PYTHON_FUNC_LOAD(_x) if (python_function_load(mctx, &inst->_x) < 0) goto error
1739 if (cp)
goto found_mod;
1756 if (cp)
goto found_func;
1770 if (
inst->instantiate.function) {
1774 switch (result.
rcode) {
1807 if (!
inst->interpreter)
return 0;
1812 PyEval_RestoreThread(
inst->interpreter);
1817 if (
inst->detach.function) {
1823#define PYTHON_FUNC_DESTROY(_x) python_function_destroy(&inst->_x)
1833 PyEval_SaveThread();
1848 PyThreadState *t_state;
1855 t_state = PyThreadState_New(
inst->interpreter->interp);
1857 ERROR(
"Failed initialising local PyThreadState");
1861 PyEval_RestoreThread(t_state);
1862 t_dict = PyThreadState_GetDict();
1864 ERROR(
"Failed getting PyThreadState dictionary");
1866 PyEval_SaveThread();
1867 PyThreadState_Delete(t_state);
1879 ERROR(
"Failed instantiating module instance information object");
1883 if (
unlikely(PyDict_SetItemString(t_dict,
"__State", p_state) < 0)) {
1884 ERROR(
"Failed setting module instance information in thread dict");
1888 DEBUG3(
"Initialised PyThreadState %p", t_state);
1890 PyEval_SaveThread();
1899 PyEval_RestoreThread(t->
state);
1900 PyThreadState_Clear(t->
state);
1901 PyEval_SaveThread();
1903 PyThreadState_Delete(t->
state);
1910#define LOAD_INFO(_fmt, ...) fr_log(LOG_DST, L_INFO, __FILE__, __LINE__, "rlm_python - " _fmt, ## __VA_ARGS__)
1911#define LOAD_WARN(_fmt, ...) fr_log_perror(LOG_DST, L_WARN, __FILE__, __LINE__, \
1912 (&(fr_log_perror_format_t){ \
1913 .first_prefix = "rlm_python - ", \
1914 .subsq_prefix = "rlm_python - ", \
1916 _fmt, ## __VA_ARGS__)
1923 LOAD_INFO(
"Python version: %s", Py_GetVersion());
1934 PyConfig_InitPythonConfig(&
config);
1941 status = PyConfig_SetString(&
config, &
config.program_name, wide_name);
1942 PyMem_RawFree(wide_name);
1944 if (PyStatus_Exception(status)) {
1967 status = PyConfig_SetString(&
config, &
config.pythonpath_env, wide_path);
1973 config.module_search_paths_set = 1;
1974 status = PyWideStringList_Append(&
config.module_search_paths, wide_path);
1976 PyMem_RawFree(wide_path);
1977 if (PyStatus_Exception(status))
goto fail;
1980 config.install_signal_handlers = 0;
1985 if (PyStatus_Exception(status))
goto fail;
2016 for (i = 0; i < talloc_array_length(
name); i++) {
2018 if (!strchr(
"abcdefghijklmnopqrstuvwxyz1234567890", *p)) *p =
'_';
2031 if (!
inst->funcs_init) {
2033 inst->funcs_init =
true;
2042 .offset = rule->pair.offset,
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
static int const char char buffer[256]
static uint8_t request[4]
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
fr_cmp_ret_t
Result of an ordering comparison.
call_env_parsed_t * call_env_parsed_add(TALLOC_CTX *ctx, call_env_parsed_head_t *head, call_env_parser_t const *rule)
Allocate a new call_env_parsed_t structure and add it to the list of parsed call envs.
void call_env_parsed_set_data(call_env_parsed_t *parsed, void const *data)
Assign data to a call_env_parsed_t.
#define CALL_ENV_TERMINATOR
#define FR_CALL_ENV_METHOD_OUT(_inst)
Helper macro for populating the size/type fields of a call_env_method_t from the output structure typ...
@ CALL_ENV_FLAG_PARSE_ONLY
The result of parsing will not be evaluated at runtime.
@ CALL_ENV_FLAG_PARSE_MISSING
If this subsection is missing, still parse it.
call_env_parser_t const * env
Parsing rules for call method env.
section_name_t const * asked
The actual name1/name2 that resolved to a module_method_binding_t.
module_instance_t const * mi
Module instance that the callenv is registered to.
@ CALL_ENV_PARSE_TYPE_VOID
Output of the parsing phase is undefined (a custom structure).
#define FR_CALL_ENV_SUBSECTION_FUNC(_name, _name2, _flags, _func)
Specify a call_env_parser_t which parses a subsection using a callback function.
#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 first 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.
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
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(_parent, _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.
fr_slen_t fr_dict_attr_by_name_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out, fr_dict_attr_t const *parent, fr_sbuff_t *name, fr_sbuff_term_t const *tt))
fr_slen_t fr_dict_attr_search_by_name_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out, fr_dict_t const *dict_def, fr_sbuff_t *name, fr_sbuff_term_t const *tt, bool internal, bool foreign))
Locate a fr_dict_attr_t by its name in the top level namespace of a dictionary.
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.
rlm_rcode_t rcode
The current rcode, from executing the instruction or merging the result from a frame.
#define ROPTIONAL(_l_request, _l_global, _fmt,...)
Use different logging functions depending on whether request is NULL or not.
#define fr_log(_log, _lvl, _file, _line, _fmt,...)
@ L_DBG_LVL_3
3rd highest priority debug messages (-xxx | -Xx).
@ L_DBG_LVL_1
Highest priority debug messages (-x).
@ L_DBG_LVL_2
2nd highest priority debug messages (-xx | -X).
@ L_DBG_LVL_OFF
No debug messages.
@ L_DBG_LVL_4
4th highest priority debug messages (-xxxx | -Xxx).
@ L_DBG_LVL_MAX
Lowest priority debug messages (-xxxxx | -Xxxx).
@ 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'.
@ 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.
void * env_data
Per call environment data.
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.
fr_pair_t * fr_pair_list_parent(fr_pair_list_t const *list)
Return a pointer to the parent pair which contains this list.
unsigned int fr_pair_count_by_da(fr_pair_list_t const *list, fr_dict_attr_t const *da)
Return the number of instances of a given da in the specified list.
int fr_pair_append_by_da(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list, fr_dict_attr_t const *da)
Alloc a new fr_pair_t (and append)
int fr_pair_value_from_str(fr_pair_t *vp, char const *value, size_t inlen, fr_sbuff_unescape_rules_t const *uerules, UNUSED bool tainted)
Convert string value to native attribute value.
fr_pair_list_t * fr_pair_parent_list(fr_pair_t const *vp)
Return a pointer to the parent pair list.
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
fr_pair_t * fr_pair_find_by_da_idx(fr_pair_list_t const *list, fr_dict_attr_t const *da, unsigned int idx)
Find a pair with a matching da at a given index.
int fr_pair_delete(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list and free.
static const conf_parser_t config[]
void * fr_rb_iter_init_inorder(fr_rb_tree_t *tree, fr_rb_iter_inorder_t *iter)
Initialise an in-order iterator.
int fr_rb_find_or_insert(void **found, fr_rb_tree_t *tree, void const *data)
Attempt to find current data in the tree, if it does not exist insert it.
void * fr_rb_iter_next_inorder(UNUSED fr_rb_tree_t *tree, fr_rb_iter_inorder_t *iter)
Return the next node.
#define fr_rb_inline_init(_tree, _type, _field, _data_cmp, _data_free)
Initialises a red black tree.
Iterator structure for in-order traversal of an rbtree.
The main red black tree structure.
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_TIMEOUT
Module (or section) timed out.
@ RLM_MODULE_NOTFOUND
User not found.
@ RLM_MODULE_UPDATED
OK (pairs modified).
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
#define RETURN_UNLANG_RCODE(_rcode)
#define RETURN_UNLANG_FAIL
#define RETURN_UNLANG_NOOP
#define RLM_MODULE_RCODE_VALID(_rcode)
Whether an integer is an rcode which a module may return.
fr_dict_attr_t const * request_attr_request
fr_dict_attr_t const * request_attr_control
fr_dict_attr_t const * request_attr_state
fr_dict_attr_t const * request_attr_reply
static py_freeradius_state_t * rlm_python_state_obj(void)
Return the module instance object associated with the thread state or interpreter state.
static int libpython_init(void)
static PyMethodDef py_freeradius_methods[]
PyObject * pythonconf_dict
Configuration parameters defined in the module made available to the python script.
static int python_parse_config(rlm_python_t const *inst, CONF_SECTION *cs, int lvl, PyObject *dict)
static int mod_detach(module_detach_ctx_t const *mctx)
static void python_function_destroy(python_func_def_t *def)
PyObject * reply
Reply list.
static unlang_action_t do_python_single(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request, PyObject *p_func, char const *funcname)
static int python_module_import_constants(rlm_python_t const *inst, PyObject *module)
Import integer constants into the module we're initialising.
PyObject_HEAD PyObject * request
< Common fields needed for every python object.
static PyTypeObject py_freeradius_value_pair_def
Contains a value pair of a specific type.
char * name2
Section name2 where this is called.
fr_rb_node_t node
Entry in tree of Python functions.
request_t * request
Current request.
rlm_python_thread_t * t
Thread-specific python instance.
static int python_func_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, UNUSED tmpl_rules_t const *t_rules, UNUSED CONF_ITEM *ci, call_env_ctx_t const *cec, call_env_parser_t const *rule)
static rlm_rcode_t python_rcode_from_long(rlm_python_t const *inst, long value)
Convert the integer which a Python function returned to an rcode.
PyObject_HEAD rlm_python_t const * inst
< Common fields needed for every python object.
static rlm_python_thread_t * current_t
Used for communicating with object init function.
static int py_freeradius_pair_map_set(PyObject *self, PyObject *attr, PyObject *value)
Set the value of a pair.
static struct @210 freeradius_constants[]
static PyGetSetDef py_freeradius_pair_getset[]
How to access "value" attribute of a pair.
PyObject *char const * def_module_name
< Local, interpreter specific module.
static PyObject * pair_list_alloc(request_t *request, fr_dict_attr_t const *list)
Create the Python object representing a pair list.
static global_lib_autoinst_t rlm_python_autoinst
static void rlm_python_set_request(request_t *request)
Set the request associated with the current thread state.
static rlm_python_t const * rlm_python_get_inst(void)
Return the rlm_python instance associated with the current interpreter.
static rlm_python_t const * current_inst
Used for communication with inittab functions.
static void libpython_free(void)
PyThreadState * interpreter
The interpreter used for this instance of rlm_python.
static PyObject * py_freeradius_pair_str(PyObject *self)
Return the string representation of a leaf pair node.
PyObject * control
Control list.
static fr_cmp_ret_t python_func_def_cmp(void const *one, void const *two)
How to compare two Python calls.
static int py_freeradius_state_init(PyObject *self, UNUSED PyObject *args, UNUSED PyObject *kwds)
static void python_obj_destroy(PyObject **ob)
static int python_module_import_config(rlm_python_t *inst, CONF_SECTION *conf, PyObject *module)
Make the current instance's config available within the module we're initialising.
static request_t * rlm_python_get_request(void)
Return the request associated with the current thread state.
static void python_func_name_safe(char *name)
rlm_python_t const * inst
Current module instance data.
char const * module_name
String name of module.
PyThreadState * state
Module instance/thread specific state.
PyObject * parent
Parent object of this pair.
char const * name
Name of the module instance.
static PyTypeObject py_freeradius_request_def
static PyThreadState * global_interpreter
Our first interpreter.
static PyObject * py_freeradius_pair_map_subscript(PyObject *self, PyObject *attr)
Returns a freeradius.Pair.
bool path_include_default
Include the default python path in path
static int py_freeradius_pair_setvalue(PyObject *self, PyObject *value, void *closure)
#define LOAD_WARN(_fmt,...)
static PyObject * python_module_init(void)
PyObject *PyObject * function
< Python reference to module.
char * name1
Section name1 where this is called.
static PyObject * py_freeradius_attribute_instance(PyObject *self, PyObject *attr)
Returns a specific instance of freeradius.Pair.
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)
fr_pair_t * vp
Real FreeRADIUS pair for this Python pair.
static PyTypeObject py_freeradius_grouping_pair_def
Contains group attribute of a specific type.
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.
static PyObject * py_freeradius_log(UNUSED PyObject *self, PyObject *args, PyObject *kwds)
Allow fr_log to be called from python.
#define _PyCFunction_CAST(func)
static libpython_global_config_t libpython_global_config
char const * function_name
String name of function in module.
bool verbose
Enable libpython verbose logging.
static fr_pair_t * py_freeradius_build_parents(PyObject *obj)
Build out missing parent pairs when a leaf node is assigned a value.
bool funcs_init
Has the tree been initialised.
static PyObject * py_freeradius_pair_getvalue(PyObject *self, void *closure)
static PyMemberDef py_freeradius_request_attrs[]
unsigned int idx
Instance index.
PyObject * state
Session state list.
#define LOAD_INFO(_fmt,...)
#define PYTHON_FUNC_LOAD(_x)
static PyModuleDef py_freeradius_def
static void * python_dlhandle
static PyTypeObject py_freeradius_pair_def
The class which all pair types inherit from.
static int python_interpreter_init(module_inst_ctx_t const *mctx)
static const call_env_method_t python_method_env
char const * path
Path to search for python files in.
#define PYTHON_FUNC_DESTROY(_x)
static PyTypeObject py_freeradius_state_def
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
static int mod_instantiate(module_inst_ctx_t const *mctx)
global_lib_autoinst_t const *const rlm_python_lib[]
static conf_parser_t module_config[]
fr_rb_tree_t funcs
Tree of function calls found by call_env parser.
static unlang_action_t mod_python(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
Thread safe call to a python function.
static void python_error_log(rlm_python_t const *inst, request_t *request)
Print out the current error.
python_func_def_t instantiate
static PyTypeObject py_freeradius_pair_list_def
Each instance contains a top level list (i.e.
PyObject_HEAD fr_dict_attr_t const * da
< Common fields needed for every python object.
Global config for python library.
Additional fields for pairs.
Wrapper around a python instance.
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.
#define FR_SBUFF_IN(_start, _len_or_end)
#define FR_SBUFF_OUT(_start, _len_or_end)
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
char const * name2
Second section name. Usually a packet type like 'access-request', 'access-accept',...
char const * name1
First section name. Usually a verb like 'recv', 'send', etc...
char const * name
Instance name e.g. user_database.
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.
fr_pair_list_t * tmpl_list_head(request_t *request, fr_dict_attr_t const *list)
Resolve attribute fr_pair_list_t value to an attribute list.
Optional arguments passed to vp_tmpl functions.
eap_aka_sim_process_conf_t * inst
fr_aka_sim_id_type_t type
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.
static int talloc_const_free(void const *ptr)
Free const'd memory.
#define talloc_strdup(_ctx, _str)
@ FR_TYPE_ATTR
A contains an attribute reference.
#define fr_type_is_structural(_x)
#define fr_type_is_leaf(_x)
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
#define fr_type_is_struct(_x)
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.
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
int fr_value_box_memdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Copy a buffer to a fr_value_box_t.
static fr_sbuff_err_t char ** out
static fr_sbuff_err_t char size_t * len