Source code for pcapkit.vendor.ipx.packet

# -*- coding: utf-8 -*-
# pylint: disable=wrong-import-position
"""IPX Packet Types
======================

.. module:: pcapkit.vendor.ipx.packet

This module contains the vendor crawler for **IPX Packet Types**,
which is automatically generating :class:`pcapkit.const.ipx.packet.Packet`.

"""

###############################################################################
# NOTE: fix duplicated name of ``socket``; restored in ``finally``, so a failed
# import does not lose the entry (#2589).
import sys

path = sys.path.pop(0)
try:
    import collections
    from typing import TYPE_CHECKING

    from pcapkit.vendor.default import Vendor

    if TYPE_CHECKING:
        from collections import Counter
finally:
    sys.path.insert(0, path)
###############################################################################

__all__ = ['Packet']

###############################################################################
# NOTE: maintained by hand, not crawled (#518, as #507): the Wikipedia table is gone
# from the live article, and IPX packet types are a closed Novell registry.
###############################################################################

#: IPX packet type registry, transcribed from the last revision of the Wikipedia
#: article that still carried the table,
#: https://en.wikipedia.org/w/index.php?title=Internetwork_Packet_Exchange&oldid=1368657333
#:
#: Maps a packet type to the enumeration name it takes and the comment rendered
#: above it. Names go through :meth:`~Vendor.rename`, so the generated member is
#: the :meth:`~Vendor.safe_name` of the first element; comments are stored as the
#: scrape rendered them, reStructuredText markup and all, since no Wikipedia
#: cell text remains for a scraping ``process()`` to rework.
#:
#: Every value below is independently corroborated by Wireshark's IPX dissector,
#: ``epan/dissectors/packet-ipx.h`` (fetched 2026-09-19), which defines
#: ``IPX_PACKET_TYPE_IPX 0``, ``_RIP 1``, ``_ECHO 2``, ``_ERROR 3``, ``_PEP 4``,
#: ``_SPX 5``, ``_NCP 17`` and ``_WANBCAST 20`` -- the same values in the
#: same order. Types 1-5 are inherited from Xerox XNS IDP, which IPX was derived
#: from, and -- type 4 apart -- no RFC assigns them. The note on each row below
#: says which sources do and do not carry its number.
DATA = {
    # NOTE: no protocol assignment but the ``type`` field's default; "Unknown" is
    # the archived revision's word alone, and Wireshark's is ``IPX``.
    0: ('Unknown', 'Unknown'),

    # :rfc:`1582` ("Extensions to RIP to Support Demand Circuits", 1994) and
    # :rfc:`2091` ("Triggered Extensions to RIP to Support Demand Circuits",
    # 1997) are the citation the article itself carried, and they do describe
    # IPX RIP -- "the Routing Information Protocol (RIP) which runs over the
    # Internetwork Packet Exchange (IPX) protocol using socket number 453h".
    # Note honestly that they extend IPX RIP rather than assign it packet type
    # 1; for the assignment they defer to Novell, "IPX Router Specification",
    # Version 1.10, October 1992, which :rfc:`1582` lists as reference [3].
    1: ('RIP', '``RIP``, Routing Information Protocol ([:rfc:`1582`], [:rfc:`2091`])'),

    # XNS IDP inheritances. The archived revision is the only source found for
    # these two names: no RFC and no reachable Novell document lists
    # either against a packet-type number. Wireshark corroborates the values as
    # ``ECHO 2`` and ``ERROR 3``.
    2: ('Echo Packet', 'Echo Packet'),
    3: ('Error Packet', 'Error Packet'),

    # NOTE: the best-sourced row: :rfc:`1362`, :rfc:`1551`, :rfc:`1634`, :rfc:`1791`
    # and :rfc:`1132` all give packet type 4.
    4: ('PEP', '``PEP``, Packet Exchange Protocol, used for SAP (Service Advertising Protocol)'),

    # :rfc:`1553` names the protocol -- "The Sequenced Packet Exchange (SPX) is
    # the reliable connection-based transport protocol commonly used by
    # applications" -- but not its packet-type number, which rests on Wireshark
    # and the archived revision.
    5: ('SPX', '``SPX``, Sequenced Packet Exchange'),

    # :rfc:`1553` names this one too -- "the Netware Core Protocol (NCP), which
    # is used for file server access" -- and again without the number. 17
    # (0x11) rests on Wireshark and the archived revision.
    17: ('NCP', '``NCP``, NetWare Core Protocol'),

    # NOTE: :rfc:`1132` assigns 0x14; ``[4]`` is Wikipedia's footnote marker, kept verbatim,
    # as renaming :attr:`~pcapkit.const.ipx.packet.Packet.Broadcast_4` breaks it (#518).
    20: ('Broadcast[4]', 'Broadcast[4]'),
}  # type: dict[int, tuple[str, str]]


[docs] class Packet(Vendor): """IPX Packet Types""" #: Value limit checker. FLAG = 'isinstance(value, int) and 0 <= value <= 255' def request(self) -> 'dict[int, tuple[str, str]]': # type: ignore[override] # pylint: disable=arguments-differ """Fetch registry data. Returns: Registry data (:data:`~pcapkit.vendor.ipx.packet.DATA`). """ return DATA def count(self, data: 'dict[int, tuple[str, str]]') -> 'Counter[str]': # type: ignore[override] """Count field records. Args: data: Registry data. Returns: Field recordings. """ return collections.Counter(self.safe_name(name) for name, _ in data.values()) def process(self, data: 'dict[int, tuple[str, str]]') -> 'tuple[list[str], list[str]]': # type: ignore[override] """Process registry data. Args: data: Registry data. Returns: Enumeration fields and missing fields. """ enum = [] # type: list[str] miss = [ "return cls._unregistered_member(value, 'Unassigned')", ] for code, (name, desc) in data.items(): pval = str(code) renm = self.rename(name, pval) enum.append(f'#: {self.wrap_comment(desc)}\n {renm} = {pval}') return enum, miss
if __name__ == '__main__': sys.exit(Packet()) # type: ignore[arg-type]