diff --git a/docs/source/pcapkit/protocols/link/link.rst b/docs/source/pcapkit/protocols/link/link.rst index 6babae7922..791dfb6ac4 100644 --- a/docs/source/pcapkit/protocols/link/link.rst +++ b/docs/source/pcapkit/protocols/link/link.rst @@ -15,6 +15,9 @@ which is a base class for link layer protocols, e.g. :class:`~pcapkit.protocols. .. autoproperty:: layer .. automethod:: register + .. automethod:: from_data + + .. automethod:: __post_init__ .. autoattribute:: __layer__ .. autoattribute:: __proto__ diff --git a/docs/source/pcapkit/protocols/transport/sctp.rst b/docs/source/pcapkit/protocols/transport/sctp.rst index 24e9661739..7c66c5346d 100644 --- a/docs/source/pcapkit/protocols/transport/sctp.rst +++ b/docs/source/pcapkit/protocols/transport/sctp.rst @@ -320,6 +320,10 @@ Header Schemas :members: :show-inheritance: +.. autoclass:: pcapkit.protocols.schema.transport.sctp.ChunkListField + :members: + :show-inheritance: + Type Stubs ~~~~~~~~~~ @@ -335,7 +339,10 @@ Auxiliary Functions ~~~~~~~~~~~~~~~~~~~ .. autofunction:: pcapkit.protocols.schema.transport.sctp.padding_length +.. autofunction:: pcapkit.protocols.schema.transport.sctp.pre_pack_padding +.. autofunction:: pcapkit.protocols.schema.transport.sctp.bounded .. autofunction:: pcapkit.protocols.schema.transport.sctp.nested_length +.. autofunction:: pcapkit.protocols.schema.transport.sctp.whole_chunks_length Data Models ----------- diff --git a/docs/source/pcapkit/protocols/transport/tcp.rst b/docs/source/pcapkit/protocols/transport/tcp.rst index 2f8645a315..dd64ffc387 100644 --- a/docs/source/pcapkit/protocols/transport/tcp.rst +++ b/docs/source/pcapkit/protocols/transport/tcp.rst @@ -17,7 +17,7 @@ Octets Bits Name Description 4 32 ``tcp.seq`` Sequence Number 8 64 ``tcp.ack`` Acknowledgement Number (if ACK set) 12 96 ``tcp.hdr_len`` Data Offset - 12 100 Reserved (must be ``\x00``) + 12 100 ``tcp.flags.reserved`` Reserved (must be ``\x00``) 12 103 ``tcp.flags.ns`` ECN Concealment Protection (NS) 13 104 ``tcp.flags.cwr`` Congestion Window Reduced (CWR) 13 105 ``tcp.flags.ece`` ECN-Echo (ECE) @@ -187,6 +187,10 @@ Header Schemas :members: :show-inheritance: +.. autoclass:: pcapkit.protocols.schema.transport.tcp.SACKBlock + :members: + :show-inheritance: + .. autoclass:: pcapkit.protocols.schema.transport.tcp.Echo :members: :show-inheritance: @@ -251,6 +255,10 @@ Header Schemas :members: :show-inheritance: +.. autoclass:: pcapkit.protocols.schema.transport.tcp._MPTCP + :members: + :show-inheritance: + .. autoclass:: pcapkit.protocols.schema.transport.tcp.MPTCP :members: :show-inheritance: @@ -372,6 +380,7 @@ Auxiliary Functions .. autofunction:: pcapkit.protocols.schema.transport.tcp.mptcp_data_selector .. autofunction:: pcapkit.protocols.schema.transport.tcp.mptcp_add_address_selector +.. autofunction:: pcapkit.protocols.schema.transport.tcp.mptcp_dss_checksum .. autofunction:: pcapkit.protocols.schema.transport.tcp.mptcp_dss_ack_selector .. autofunction:: pcapkit.protocols.schema.transport.tcp.mptcp_dss_dsn_selector @@ -420,6 +429,10 @@ Data Models :members: :show-inheritance: +.. autoclass:: pcapkit.protocols.data.transport.tcp.SACKBlock + :members: + :show-inheritance: + .. autoclass:: pcapkit.protocols.data.transport.tcp.Echo :members: :show-inheritance: @@ -496,6 +509,10 @@ Data Models :members: :show-inheritance: +.. autoclass:: pcapkit.protocols.data.transport.tcp.MPTCPCapableFlag + :members: + :show-inheritance: + .. autoclass:: pcapkit.protocols.data.transport.tcp.MPTCPJoin :members: :show-inheritance: diff --git a/docs/source/pcapkit/protocols/transport/transport.rst b/docs/source/pcapkit/protocols/transport/transport.rst index dbed2373ef..47cdbaaf56 100644 --- a/docs/source/pcapkit/protocols/transport/transport.rst +++ b/docs/source/pcapkit/protocols/transport/transport.rst @@ -18,6 +18,9 @@ which is a base class for transport layer protocols, eg. .. automethod:: register .. automethod:: analyze + .. automethod:: from_data + + .. automethod:: __post_init__ .. automethod:: _make_port .. automethod:: _decode_next_layer diff --git a/pcapkit/protocols/link/arp.py b/pcapkit/protocols/link/arp.py index 3be2821700..ba00d309fc 100644 --- a/pcapkit/protocols/link/arp.py +++ b/pcapkit/protocols/link/arp.py @@ -85,6 +85,15 @@ class ARP(Link[Data_ARP, Schema_ARP], - Dynamic Reverse Address Resolution Protocol (:class:`~pcapkit.protocols.application.rarp.DRARP`) [:rfc:`1931`] - Inverse Address Resolution Protocol (:class:`~pcapkit.protocols.link.arp.InARP`) [:rfc:`2390`] + .. versionchanged:: 1.5.0 + + :meth:`make` refuses a :obj:`bool` protocol address (:issue:`540`), packs + a non-IP protocol address from its *hex* text rather than as ASCII, and + checks every address against ``hlen`` and ``plen`` (:issue:`1139`). An + Ethernet ``hlen`` other than 6 rebuilds (:issue:`1205`), and + :meth:`read` takes an IPv4 or IPv6 protocol address only when both + ``ptype`` and the address length agree (:issue:`1206`). + """ #: Name of corresponding protocol. _name: 'Literal["Address Resolution Protocol", "Inverse Address Resolution Protocol", "Reverse Address Resolution Protocol", "Dynamic Reverse Address Resolution Protocol"]' # pylint: disable=line-too-long @@ -484,7 +493,14 @@ def _make_proto_resolve(self, addr: 'IPv4Address | IPv6Address | str | bytes', p class InARP(ARP, schema=Schema_ARP, data=Data_ARP): - """This class implements Inverse Address Resolution Protocol.""" + """This class implements Inverse Address Resolution Protocol. + + .. versionchanged:: 1.5.0 + + Parses with the ARP schema rather than falling back to the raw one + (:issue:`1204`). + + """ ########################################################################## # Methods. diff --git a/pcapkit/protocols/link/c_tag.py b/pcapkit/protocols/link/c_tag.py index 0b138c656a..7beaf8bcea 100644 --- a/pcapkit/protocols/link/c_tag.py +++ b/pcapkit/protocols/link/c_tag.py @@ -44,7 +44,13 @@ # the base class's pair. c.f. :class:`~pcapkit.protocols.application.rarp.RARP`, which # restates them for the same reason. class C_Tag(VLAN, schema=Schema_VLAN, data=Data_VLAN): - """This class implements 802.1Q Customer VLAN Tag Type.""" + """This class implements 802.1Q Customer VLAN Tag Type. + + .. versionadded:: 1.5.0 + + Takes over the customer tag from :class:`~pcapkit.protocols.link.vlan.VLAN`. + + """ ########################################################################## # Properties. @@ -65,7 +71,7 @@ def alias(self) -> 'Literal["802.1Q"]': #: class-name default -- a rename must not silently move the output key. @property def info_name(self) -> 'Literal["c_tag"]': - """Key name of the :attr:`info` dict.""" + """Key name of the :attr:`~pcapkit.protocols.protocol.Protocol.info` dict.""" return 'c_tag' ########################################################################## diff --git a/pcapkit/protocols/link/ethernet.py b/pcapkit/protocols/link/ethernet.py index 1de0aa45ba..f18672f103 100644 --- a/pcapkit/protocols/link/ethernet.py +++ b/pcapkit/protocols/link/ethernet.py @@ -12,15 +12,15 @@ .. table:: - ====== ===== ============ ========================= - Octets Bits Name Description - ====== ===== ============ ========================= - 0 0 ``eth.dst`` Destination MAC Address - ------ ----- ------------ ------------------------- - 6 48 ``eth.src`` Source MAC Address - ------ ----- ------------ ------------------------- - 12 96 ``eth.type`` Protocol (Internet Layer) - ====== ===== ============ ========================= + ====== ===== ================= ========================= + Octets Bits Name Description + ====== ===== ================= ========================= + 0 0 ``ethernet.dst`` Destination MAC Address + ------ ----- ----------------- ------------------------- + 6 48 ``ethernet.src`` Source MAC Address + ------ ----- ----------------- ------------------------- + 12 96 ``ethernet.type`` Protocol (Internet Layer) + ====== ===== ================= ========================= .. [*] https://en.wikipedia.org/wiki/Ethernet diff --git a/pcapkit/protocols/link/l2tp.py b/pcapkit/protocols/link/l2tp.py index f24ed274c7..fa25bb45d5 100644 --- a/pcapkit/protocols/link/l2tp.py +++ b/pcapkit/protocols/link/l2tp.py @@ -120,6 +120,11 @@ class L2TP(Link[_PT, _ST], Generic[_PT, _ST]): # pylint: disable=abstract-metho defined here, so the class cannot be instantiated. Bind a version, never this class. + .. versionchanged:: 1.5.0 + + Became an abstract base for the family; its version-2 parsing moved to + :class:`~pcapkit.protocols.link.l2tpv2.L2TPv2`. + """ ########################################################################## @@ -134,7 +139,7 @@ class L2TP(Link[_PT, _ST], Generic[_PT, _ST]): # pylint: disable=abstract-metho #: every consumer would have to know the version to find the data. @property def info_name(self) -> 'Literal["l2tp"]': - """Key name of the :attr:`info` dict.""" + """Key name of the :attr:`~pcapkit.protocols.protocol.Protocol.info` dict.""" return 'l2tp' ########################################################################## diff --git a/pcapkit/protocols/link/l2tpv2.py b/pcapkit/protocols/link/l2tpv2.py index ecaee75975..120c8b3906 100644 --- a/pcapkit/protocols/link/l2tpv2.py +++ b/pcapkit/protocols/link/l2tpv2.py @@ -33,7 +33,7 @@ ------- ----- --------------------- ------------------------------------------ 1 8 Reserved (must be zero ``x00``) ------- ----- --------------------- ------------------------------------------ - 1 12 ``l2tp.ver`` Version (``2``) + 1 12 ``l2tp.version`` Version (``2``) ------- ----- --------------------- ------------------------------------------ 2 16 ``l2tp.length`` Length (optional by ``len``) ------- ----- --------------------- ------------------------------------------ @@ -93,6 +93,12 @@ class L2TPv2(L2TP[Data_L2TP, Schema_L2TP], (:rfc:`3931` ยง4.1.2 shares the port) degrades to :class:`~pcapkit.protocols.misc.raw.Raw` instead of being reported as v2. + .. versionadded:: 1.5.0 + + Takes over the version-2 parsing that + :class:`~pcapkit.protocols.link.l2tp.L2TP` carried, and refuses a version + nibble other than ``2`` (:issue:`548`). + Note: IANA protocol number 115 (``L2TP``) is deliberately left unbound. It references :rfc:`3931`, i.e. **L2TPv3**, whose session and control diff --git a/pcapkit/protocols/link/link.py b/pcapkit/protocols/link/link.py index 2ed84de434..782f010a52 100644 --- a/pcapkit/protocols/link/link.py +++ b/pcapkit/protocols/link/link.py @@ -135,7 +135,7 @@ def register(cls, code: 'Enum_EtherType', protocol: 'ModuleDescriptor[ProtocolBa replacement so a caller can tell *what* was lost. Fires only when the incumbent differs from the replacement -- see :meth:`ProtocolBase.register - ` for the + ` for the guard this shares with ``register_protocol``, and for the shipped descriptor a restore puts back (:issue:`1504`). @@ -156,7 +156,7 @@ def from_data(cls, data: '_PT | dict[str, Any]', **kwargs: 'Any') -> 'Self': Args: data: Protocol data. **kwargs: Construction keywords, as for :meth:`ProtocolBase.from_data - `. + `. Returns: Protocol instance, cut back to what was captured when the header @@ -179,9 +179,9 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, **kwargs: Arbitrary keyword arguments. Notes: - A header the data ends inside keeps that in its :attr:`info`, so - that :meth:`from_data` rebuilds only what was captured - (:issue:`1458`). + A header the data ends inside keeps that in its + :attr:`~pcapkit.protocols.protocol.Protocol.info`, so that + :meth:`from_data` rebuilds only what was captured (:issue:`1458`). """ super().__post_init__(file, length, **kwargs) # type: ignore[arg-type] diff --git a/pcapkit/protocols/link/loopback.py b/pcapkit/protocols/link/loopback.py index 88c9961f9d..f197977ce7 100644 --- a/pcapkit/protocols/link/loopback.py +++ b/pcapkit/protocols/link/loopback.py @@ -85,7 +85,8 @@ class Loopback(Link[Data_Loopback, Schema_Loopback], ``alias`` it was dispatched with; for ``LINKTYPE_NULL``, which a frame parsed on its own is read as, the byte order is read from the octets themselves (see :func:`family_byteorder`). Either way it is kept in - :attr:`info`, and :meth:`from_data ` + :attr:`~pcapkit.protocols.protocol.Protocol.info`, and + :meth:`from_data ` reads the family back in that byte order rather than inferring it again. The address families are those of the BSD socket API, whose ``AF_INET6`` @@ -179,7 +180,8 @@ def read(self, length: 'Optional[int]' = None, *, alias: 'Optional[int]' = None, ``LINKTYPE_LOOP`` reads the family in network byte order, and anything else as ``LINKTYPE_NULL``. byteorder: Byte order to read the family in, ahead of ``alias``. - :meth:`make` is handed the one :attr:`info` holds by + :meth:`make` is handed the one + :attr:`~pcapkit.protocols.protocol.Protocol.info` holds by :meth:`from_data `, and it reaches here too, so a rebuild reads the family as it was parsed rather than inferring it again. diff --git a/pcapkit/protocols/link/s_tag.py b/pcapkit/protocols/link/s_tag.py index febd8e1734..140c03884c 100644 --- a/pcapkit/protocols/link/s_tag.py +++ b/pcapkit/protocols/link/s_tag.py @@ -45,6 +45,8 @@ class S_Tag(VLAN, schema=Schema_VLAN, data=Data_VLAN): the only thing distinguishing this class from :class:`~pcapkit.protocols.link.c_tag.C_Tag` by name. + .. versionadded:: 1.5.0 + """ ########################################################################## @@ -66,7 +68,7 @@ def alias(self) -> 'Literal["802.1ad"]': #: and customer tag apart in the parsed info dict. @property def info_name(self) -> 'Literal["s_tag"]': - """Key name of the :attr:`info` dict.""" + """Key name of the :attr:`~pcapkit.protocols.protocol.Protocol.info` dict.""" return 's_tag' ########################################################################## diff --git a/pcapkit/protocols/link/vlan.py b/pcapkit/protocols/link/vlan.py index ab397cf10d..34f687a53e 100644 --- a/pcapkit/protocols/link/vlan.py +++ b/pcapkit/protocols/link/vlan.py @@ -82,14 +82,22 @@ class VLAN(Link[Data_VLAN, Schema_VLAN], # pylint: disable=abstract-method The class implements the whole of the tag -- both parsing and construction -- since the customer and service tags are byte-for-byte identical. What it deliberately leaves to its subclasses is only how the tag *names* itself: - :attr:`name`, :attr:`alias` and + :attr:`~pcapkit.protocols.protocol.Protocol.name`, + :attr:`~pcapkit.protocols.protocol.Protocol.alias` and :attr:`~pcapkit.protocols.protocol.Protocol.info_name`. It is abstract for the same reason :class:`~pcapkit.protocols.internet.ip.IP` is: :attr:`~pcapkit.protocols.protocol.Protocol.name` is declared abstract by :class:`~pcapkit.protocols.protocol.ProtocolBase` and is not defined here, so the class cannot be instantiated. Bind - :class:`C_Tag` or :class:`S_Tag`, never this class. + :class:`~pcapkit.protocols.link.c_tag.C_Tag` or + :class:`~pcapkit.protocols.link.s_tag.S_Tag`, never this class. + + .. versionchanged:: 1.5.0 + + Became an abstract base. The 802.1Q customer tag it implemented, with its + ``name``, ``alias`` and ``info_name``, moved to + :class:`~pcapkit.protocols.link.c_tag.C_Tag`. """ diff --git a/pcapkit/protocols/schema/transport/sctp.py b/pcapkit/protocols/schema/transport/sctp.py index 2366f1f3ef..6e9ce825ae 100644 --- a/pcapkit/protocols/schema/transport/sctp.py +++ b/pcapkit/protocols/schema/transport/sctp.py @@ -123,8 +123,9 @@ def pre_pack_padding(schema: 'Schema', packet: 'dict[str, Any]') -> 'None': A schema whose padding was captured short -- only the last chunk of a packet can be -- carries the width as captured under ``__padding__`` in its - ``__dict__``, set by :func:`~pcapkit.protocols.transport.sctp._restore_padding` - from the chunk's ``padding`` as parsed (:issue:`1474`). The key is written to + ``__dict__``, set by ``_restore_padding`` in + :mod:`pcapkit.protocols.transport.sctp` from the chunk's ``padding`` as + parsed (:issue:`1474`). The key is written to ``packet`` for *every* schema, ``None`` when there is no record, since :meth:`Schema.pack ` shares one ``packet`` mapping across siblings and a record left behind by one would diff --git a/pcapkit/protocols/schema/transport/tcp.py b/pcapkit/protocols/schema/transport/tcp.py index e440ffdf4e..4901577ba4 100644 --- a/pcapkit/protocols/schema/transport/tcp.py +++ b/pcapkit/protocols/schema/transport/tcp.py @@ -1058,7 +1058,7 @@ def __init__(self, kind: 'Enum_Option', length: 'int', test: 'MPTCPSubtype', key @schema_final class FastOpenCookie(Option, code=Enum_Option.TCP_Fast_Open_Cookie): - """"Header schema for TCP Fast Open option.""" + """Header schema for TCP Fast Open option.""" #: Cookie. cookie: 'bytes' = ConditionalField( diff --git a/pcapkit/protocols/schema/transport/udp.py b/pcapkit/protocols/schema/transport/udp.py index 8df891fb8d..b6d127deaa 100644 --- a/pcapkit/protocols/schema/transport/udp.py +++ b/pcapkit/protocols/schema/transport/udp.py @@ -32,7 +32,7 @@ class UDP(Schema): #: Checksum of UDP packet. checksum: 'bytes' = BytesField(length=2) #: Payload. A Length below the header's own 8 octets leaves the length - #: negative, which takes the rest of the datagram, as before. + #: negative, which takes the rest of the datagram. payload: 'bytes' = PayloadField(length=lambda pkt: pkt['len'] - 8) #: Octets captured past the Length field, c.f. #: :attr:`IPv4.trailer `. diff --git a/pcapkit/protocols/transport/sctp.py b/pcapkit/protocols/transport/sctp.py index ed19dc8b96..a3fee39e0d 100644 --- a/pcapkit/protocols/transport/sctp.py +++ b/pcapkit/protocols/transport/sctp.py @@ -335,7 +335,7 @@ class SCTP(Transport[Data_SCTP, Schema_SCTP], :class:`~pcapkit.protocols.misc.raw.Raw`. It is registered so that the PPID is *named* in the protochain rather than reported as an unassigned number. - This class currently supports parsing of the following SCTP chunks, which + This class supports parsing of the following SCTP chunks, which are directly mapped to the :class:`pcapkit.const.sctp.chunk.Chunk` enumeration: @@ -390,7 +390,7 @@ class SCTP(Transport[Data_SCTP, Schema_SCTP], :meth:`~pcapkit.protocols.transport.sctp.SCTP._read_chunk_donone`, which records the chunk's raw flags and value verbatim rather than raising. - This class currently supports parsing of the following chunk parameters, + This class supports parsing of the following chunk parameters, which are directly mapped to the :class:`pcapkit.const.sctp.parameter.Parameter` enumeration: @@ -425,13 +425,15 @@ class SCTP(Transport[Data_SCTP, Schema_SCTP], - :meth:`~pcapkit.protocols.transport.sctp.SCTP._read_param_addrtypes` - :meth:`~pcapkit.protocols.transport.sctp.SCTP._make_param_addrtypes` - This class currently supports parsing of all thirteen error causes defined + This class supports parsing of all thirteen error causes defined by :rfc:`9260#section-3.3.10`, which are directly mapped to the :class:`pcapkit.const.sctp.cause_code.CauseCode` enumeration; see :attr:`self.__cause__ ` for the mapping. Unknown cause codes fall through to :meth:`~pcapkit.protocols.transport.sctp.SCTP._read_cause_donone`. + .. versionadded:: 1.5.0 + """ ########################################################################## @@ -992,8 +994,7 @@ def _read_sctp_chunks(self) -> 'Chunks': Raises: ProtocolError: If a raw chunk given to :meth:`make` is not a whole chunk. Parsed, its octets would fall to the trailer rather than - to the chunk list, so it is rejected, as it was before - :issue:`1468`. + to the chunk list, so it is rejected (:issue:`1468`). """ chunks = OrderedMultiDict() # type: Chunks diff --git a/pcapkit/protocols/transport/tcp.py b/pcapkit/protocols/transport/tcp.py index 795db663eb..cc697ed0eb 100644 --- a/pcapkit/protocols/transport/tcp.py +++ b/pcapkit/protocols/transport/tcp.py @@ -32,7 +32,7 @@ 14 112 ``tcp.window_size`` Size of Receive Window 16 128 ``tcp.checksum`` Checksum 18 144 ``tcp.urgent_pointer`` Urgent Pointer (if URG set) - 20 160 ``tcp.opt`` TCP Options (if data offset > 5) + 20 160 ``tcp.options`` TCP Options (if data offset > 5) ======= ========= ========================= ======================================= .. [*] https://en.wikipedia.org/wiki/Transmission_Control_Protocol @@ -172,7 +172,7 @@ class TCP(Transport[Data_TCP, Schema_TCP], schema=Schema_TCP, data=Data_TCP): """This class implements Transmission Control Protocol. - This class currently supports parsing of the following protocols, which are + This class supports parsing of the following protocols, which are registered in the :attr:`self.__proto__ ` attribute: @@ -190,7 +190,7 @@ class TCP(Transport[Data_TCP, Schema_TCP], * - 8080 - :class:`pcapkit.protocols.application.http.HTTP` - This class currently supports parsing of the following TCP options, + This class supports parsing of the following TCP options, which are directly mapped to the :class:`pcapkit.const.tcp.option.Option` enumeration: @@ -267,7 +267,7 @@ class TCP(Transport[Data_TCP, Schema_TCP], - :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_fastopen` - :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_fastopen` - This class currently supports parsing of the following Multipath TCP options, + This class supports parsing of the following Multipath TCP options, which are directly mapped to the :class:`pcapkit.const.tcp.mp_tcp_option.MPTCPOption` enumeration: @@ -302,6 +302,30 @@ class TCP(Transport[Data_TCP, Schema_TCP], - :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mptcp_fastclose` - :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mptcp_fastclose` + .. versionchanged:: 1.5.0 + + * :meth:`read` reports the flags of a flagless segment as an empty + :class:`~pcapkit.const.tcp.flags.Flags` rather than a plain + :obj:`int` (:issue:`616`). + * A constructed MPTCP option sets its ``subtype`` (:issue:`566`), and + MP_CAPABLE is written at the :rfc:`8684` lengths (:issue:`567`) and + read at all five of them (:issue:`1042`). + * A rebuild keeps what was parsed: the option order and padding + (:issue:`1151`), the reserved bits of the header and of the POCSP, + Quick-Start and MPTCP options (:issue:`1211`, :issue:`1212`), the + octets after EOOL (:issue:`1218`), the User Timeout granularity + (:issue:`1219`), and the MP_CAPABLE ``C`` flag and ``D``-``G`` bits + (:issue:`1220`). + * :meth:`read` refuses a Data Offset that declares more header than the + data holds, rather than reading the missing octets as zeros + (:issue:`1404`). + * MPTCP parsing follows the flags and the option length: MP_FAIL reads + its DSN at the right offset (:issue:`1213`), an unknown subtype stays + within its option (:issue:`1214`), DSS sizes its Data ACK and DSN from + the ``a`` and ``m`` flags and reads a checksum only when one is + present (:issue:`1215`, :issue:`1216`), and ADD_ADDR parses the + :rfc:`8684` layout (:issue:`1217`). + """ ########################################################################## @@ -990,7 +1014,7 @@ def _read_mode_sack(self, schema: 'Schema_SACK', *, options: 'Option') -> 'Data_ Parsed option data. Raises: - ProtocolError: If length is **NOT** multiply of ``8`` plus ``2``. + ProtocolError: If length is **NOT** a multiple of ``8`` plus ``2``. """ if (schema.length - 2) % 8 != 0: @@ -1107,7 +1131,7 @@ def _read_mode_ts(self, schema: 'Schema_Timestamps', *, options: 'Option') -> 'D return data def _read_mode_poc(self, schema: 'Schema_PartialOrderConnectionPermitted', *, options: 'Option') -> 'Data_PartialOrderConnectionPermitted': # pylint: disable=unused-argument - """Read TCP partial order connection service profile option. + """Read TCP partial order connection permitted option. Structure of TCP ``POC-Permitted`` option [:rfc:`1693`][:rfc:`6247`]: diff --git a/pcapkit/protocols/transport/transport.py b/pcapkit/protocols/transport/transport.py index 90c22b3b69..008ad78341 100644 --- a/pcapkit/protocols/transport/transport.py +++ b/pcapkit/protocols/transport/transport.py @@ -99,7 +99,7 @@ def register(cls, code: 'int', protocol: 'ModuleDescriptor[ProtocolBase] | Type[ :class:`~pcapkit.corekit.module.ModuleDescriptor` counts as different from the class it names. See :meth:`ProtocolBase.register - ` for the + ` for the guard this shares with ``register_protocol``, and for the shipped descriptor a restore puts back (:issue:`1504`). @@ -163,7 +163,7 @@ def from_data(cls, data: '_PT | dict[str, Any]', **kwargs: 'Any') -> 'Self': Args: data: Protocol data. **kwargs: Construction keywords, as for :meth:`ProtocolBase.from_data - `. + `. Returns: Protocol instance, cut back to what was captured when the header @@ -186,9 +186,9 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, **kwargs: Arbitrary keyword arguments. Notes: - A header the data ends inside keeps that in its :attr:`info`, so - that :meth:`from_data` rebuilds only what was captured - (:issue:`1458`). + A header the data ends inside keeps that in its + :attr:`~pcapkit.protocols.protocol.Protocol.info`, so that + :meth:`from_data` rebuilds only what was captured (:issue:`1458`). """ super().__post_init__(file, length, **kwargs) # type: ignore[arg-type] @@ -209,16 +209,17 @@ def _make_port(port: 'Enum_AppType | int', distinguishes e.g. TCP/80 from UDP/80 Returns: - The :class:`~pcapkit.const.reg.apptype.AppType` for ``port``. + The :class:`~pcapkit.const.reg.apptype.apptype.AppType` for ``port``. Important: - :meth:`self.make ` accepts a bare :obj:`int` for a - port, but the schema field converts it only on the way *out* (in + :meth:`self.make ` accepts + a bare :obj:`int` for a port, but the schema field converts it only + on the way *out* (in :meth:`PortEnumField.pre_process `), so the schema attribute keeps whatever it was handed. Normalising here makes a constructed packet carry the same - :class:`~pcapkit.const.reg.apptype.AppType` as a parsed one, so + :class:`~pcapkit.const.reg.apptype.apptype.AppType` as a parsed one, so reading ``.port`` off it works on both paths. """ diff --git a/pcapkit/protocols/transport/udp.py b/pcapkit/protocols/transport/udp.py index d3b6f1b830..6b0e7f60f3 100644 --- a/pcapkit/protocols/transport/udp.py +++ b/pcapkit/protocols/transport/udp.py @@ -48,7 +48,7 @@ class UDP(Transport[Data_UDP, Schema_UDP], schema=Schema_UDP, data=Data_UDP): """This class implements User Datagram Protocol. - This class currently supports parsing of the following protocols, which are + This class supports parsing of the following protocols, which are registered in the :attr:`self.__proto__ ` attribute: @@ -71,6 +71,14 @@ class UDP(Transport[Data_UDP, Schema_UDP], :attr:`TCP.__proto__ ` binds the same class for its HTTP ports. + .. versionchanged:: 1.5.0 + + :meth:`make` takes ``total_length``, which a + :meth:`~pcapkit.protocols.protocol.Protocol.from_data` rebuild + passes so that a truncated capture keeps its declared Length + (:issue:`1155`), and ``trailer``, so that the octets past the Length + field rebuild as captured (:issue:`1461`). + """ ##########################################################################