Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions docs/source/pcapkit/protocols/link/l2tp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ versions do not share one. Only the first 16-bit word, with a version nibble at
bits 12-15, is common to all of them; a base that parsed further would assume one
version's layout for every version.

.. autoclass:: pcapkit.protocols.link.l2tp.L2TP
:no-members:
:show-inheritance:

.. autoproperty:: info_name

.. automethod:: id

.. automethod:: __index__

Versions Not Implemented
------------------------

Expand All @@ -51,8 +61,8 @@ since callers take element zero as canonical.
Version Dispatch
----------------

Nothing dispatches on the version nibble, because only one version exists. A
second would follow the precedent of
Nothing dispatches on the version nibble, because L2TPv2 is the only version
implemented. Another would follow the precedent of
:class:`~pcapkit.protocols.application.http.HTTP`, which reads a version and
delegates to a per-version class. L2TP is the easier case:
:meth:`HTTP._guess_version <pcapkit.protocols.application.http.HTTP._guess_version>`
Expand All @@ -61,16 +71,6 @@ line, else trial-parsing each candidate -- because HTTP's wire format carries no
version field, whereas L2TP states its version explicitly in those four bits. A
deterministic switch on ``Ver`` is enough, and no new registry is needed.

.. autoclass:: pcapkit.protocols.link.l2tp.L2TP
:no-members:
:show-inheritance:

.. autoproperty:: info_name

.. automethod:: id

.. automethod:: __index__

.. rubric:: Footnotes

.. [*] https://en.wikipedia.org/wiki/Layer_2_Tunneling_Protocol
16 changes: 8 additions & 8 deletions docs/source/pcapkit/protocols/link/l2tpv2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@ reading ``2``. It is dispatched from
------- ----- --------------------- ------------------------------------------
0 1 ``l2tp.flags.len`` Length
------- ----- --------------------- ------------------------------------------
0 2 Reserved (must be zero ``x00``)
0 2 Reserved (must be zero)
------- ----- --------------------- ------------------------------------------
0 4 ``l2tp.flags.seq`` Sequence
------- ----- --------------------- ------------------------------------------
0 5 Reserved (must be zero ``x00``)
0 5 Reserved (must be zero)
------- ----- --------------------- ------------------------------------------
0 6 ``l2tp.flags.offset`` Offset
------- ----- --------------------- ------------------------------------------
0 7 ``l2tp.flags.prio`` Priority
------- ----- --------------------- ------------------------------------------
1 8 Reserved (must be zero ``x00``)
1 8 Reserved (must be zero)
------- ----- --------------------- ------------------------------------------
1 12 ``l2tp.version`` Version (``2``)
------- ----- --------------------- ------------------------------------------
Expand All @@ -57,11 +57,6 @@ reading ``2``. It is dispatched from
whichever version was on the wire. The version is reported by
:attr:`~pcapkit.protocols.link.l2tpv2.L2TPv2.alias` instead.

IANA protocol number 115 (``L2TP``) is deliberately left unbound: it
references :rfc:`3931`, i.e. **L2TPv3**, whose headers have a different shape,
so the binding waits on an ``L2TPv3`` class rather than this one. See
:mod:`pcapkit.protocols.link.l2tp`.

.. autoclass:: pcapkit.protocols.link.l2tpv2.L2TPv2
:no-members:
:show-inheritance:
Expand Down Expand Up @@ -96,6 +91,11 @@ Type Stubs
:members:
:show-inheritance:

Auxiliary Functions
~~~~~~~~~~~~~~~~~~~

.. autofunction:: pcapkit.protocols.schema.link.l2tp.l2tp_payload_length

Data Models
-----------

Expand Down
4 changes: 2 additions & 2 deletions docs/source/pcapkit/protocols/link/link.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ Base Protocol

:mod:`pcapkit.protocols.link.link` contains :class:`~pcapkit.protocols.link.link.Link`,
which is a base class for link layer protocols, e.g. :class:`~pcapkit.protocols.link.arp.ARP`/InARP,
:class:`~pcapkit.protocols.link.ethernet.Ethernet`, :class:`~pcapkit.protocols.link.l2tp.L2TP`,
:class:`~pcapkit.protocols.link.vlan.VLAN` and etc.
:class:`~pcapkit.protocols.link.ethernet.Ethernet`, :class:`~pcapkit.protocols.link.l2tp.L2TP`
and :class:`~pcapkit.protocols.link.vlan.VLAN`.

.. autoclass:: pcapkit.protocols.link.link.Link
:no-members:
Expand Down
5 changes: 0 additions & 5 deletions docs/source/pcapkit/protocols/link/s_tag.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,6 @@ It has a module of its own, apart from
*different* registry indices, ``0x88A8`` against ``0x8100``; see
:mod:`pcapkit.protocols.link.vlan` for the rule.

.. note::

802.1ad is part of IEEE 802.1Q-2011. The ``802.1ad`` name is kept because it
is what the provider-bridging tag is universally called.

.. autoclass:: pcapkit.protocols.link.s_tag.S_Tag
:no-members:
:show-inheritance:
Expand Down
5 changes: 0 additions & 5 deletions docs/source/pcapkit/protocols/transport/tcp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -318,11 +318,6 @@ Type Stubs
:members:
:show-inheritance:

.. autoclass:: pcapkit.protocols.schema.transport.tcp.Flags
:no-index:
:members:
:show-inheritance:

.. autoclass:: pcapkit.protocols.schema.transport.tcp.POCProfile
:members:
:show-inheritance:
Expand Down
2 changes: 1 addition & 1 deletion docs/source/pcapkit/protocols/transport/transport.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Base Protocol

:mod:`pcapkit.protocols.transport.transport` contains
:class:`~pcapkit.protocols.transport.transport.Transport`,
which is a base class for transport layer protocols, eg.
which is a base class for transport layer protocols, e.g.
:class:`~pcapkit.protocols.transport.tcp.TCP`,
:class:`~pcapkit.protocols.transport.udp.UDP` and
:class:`~pcapkit.protocols.transport.sctp.SCTP`.
Expand Down
6 changes: 3 additions & 3 deletions pcapkit/protocols/data/transport/tcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ class UserTimeout(Option):

#: User timeout.
timeout: 'timedelta'
#: Granularity (``G``): the timeout is in minutes if set, in seconds if not.
#: Granularity (``G``). The timeout is in minutes if set, in seconds if not.
granularity: 'bool'

if TYPE_CHECKING:
Expand Down Expand Up @@ -427,8 +427,8 @@ class MPTCPCapableFlag(Data):
deny_join: 'bool'
#: Reserved flags (``D`` to ``G``).
reserved: 'int'
#: HMAC algorithm flag (``H``): HMAC-SHA1 under version 0 (:rfc:`6824`),
#: HMAC-SHA256 under version 1 (:rfc:`8684`).
#: HMAC algorithm flag (``H``), selecting HMAC-SHA1 under version 0
#: (:rfc:`6824`) and HMAC-SHA256 under version 1 (:rfc:`8684`).
hsa: 'bool'

if TYPE_CHECKING:
Expand Down
4 changes: 2 additions & 2 deletions pcapkit/protocols/link/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

.. module:: pcapkit.protocols.link

:mod:`pcapkit.protocols.link` is collection of all protocols in
link layer, with detailed implementation and methods.
:mod:`pcapkit.protocols.link` is a collection of all protocols in
the link layer, with detailed implementation and methods.

"""
# TODO: Implements DSL, EAPOL, FDDI, ISDN, NDP, PPP.
Expand Down
13 changes: 7 additions & 6 deletions pcapkit/protocols/link/l2tp.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,16 @@
Selecting a Version
-------------------

Nothing *dispatches* on the version nibble, because only one version exists
-- but :meth:`L2TPv2.read <pcapkit.protocols.link.l2tpv2.L2TPv2.read>` does
**check** it, and refuses anything other than ``2``. That is the half of the
mechanism which is useful with one version implemented: it keeps v3 traffic on
port 1701 (:rfc:`3931` §4.1.2 shares the port, so this is ordinary capture
Nothing *dispatches* on the version nibble, because L2TPv2 is the only version
implemented -- but
:meth:`L2TPv2.read <pcapkit.protocols.link.l2tpv2.L2TPv2.read>` does **check**
it, and refuses anything other than ``2``. That is the half of the mechanism
which is useful with no other version implemented: it keeps v3 traffic on port
1701 (:rfc:`3931` §4.1.2 shares the port, so this is ordinary capture
traffic rather than a corner case) from being reported as v2 with a tunnel and
session ID read out of v3's Control Connection ID.

When a second version lands, the remaining half -- delegation rather than refusal
When another version lands, the remaining half -- delegation rather than refusal
-- already has a precedent in
:class:`~pcapkit.protocols.application.http.HTTP`, which reads a version and
delegates to a per-version class. L2TP is the easier case: HTTP has to
Expand Down
10 changes: 5 additions & 5 deletions pcapkit/protocols/link/l2tpv2.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@
------- ----- --------------------- ------------------------------------------
0 1 ``l2tp.flags.len`` Length
------- ----- --------------------- ------------------------------------------
0 2 Reserved (must be zero ``x00``)
0 2 Reserved (must be zero)
------- ----- --------------------- ------------------------------------------
0 4 ``l2tp.flags.seq`` Sequence
------- ----- --------------------- ------------------------------------------
0 5 Reserved (must be zero ``x00``)
0 5 Reserved (must be zero)
------- ----- --------------------- ------------------------------------------
0 6 ``l2tp.flags.offset`` Offset
------- ----- --------------------- ------------------------------------------
0 7 ``l2tp.flags.prio`` Priority
------- ----- --------------------- ------------------------------------------
1 8 Reserved (must be zero ``x00``)
1 8 Reserved (must be zero)
------- ----- --------------------- ------------------------------------------
1 12 ``l2tp.version`` Version (``2``)
------- ----- --------------------- ------------------------------------------
Expand Down Expand Up @@ -106,8 +106,8 @@ class L2TPv2(L2TP[Data_L2TP, Schema_L2TP],
``L2TPv3`` class rather than on this one. Binding *this* class there does
not work (:issue:`548`): over IP the v3 session header carries no
version nibble at all, so this class cannot recognise that the datagram
is not its own. See
:class:`~pcapkit.protocols.link.l2tp.L2TP` for the measurement.
is not its own. See :mod:`pcapkit.protocols.link.l2tp` for the
versions not implemented.

The class subclasses :class:`~pcapkit.protocols.link.link.Link` and so
reports ``layer == 'Link'`` even though it is carried inside UDP: a
Expand Down
11 changes: 5 additions & 6 deletions pcapkit/protocols/link/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
:class:`~pcapkit.protocols.link.arp.ARP`/:class:`~pcapkit.protocols.link.arp.InARP`,
:class:`~pcapkit.protocols.link.ethernet.Ethernet`,
:class:`~pcapkit.protocols.link.l2tp.L2TP`,
:class:`~pcapkit.protocols.link.loopback.Loopback`,
:class:`~pcapkit.protocols.link.vlan.VLAN`
and etc.
:class:`~pcapkit.protocols.link.loopback.Loopback` and
:class:`~pcapkit.protocols.link.vlan.VLAN`.

"""
import collections
Expand Down Expand Up @@ -117,8 +116,8 @@ def register(cls, code: 'Enum_EtherType', protocol: 'ModuleDescriptor[ProtocolBa
r"""Register a new protocol class.

Notes:
The full qualified class name of the new protocol class
should be as ``{protocol.module}.{protocol.name}``.
The fully qualified class name of the new protocol class
should be ``{protocol.module}.{protocol.name}``.

Arguments:
code: protocol code as in :class:`~pcapkit.const.reg.ethertype.EtherType`
Expand All @@ -137,7 +136,7 @@ def register(cls, code: 'Enum_EtherType', protocol: 'ModuleDescriptor[ProtocolBa
:meth:`ProtocolBase.register
<pcapkit.protocols.protocol.Protocol.register>` for the
guard this shares with ``register_protocol``, and for the
shipped descriptor a restore puts back (:issue:`1504`).
shipped descriptor that a restore puts back (:issue:`1504`).

.. versionchanged:: 1.3.0

Expand Down
10 changes: 10 additions & 0 deletions pcapkit/protocols/schema/link/arp.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,25 @@
class ARP(Schema):
"""Header schema for ARP packet."""

#: Hardware type.
htype: 'Enum_Hardware' = EnumField(length=2, namespace=Enum_Hardware)
#: Protocol type.
ptype: 'Enum_EtherType' = EnumField(length=2, namespace=Enum_EtherType)
#: Hardware address length.
hlen: 'int' = UInt8Field()
#: Protocol address length.
plen: 'int' = UInt8Field()
#: Operation code.
oper: 'Enum_Operation' = EnumField(length=2, namespace=Enum_Operation)
#: Sender hardware address.
sha: 'bytes' = BytesField(length=lambda pkt: pkt['hlen'])
#: Sender protocol address.
spa: 'bytes' = BytesField(length=lambda pkt: pkt['plen'])
#: Target hardware address.
tha: 'bytes' = BytesField(length=lambda pkt: pkt['hlen'])
#: Target protocol address.
tpa: 'bytes' = BytesField(length=lambda pkt: pkt['plen'])
#: Payload.
payload: 'bytes' = PayloadField()

if TYPE_CHECKING:
Expand Down
10 changes: 5 additions & 5 deletions pcapkit/protocols/schema/link/l2tp.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@
class FlagsType(TypedDict):
"""Flags of L2TP packet."""

#: Type of L2TP packet.
#: Type flag (``T``).
type: int
#: Length of L2TP packet.
#: Length flag (``L``).
len: int
#: Sequence number of L2TP packet.
#: Sequence flag (``S``).
seq: int
#: Offset size of L2TP packet.
#: Offset flag (``O``).
offset: int
#: Priority of L2TP packet.
#: Priority flag (``P``).
prio: int
#: Reserved bits 2 and 3 of L2TP packet.
reserved_1: int
Expand Down
4 changes: 2 additions & 2 deletions pcapkit/protocols/schema/transport/sctp.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ def nested_length(base: 'int') -> 'Callable[[dict[str, Any]], int]':
The chunks that carry a nested list -- INIT, INIT ACK, HEARTBEAT,
HEARTBEAT ACK, ABORT and ERROR -- deliberately have no separate
:class:`~pcapkit.corekit.fields.strings.PaddingField`, and fold the chunk's
trailing padding into the nested list's own span instead. There are two
reasons, and both matter:
trailing padding into the nested list's own span instead, which parsing and
construction each need for a reason of their own:

* On parsing, a sender is allowed by :rfc:`9260#section-3.2` to leave the
final parameter's padding out of the chunk length, so the padding has to
Expand Down
45 changes: 25 additions & 20 deletions pcapkit/protocols/schema/transport/tcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class Flags(TypedDict):
cwr: int
#: ECN-Echo.
ece: int
#: Urgent pointer.
#: Urgent.
urg: int
#: Acknowledgment.
ack: int
Expand Down Expand Up @@ -234,6 +234,10 @@ def mptcp_data_selector(pkt: 'dict[str, Any]') -> 'Field':
:class:`~pcapkit.protocols.schema.transport.tcp.MPTCP` subclass
instance.

Raises:
FieldError: If an MP_JOIN option is carried by a segment with
neither SYN nor ACK set.

"""
subtype = Enum_MPTCPOption.get(pkt['test']['subtype'])
pkt['test']['subtype'] = subtype
Expand All @@ -258,10 +262,13 @@ def mptcp_add_address_selector(pkt: 'dict[str, Any]') -> 'Field':
pkt: Packet data.

Returns:
* If the option length is one of the IPv4 lengths, a
:class:`~pcapkit.corekit.fields.ipaddress.IPv4AddressField` instance.
* If the option length is one of the IPv6 lengths, a
:class:`~pcapkit.corekit.fields.ipaddress.IPv6AddressField` instance.
An :class:`~pcapkit.corekit.fields.ipaddress.IPv4AddressField` instance
if the option length is one of the IPv4 lengths, or an
:class:`~pcapkit.corekit.fields.ipaddress.IPv6AddressField` instance if
it is one of the IPv6 lengths.

Raises:
FieldError: If the option length is neither.

Note:
:rfc:`8684` section 3.4.1 figure 12 has no IP version field: the
Expand Down Expand Up @@ -313,12 +320,11 @@ def mptcp_dss_ack_selector(pkt: 'dict[str, Any]') -> 'Field':
pkt: Packet data.

Returns:
* If ``A`` is clear, a :class:`~pcapkit.corekit.fields.misc.NoValueField`
instance -- the field is absent from the wire.
* If ``A`` is set and ``a`` is set, a
:class:`~pcapkit.corekit.fields.numbers.UInt64Field` instance.
* If ``A`` is set and ``a`` is clear, a
:class:`~pcapkit.corekit.fields.numbers.UInt32Field` instance.
A :class:`~pcapkit.corekit.fields.misc.NoValueField` instance if ``A``
is clear, since the field is then absent from the wire; otherwise a
:class:`~pcapkit.corekit.fields.numbers.UInt64Field` instance if ``a``
is set, or a :class:`~pcapkit.corekit.fields.numbers.UInt32Field`
instance if it is clear.

Note:
This is a :class:`~pcapkit.corekit.fields.misc.SwitchField` selector
Expand Down Expand Up @@ -367,12 +373,11 @@ def mptcp_dss_dsn_selector(pkt: 'dict[str, Any]') -> 'Field':
pkt: Packet data.

Returns:
* If ``M`` is clear, a :class:`~pcapkit.corekit.fields.misc.NoValueField`
instance -- the field is absent from the wire.
* If ``M`` is set and ``m`` is set, a
:class:`~pcapkit.corekit.fields.numbers.UInt64Field` instance.
* If ``M`` is set and ``m`` is clear, a
:class:`~pcapkit.corekit.fields.numbers.UInt32Field` instance.
A :class:`~pcapkit.corekit.fields.misc.NoValueField` instance if ``M``
is clear, since the field is then absent from the wire; otherwise a
:class:`~pcapkit.corekit.fields.numbers.UInt64Field` instance if ``m``
is set, or a :class:`~pcapkit.corekit.fields.numbers.UInt32Field`
instance if it is clear.

Note:
Identical in shape to :func:`mptcp_dss_ack_selector`; see that function's
Expand Down Expand Up @@ -774,9 +779,9 @@ class MPTCP(EnumSchema[Enum_MPTCPOption]):
#: MPTCP length.
length: 'int' = UInt8Field()

# NOTE: ``subtype`` stays an annotation rather than becoming a third real
# field alongside ``kind``/``length`` above -- deliberately, and the
# difference from those two is why. ``kind`` and ``length`` are each the
# NOTE: ``subtype`` stays an annotation rather than becoming a real field
# alongside ``kind``/``length`` above -- deliberately, and the difference
# from those fields is why. ``kind`` and ``length`` are each the
# *sole* source of their own octet: nothing else in the schema packs them,
# so declaring them as real fields was the only way to get them onto the
# wire at all. ``subtype`` is not like that: every concrete subclass
Expand Down
Loading
Loading