]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add definitions of Python objects for pair access
authorNick Porter <nick@portercomputing.co.uk>
Wed, 16 Apr 2025 11:42:14 +0000 (12:42 +0100)
committerNick Porter <nick@portercomputing.co.uk>
Mon, 21 Apr 2025 11:30:22 +0000 (12:30 +0100)
And associated function prototypes

src/modules/rlm_python/rlm_python.c

index f6b518ac3d5a35bd22fa5ad1c1831913b1476d7c..91df93a3d5fa20165313199ae319229e55848179 100644 (file)
@@ -36,6 +36,7 @@ RCSID("$Id$")
 #include <freeradius-devel/util/lsan.h>
 
 #include <Python.h>
+#include <structmember.h>
 #include <frameobject.h> /* Python header not pulled in by default. */
 #include <libgen.h>
 #include <dlfcn.h>
@@ -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