From: Nick Porter Date: Wed, 16 Apr 2025 11:42:14 +0000 (+0100) Subject: Add definitions of Python objects for pair access X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=461663c804119d8dcc13f93d4b0a2d6c668c095d;p=thirdparty%2Ffreeradius-server.git Add definitions of Python objects for pair access And associated function prototypes --- diff --git a/src/modules/rlm_python/rlm_python.c b/src/modules/rlm_python/rlm_python.c index f6b518ac3d5..91df93a3d5f 100644 --- a/src/modules/rlm_python/rlm_python.c +++ b/src/modules/rlm_python/rlm_python.c @@ -36,6 +36,7 @@ RCSID("$Id$") #include #include +#include #include /* Python header not pulled in by default. */ #include #include @@ -129,6 +130,15 @@ static CONF_SECTION *current_conf; //!< Used for communication with inittab fu static PyObject *py_freeradius_log(UNUSED PyObject *self, PyObject *args, PyObject *kwds); +static int py_freeradius_state_init(PyObject *self, UNUSED PyObject *args, UNUSED PyObject *kwds); + +static PyObject *py_freeradius_pair_map_subscript(PyObject *self, PyObject *attr); +static PyObject *py_freeradius_attribute_instance(PyObject *self, PyObject *attr); +static int py_freeradius_pair_map_set(PyObject* self, PyObject* attr, PyObject* value); +static PyObject *py_freeradius_pair_getvalue(PyObject *self, void *closure); +static int py_freeradius_pair_setvalue(PyObject *self, PyObject *value, void *closure); +static PyObject *py_freeradius_pair_str(PyObject *self); + static libpython_global_config_t libpython_global_config = { .path = NULL, .path_include_default = true @@ -229,6 +239,137 @@ static struct { { NULL, 0 }, }; +/** The class which all pair types inherit from + * + */ +static PyTypeObject py_freeradius_pair_def = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "freeradius.Pair", + .tp_doc = "An attribute value pair", + .tp_basicsize = sizeof(py_freeradius_pair_t), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_new = PyType_GenericNew, +}; + +/** How to access "value" attribute of a pair + * + */ +static PyGetSetDef py_freeradius_pair_getset[] = { + { + .name = "value", + .get = py_freeradius_pair_getvalue, + .set = py_freeradius_pair_setvalue, + .doc = "Pair value", + .closure = NULL + }, + { NULL } /* Terminator */ +}; + +/** Contains a value pair of a specific type + * + */ +static PyTypeObject py_freeradius_value_pair_def = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "freeradius.ValuePair", + .tp_doc = "A value pair, i.e. one of the type string, integer, ipaddr etc...)", + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_base = &py_freeradius_pair_def, + .tp_getset = py_freeradius_pair_getset, + .tp_str = py_freeradius_pair_str, + .tp_as_mapping = &(PyMappingMethods) { + .mp_subscript = py_freeradius_attribute_instance, + .mp_ass_subscript = py_freeradius_pair_map_set, + } +}; + +/** Contains group attribute of a specific type + * + * Children of this attribute may be accessed using the map protocol + * i.e. foo['child-of-foo']. + * + */ +static PyTypeObject py_freeradius_grouping_pair_def = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "freeradius.GroupingPair", + .tp_doc = "A grouping pair, i.e. one of the type group, tlv, vsa or vendor. " + "Children are accessible via the mapping protocol i.e. foo['child-of-foo]", + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_base = &py_freeradius_pair_def, + .tp_as_mapping = &(PyMappingMethods){ + .mp_subscript = py_freeradius_pair_map_subscript, + .mp_ass_subscript = py_freeradius_pair_map_set, + } +}; + +/** Each instance contains a top level list (i.e. request, reply, control, session-state) + */ +static PyTypeObject py_freeradius_pair_list_def = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "freeradius.PairList", + .tp_doc = "A list of objects of freeradius.GroupingPairList and freeradius.ValuePair", + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_base = &py_freeradius_pair_def, + .tp_as_mapping = &(PyMappingMethods){ + .mp_subscript = py_freeradius_pair_map_subscript, + .mp_ass_subscript = py_freeradius_pair_map_set, + } +}; + +static PyMemberDef py_freeradius_request_attrs[] = { + { + .name = "request", + .type = T_OBJECT, + .offset = offsetof(py_freeradius_request_t, request), + .flags = READONLY, + .doc = "Pairs in the request list - received from the network" + }, + { + .name = "reply", + .type = T_OBJECT, + .offset = offsetof(py_freeradius_request_t, reply), + .flags = READONLY, + .doc = "Pairs in the reply list - sent to the network" + }, + { + .name = "control", + .type = T_OBJECT, + .offset = offsetof(py_freeradius_request_t, control), + .flags = READONLY, + .doc = "Pairs in the control list - control the behaviour of subsequently called modules" + }, + { + .name = "session-state", + .type = T_OBJECT, + .offset = offsetof(py_freeradius_request_t, state), + .flags = READONLY, + .doc = "Pairs in the session-state list - persists for the length of the session" + }, + { NULL } /* Terminator */ +}; + +static PyTypeObject py_freeradius_request_def = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "freeradius.Request", + .tp_doc = "freeradius request handle", + .tp_basicsize = sizeof(py_freeradius_request_t), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = PyType_GenericNew, + .tp_members = py_freeradius_request_attrs +}; + +static PyTypeObject py_freeradius_state_def = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "freeradius.State", + .tp_doc = "Private state data", + .tp_basicsize = sizeof(py_freeradius_state_t), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = PyType_GenericNew, + .tp_init = py_freeradius_state_init +}; + #ifndef _PyCFunction_CAST #define _PyCFunction_CAST(func) (PyCFunction)((void(*)(void))(func)) #endif