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`. .. method:: isVSASet(vendor, vendor_type, /) Verifies if a specified vendor-specific attribute is present. :param int vendor: Vendor. :param int vendor_type: Vendor type. :rtype: bool .. method:: getVSA(vendor, vendor_type, /) Retrieves the value of a specified vendor-specific attribute. :param int vendor: Vendor. :param int vendor_type: Vendor type. :return: Value of the attribute, or None if not present. :rtype: bytes, None .. method:: getVSATuple(vendor, vendor_type, /) Retrieves all values of a specified vendor-specific attribute. :param int vendor: Vendor. :param int vendor_type: Vendor type. :return: All values collected in a tuple. :rtype: tuple .. method:: setVSA(vendor, vendor_type, value, /) Adds a vendor-specific attribute. If already present, the attribute is overwritten. :param int vendor: Vendor. :param int vendor_type: Vendor type. :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:: clearVSA(vendor, vendor_type, /) Removes all specified vendor-specific attributes. :param int vendor: Vendor. :param int vendor_type: Vendor type. .. method:: isExtSet(type, ext_type, /) Verifies if a specified extended attribute is present. :param int type: Type. Must be one of 241, 242, 243, 244, 245, 246. :param int ext_type: Extended type. :rtype: bool .. method:: getExt(type, ext_type, /) Retrieves the value of a specified extended attribute. :param int type: Type. Must be one of 241, 242, 243, 244, 245, 246. :param int ext_type: Extended type. :return: All values collected in a tuple. :rtype: tuple .. method:: getExtTuple(type, ext_type, /) Retrieves all values of a specified extended attribute. :param int type: Type. Must be one of 241, 242, 243, 244, 245, 246. :param int ext_type: Extended type. :return: All values collected in a tuple. :rtype: tuple .. method:: setExt(type, ext_type, value, /) Adds an extended attribute. If already present, the attribute is overwritten. :param int type: Type. Must be one of 241, 242, 243, 244, 245, 246. :param int ext_type: Extended type. :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:: clearExt(type, ext_type, /) Removes all specified extended attributes. :param int type: Type. Must be one of 241, 242, 243, 244, 245, 246. :param int ext_type: Extended type. .. method:: isExtVSASet(type, vendor, vendor_type, /) Verifies if a specified extended-vendor-specific attribute is present. :param int type: Type. Must be one of 241, 242, 243, 244, 245, 246. :param int vendor: Vendor. :param int vendor_type: Vendor type. :rtype: bool .. method:: getExtVSA(type, vendor, vendor_type, /) Retrieves the value of a specified extended-vendor-specific attribute. :param int type: Type. Must be one of 241, 242, 243, 244, 245, 246. :param int vendor: Vendor. :param int vendor_type: Vendor type. :return: All values collected in a tuple. :rtype: tuple .. method:: getExtVSATuple(type, vendor, vendor_type, /) Retrieves all values of a specified extended-vendor-specific attribute. :param int type: Type. Must be one of 241, 242, 243, 244, 245, 246. :param int vendor: Vendor. :param int vendor_type: Vendor type. :return: All values collected in a tuple. :rtype: tuple .. method:: setExtVSA(type, vendor, vendor_type, value, /) Adds an extended-vendor-specific attribute. If already present, the attribute is overwritten. :param int type: Type. Must be one of 241, 242, 243, 244, 245, 246. :param int vendor: Vendor. :param int vendor_type: Vendor type. :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:: clearExtVSA(type, vendor, vendor_type, /) Removes all specified extended-vendor-specific attributes. :param int type: Type. Must be one of 241, 242, 243, 244, 245, 246. :param int vendor: Vendor. :param int vendor_type: Vendor type. .. method:: getLongExtTuple(type, ext_type, /) Retrieves all values of a specified long-extended attribute. :deprecated: use getExtTuple() instead :param int type: Type. Must be one of 245, 246. :param int ext_type: Extended type. :return: All values collected in a tuple. :rtype: tuple .. method:: setLongExt(type, ext_type, value, /) Adds a long-extended attribute. If already present, the attribute is overwritten. :deprecated: use setExt() instead :param int type: Type. Must be one of 245, 246. :param int ext_type: Extended type. :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:: getLongExtVSATuple(type, vendor, vendor_type, /) Retrieves all values of a specified long-extended vendor-specific attribute. :deprecated: use getExtVSATuple() instead :param int type: Type. Must be one of 245, 246. :param int vendor: Vendor. :param int vendor_type: Vendor type. :return: All values collected in a tuple. :rtype: tuple .. method:: setLongExtVSA(type, vendor, vendor_type, value, /) Adds a long-extended vendor-specific attribute. If already present, the attribute is overwritten. :deprecated: use setExtVSA() instead :param int type: Type. Must be one of 245, 246. :param int vendor: Vendor. :param int vendor_type: Vendor type. :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. .. 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. See :ref:`Breaking changes` for differences with the previous version. 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' .. warning:: The type of object returned by the iterator has changed between the Python 2 and Python 3 version of this module. See :ref:`Breaking changes`. 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) .. _breaking-radius: Breaking changes ---------------- .. _breaking-radius-iteration: Radius attribute iteration ^^^^^^^^^^^^^^^^^^^^^^^^^^ .. warning:: With Python 2 API, the result of iterating over the :class:`alc.RadiusAttributes` object returns tuples of length 3: (vendor, type, value), where vendor was set to 0 for regular attributes. With Python 3, the iterator has been changed to return tuples of length 2: (identifier, value), where the identifier is itself a tuple as specified in :ref:`Attribute Identifiers`, which uniquely identifies an attribute. .. _breaking-radius-invalid-arguments: Radius invalid arguments ^^^^^^^^^^^^^^^^^^^^^^^^ .. warning:: With Python 2 API, all functions on the :class:`alc.RadiusAttributes` object fail silently when one of the arguments (type, vendor, ext-type, or vendor-type) is invalid. With Python 3, a `TypeError` or `ValueError` exception is raised in cases of invalid arguments. .. _breaking-radius-attribute-not-present: Radius attribute not present ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. warning:: With Python 2 API, all functions on the :class:`alc.RadiusAttributes` object returning a single attribute (not the getTuple variants) return the empty bytes if the attribute is not present. With Python 3, `None` is returned when the attribute is not present.