PPPoE/PPP/PAP/CHAP
==================

The system provides the following Python object/classes to inspect and in certain cases, modify the corresponding protocol packet or message:

* object :data:`alc.pppoe`: PPPoE packet, class of :data:`alc.Pppoe`
* class :data:`alc.Ppp`: LCP/IPCP/IPv6CP message
* class :data:`alc.Pap`: PAP message
* class :data:`alc.Chap`: CHAP message

   .. note::
      For PPPoE message, only the pre-provided :data:`alc.pppoe` object should be used in script, the class :data:`alc.Pppoe` should not be used directly.


.. _alc_dot_pppoe:

The :data:`alc.Pppoe` class
----------------------------

.. note:: In addition to PPPoE packets, :data:`alc.pppoe` is also available when the Python script is triggered by packets encapsulated in PPPoE, such as LCP, PAP, or CHAP.

Instance Attributes
^^^^^^^^^^^^^^^^^^^

The PPPoE header fields are exposed as instance attributes on the object.

.. list-table:: Attributes defined on `alc.pppoe` object
   :header-rows: 1
   
   * - Attribute
     - Access
     - Type
     - Format
   * - dest_mac  
     - ro
     - str
     - "xx:xx:xx:xx:xx:xx"
   * - src_mac   
     - ro
     - str
     - "xx:xx:xx:xx:xx:xx"
   * - port_id   
     - ro
     - str
     - "1/2/3"
   * - vlan_tag  
     - ro
     - int
     -
   * - ver       
     - ro
     - int
     -
   * - type      
     - ro
     - int
     -
   * - code      
     - ro
     - int
     -
   * - session_id
     - ro
     - int
     -
   * - len       
     - ro
     - int
     -

Methods
^^^^^^^

.. method:: drop()

   Drops the packet.

.. method:: getTagList()

   Retrieves a tuple that includes tag-type of existing PPPoE tags in the packet.

   - The order of the element in the tuple is the same as the order of the tags in the packet.
   - If there are multiple instances of the same tag, the tag appears multiple times in the resulting tuple.

   :return: tuple of tag-types
   :raises RuntimeError: when called on a PPPoE packet that does not accept tags.

.. method:: get(type, /)

   Retrieves all instances of a specific tag-type.

   :param int type: tag type
   :return: tuple of bytes where each element is the value (as a bytestring) of a single instance.
            An empty tuple is returned when the tag is not present.
   :raises RuntimeError: when called on a PPPoE packet that does not accept tags.

.. method:: set(type, values, /)

   Deletes existing tags of the specified type and inserts new tags with the specified type and values.

   :param int type: tag type
   :param values: tuple of bytes, each element is the value of a separate tag (the length is deduced from this value)
   :raises RuntimeError: when called on a PPPoE packet that does not accept tags.

.. method:: clear(type, /)

   Removes all tags of specified type.

   :param int type: tag type
   :raises RuntimeError: when called on a PPPoE packet that does not accept tags.

.. method:: getPPP()

   Retrieves an object of type :class:`alc.Ppp<alc.Ppp>` which represents the LCP, IPCP or IP6CP packet encapsulated inside the PPPoE packet.

   :return: `alc.Ppp` object
   :raises RuntimeError:  when called on a PPPoE packet without embedded PPP packet.

   .. note:: Modifying the object returned by this function does not alter the PPPoE packet.

.. method:: getPAP()

   Retrieves an object of type :class:`alc.Pap<alc.Pap>` which represents the embedded PAP packet.

   :return: `alc.Pap` object
   :raises RuntimeError:  when called on a PPPoE packet without embedded PAP packet.

   .. note:: Modifying the object returned by this function does not alter the PPPoE packet. For the changes to take effect, :meth:`setPAP` must be called with the modified PAP packet as its argument.

.. method:: setPAP(pap, /)

   Replaces the existing PAP packet.

   :param alc.Pap pap: new PAP packet
   :raises RuntimeError: when called on a PPPoE packet without embedded PAP packet.

.. method:: getCHAP()

   Retrieves an object of type :class:`alc.Chap<alc.Chap>` which represents the embedded CHAP packet.

   :return: `alc.Ppp` object
   :raises RuntimeError:  when called on a PPPoE packet without embedded CHAP packet.

   .. note:: Modifying the object returned by this function does not alter the PPPoE packet. For the changes to take effect, :meth:`setCHAP` must be called with the modified CHAP packet as its argument.

.. method:: setCHAP(chap, /)

   Replaces the existing CHAP packet.

   :param alc.Chap chap: new CHAP packet
   :raises RuntimeError: when called on a PPPoE packet without embedded CHAP packet.

.. _alc_dot_ppp:

The :data:`alc.Ppp` class
-------------------------

The object returned from calling `alc.pppoe.getPPP()` is of type `alc.Ppp`.
This object can be inspected.


.. class:: Ppp(bytes, /)

    Creates a new object representing a PPP packet.

    :param bytes bytes: the bytes representation of the complete PPP packet, including the header.
   
Instance Attributes
^^^^^^^^^^^^^^^^^^^

The PPP header fields are exposed as instance attributes on the object.

.. list-table:: Attributes defined on `alc.Ppp` objects
   :header-rows: 1
   
   * - Attribute
     - Access
     - Type
   * - protocol  
     - ro
     - int
   * - code
     - ro
     - int
   * - id
     - ro
     - int
   * - len
     - ro
     - int

Methods
^^^^^^^

.. method:: getOptionList()

   Retrieves a tuple of all PPP options that are present in the packet.

   - The order of the options is the same as they appear in the packet.
   - Each instance of the option is reflected in the tuple.

   :return: tuple of option-types

.. method:: get()

   Retrieves the values of a specific PPP option.

   :param int type: option-type
   :return: tuple of bytes, each element is the value of an instance of the specified option-type

.. _alc_dot_pap:

The :data:`alc.Pap` class
-------------------------

The object returned from calling `alc.pppoe.getPAP()` is of type `alc.Pap`.
This object can be inspected and modified and can be passed to `alc.pppoe.setPAP()` to modify the active PPPoE packet.

Alternatively, new objects of this class can be created and used to set the embedded PAP packet.

.. class:: Pap(bytes, /)

    Creates a new object representing a PAP packet.

    :param bytes bytes: the bytes representation of the complete PAP packet, including the header.
   
Instance Attributes
^^^^^^^^^^^^^^^^^^^

The PAP header fields are exposed as instance attributes on the object.

.. list-table:: Attributes defined on `alc.Pap` objects
   :header-rows: 1
   
   * - Attribute
     - Access
     - Type
   * - code
     - ro
     - int
   * - id
     - ro
     - int
   * - len
     - ro
     - int

Methods
^^^^^^^

.. method:: getCred()

   Retrieves the peer-id and password of an Authentication-Request packet.

   :return: (peer_id, password) tuple, both elements are bytes, possibly b'' if the length is 0.
   :raises RuntimeError: when the packet is not an Authentication-Request

.. method:: setCred(value, /)

   Set the peer-id and password on an Authentication-Request packet.

   :param value: (peer_id, password) tuple, both elements are bytes, b'' is allowed for either element.
   :raises RuntimeError: when the packet is not an Authentication-Request

.. method:: getMsg()

   Retrieves the contents of the packet.

   :return: contents as a bytestring
   :raises RuntimeError: when the packet is not an Authentication-Ack/Nak

.. method:: setMsg(value, /)

   Sets the contents of the packet.

   :param bytes value: contents as a bytestring
   :raises RuntimeError: when the packet is not an Authentication-Ack/Nak


.. _alc_dot_chap:

The :data:`alc.Chap` class
--------------------------

The object returned from calling `alc.pppoe.getCHAP()` is of type `alc.Chap`.
This object can be inspected and modified and can be passed to `alc.pppoe.setCHAP()` to modify the active PPPoE packet.

Alternatively, new objects of this class can be created and used to set the embedded CHAP packet.

.. class:: Chap(bytes, /)

    Creates a new object representing a CHAP packet.

    :param bytes bytes: the bytes representation of the complete CHAP packet, including the header.
   
Instance Attributes
^^^^^^^^^^^^^^^^^^^

The CHAP header fields are exposed as instance attributes on the object.

.. list-table:: Attributes defined on `alc.Chap` objects
   :header-rows: 1
   
   * - Attribute
     - Access
     - Type
   * - code
     - ro
     - int
   * - id
     - ro
     - int
   * - len
     - ro
     - int

Methods
^^^^^^^

.. method:: getCred()

   Retrieves the name and challenge/response from a challenge or response packet.

   :return: (name, value) tuple, both elements are bytes, where value is either the challenge or response depending on the code of the packet
   :raises RuntimeError: when the packet is not a challenge or response packet

.. method:: setCred(value, /)

   Sets the name and challenge/response on a challenge/response packet.

   :param value: (name, value) tuple, both elements are bytes, where value is either the challenge or response depending on the code of the packet. b'' is valid for either element.
   :raises RuntimeError: when the packet is not a challenge or response packet

.. method:: getMsg()

   Retrieves the contents of the packet.

   :return: contents as a bytestring
   :raises RuntimeError: when the packet is not a success or failure packet.

.. method:: setMsg(value, /)

   Sets the contents of the packet.

   :param bytes value: contents as a bytestring
   :raises RuntimeError: when the packet is not a success or failure packet.


.. _breaking-pppoe:

Breaking changes
----------------


.. _breaking-pppoe-class-names:

Class objects renamed
^^^^^^^^^^^^^^^^^^^^^

.. warning:: In Python 3, the classes alc.Ppp, alc.Pap, and alc.Chap follow the CapWords convention. In the Python 2 API, these are called alc.ppp, alc.pap, and alc.chap respectively (all lowercase).

.. _breaking-pppoe-exceptions:

New exceptions on alc.Pppoe functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. warning:: For alc.Pppoe, When calling the functions :meth:`getTagList`, :meth:`get`, :meth:`set`, :meth:`clear` on a packet that is not in discovery state, an exception is raised. In the Python 2 implementation, `None` is returned. 

   The same is true when the functions :meth:`getPPP`, :meth:`getPAP`, and :meth:`getCHAP` are called on packets without a corresponding embedded packet.


.. _breaking-pppoe-pap-exceptions:

New exceptions on alc.Pap functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. warning:: The functions :meth:`alc.Pap.getCred`, :meth:`alc.Pap.setCred`, :meth:`alc.Pap.getMsg`, and :meth:`alc.Pap.setMsg` raise an exception when called on a packet with the wrong code.


.. _breaking-pppoe-chap-exceptions:

New exceptions on alc.Chap functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. warning:: The functions :meth:`alc.Chap.getCred`, :meth:`alc.Chap.setCred`, :meth:`alc.Chap.getMsg`, and :meth:`alc.Chap.setMsg` raise an exception when called on a packet with the wrong code.