RADIUS ====== The system provides two Python objects :data:`alc.radius`, instance of class :data:`alc.Radius`, and :data:`alc.radius.attributes`, instance if class :data:`alc.RadiusAttributes`, to inspect and modify RADIUS packets. .. note:: Only the pre-provided :data:`alc.radius`/:data:`alc.radius.attributes` object should be used in script, the class :data:`alc.Radius`/:data:`alc.RadiusAttributes` should not be used directly. .. _alc_dot_radius: The :data:`alc.Radius` class ----------------------------- Provides packet level operations. .. method:: header() Returns a dictionary containing the value of the RADIUS header fields: * code (:class:`integer`) * id (:class:`integer`) * len (:class:`integer`) * authenticator (:class:`bytes`) :: print(alc.radius.header()) # {'code': 1, 'id': 202, 'len': 133, 'authenticator': b'\xe5C\xabM\xa1\x82(\x95\xe2\x84\xfai\xe6|\xd8\x92'} .. method:: drop() Drops the packet. The :data:`alc.RadiusAttributes` class ---------------------------------------- Provides attribute level operations. .. method:: isSet(type, /) Checks if a specified attribute is present. :param int|tuple type: Attribute type. If the parameter is a tuple, it should be interpreted as an attribute identifier. See :ref:`Attribute Identifiers`. :rtype: bool .. method:: get(type, /) Retrieves the value of a specified attribute. :param int|tuple type: Attribute type. If the parameter is a tuple, it should be interpreted as an attribute identifier. See :ref:`Attribute Identifiers`. :return: Value of the attribute, or None if not present. :rtype: bytes .. method:: getTuple(type, /) Retrieves all values of a specified attribute. :param int|tuple type: Attribute type. If the parameter is a tuple, it should be interpreted as an attribute identifier. See :ref:`Attribute Identifiers`. :return: All values collected in a tuple. :rtype: tuple .. method:: set(type, value, /) Adds an attribute with the specified type and value. This overwrites previously existing values if present. :param int|tuple type: Attribute type. If the parameter is a tuple, it should be interpreted as an attribute identifier. See :ref:`Attribute Identifiers`. :param bytes|tuple value: Attribute value. If it is a tuple, multiple attributes with the same type are added, one for each item in the tuple. .. method:: clear(type, /) Removes all attributes with the specified type. :param int|tuple type: Attribute type. If the parameter is a tuple, it should be interpreted as an attribute identifier. See :ref:`Attribute Identifiers`. .. note:: The following RADIUS attributes or VSAs are read-only: - Message-Authenticator (80) - Alc-LI-Action (26.6527.122) - Alc-LI-Destination (26.6527.123) - Alc-LI-FC (26.6527.124) - Alc-LI-Direction (26.6527.125) - Alc-LI-Intercept-Id (26.6527.138) - Alc-LI-Session-Id (26.6527.139) .. warning:: All methods in :class:`alc.RadiusAttributes` raise appropriate `TypeError` or `ValueError` messages in cases of invalid arguments. Attribute iteration ------------------- The class :class:`alc.RadiusAttributes` acts as an iterator over the attributes, yielding a tuple (identifier, value) for each attribute present. :: import alc print(list(alc.radius.attributes)) # [((8,), b'\xc0\xa8\x01\x14'), ((26, 6527, 9), b'\x08\x08\x08\x08'), ((26, 6527, 10), b'\x08\x08\x04\x04')] for attr, value in alc.radius.attributes: dotted_number = ".".join(map(str, attr)) print("{} = {}".format(dotted_number, value)) #8 = b'\xc0\xa8\x01\x14' #26.6527.9 = b'\x08\x08\x08\x08' #26.6527.10 = b\x08\x08\x04\x04' Attribute access ---------------- Besides the methods defined for the alc.Radius class, the attributes can also be fetched, set, and cleared using the container syntax of Python. The keys by which the attributes can be reached are the identifier tuples as described in :ref:`Attribute Identifiers`. The values are tuples of bytes. :: print(alc.radius.attributes[(8,)]) #(b'\xc0\xa8\x01\x14',) print(alc.radius.attributes[(241, 26, 6527, 4)]) #() Checking if an attribute is present can be done via the in operator. :: print((8,) in alc.radius.attributes) #True print((241, 26, 6527, 4) in alc.radius.attributes) #False Adding or overwriting an attribute can be done by assigning a value to the indexed attributes object. When setting multiple values for an attribute, the value should be a tuple of bytes. When setting a single value for an attribute, the value can be a 1-tuple of bytes or the individual bytes. :: alc.radius.attributes[(8,)] = b'\xc0\xa8\x01\x14' alc.radius.attributes[(8,)] = (b'\xc0\xa8\x01\x14',) alc.radius.attributes[(25,)] = (b'red', b'green', b'blue') Clearing an attribute can be performed with the del operator. :: del alc.radius.attributes[(8,)] .. _Attribute identifiers: Attribute identifiers --------------------- Attribute identifiers as described in :rfc:`6929#section-2.7` can be used to target a specific attribute. They are specified in Python as a tuple of integers, where each item in the tuple corresponds to a number in the "dotted number" format. .. list-table:: :header-rows: 1 * - Type - Name - Identifier - Python object * - Normal - NAS-IP-Address - 4 - (4, ) * - Extended - Frag-Status - 241.1 - (241, 1) * - Vendor-Specific - Alc-Subsc-Prof-Str - 26.6527.12 - (26, 6527, 12) * - Extended-Vendor-Specific - Alc-PPPoE-Client-Service - 241.26.6527.1 - (241, 26, 6527, 1)