# -*- coding: utf-8 -*-
"""data model for IPv4 protocol"""
from typing import TYPE_CHECKING
from pcapkit.const.ipv4.option_class import OptionClass
from pcapkit.const.ipv4.tos_del import ToSDelay
from pcapkit.corekit.infoclass import info_final
from pcapkit.protocols.data.data import Data
from pcapkit.protocols.data.protocol import Protocol
if TYPE_CHECKING:
from datetime import timedelta
from ipaddress import IPv4Address
from typing import Any, Optional
from typing_extensions import Literal
from pcapkit.const.ipv4.classification_level import ClassificationLevel
from pcapkit.const.ipv4.option_number import OptionNumber
from pcapkit.const.ipv4.protection_authority import ProtectionAuthority
from pcapkit.const.ipv4.qs_function import QSFunction
from pcapkit.const.ipv4.router_alert import RouterAlert
from pcapkit.const.ipv4.tos_ecn import ToSECN
from pcapkit.const.ipv4.tos_pre import ToSPrecedence
from pcapkit.const.ipv4.tos_rel import ToSReliability
from pcapkit.const.ipv4.tos_thr import ToSThroughput
from pcapkit.const.ipv4.ts_flag import TSFlag
from pcapkit.const.reg.transtype import TransType
from pcapkit.corekit.infoclass import OrderedMultiInfo
from pcapkit.corekit.multidict import OrderedMultiDict
__all__ = [
'IPv4',
'ToSField', 'Flags',
'OptionType',
'UnassignedOption', 'EOOLOption', 'NOPOption',
'SECOption', 'LSROption', 'TSOption',
'ESECOption', 'RROption', 'SIDOption',
'SSROption', 'MTUPOption', 'MTUROption',
'TROption', 'RTRALTOption', 'QSOption',
'QuickStartRequestOption', 'QuickStartReportOption',
]
[docs]
@info_final
class ToSField(Data):
"""Data model for IPv4 ToS fields.
Important:
Due to the reserved keyword conflict, please use
:meth:`~pcapkit.corekit.infoclass.Info.from_dict`
to create an instance of this data model.
"""
#: Precedence.
pre: 'ToSPrecedence'
#: Delay.
#del: 'ToSDelay'
#: Throughput.
thr: 'ToSThroughput'
#: Reliability.
rel: 'ToSReliability'
#: Explicit congestion notification (ECN).
ecn: 'ToSECN'
def __new__(cls, *args: 'Any', **kwargs: 'Any') -> 'ToSField':
self = super().__new__(cls, *args, **kwargs)
# NOTE: We cannot define ``del`` due to reserved keyword conflict.
# Thus, we directly inject the information into the annotations.
cls.__annotations__['del'] = ToSDelay
return self
[docs]
@info_final
class Flags(Data):
"""Data model for IPv4 Flags.
.. versionchanged:: 1.5.0
New required field ``reserved`` (:issue:`1326`).
"""
#: Reserved flag bit.
reserved: 'int'
#: Don't fragment.
df: 'bool'
#: More fragments.
mf: 'bool'
if TYPE_CHECKING:
def __init__(self, reserved: 'int', df: 'bool', mf: 'bool') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin
[docs]
@info_final
class IPv4(Protocol):
"""Data model for IPv4 packet.
.. versionchanged:: 1.5.0
``options`` is an immutable
:class:`~pcapkit.corekit.infoclass.OrderedMultiInfo` rather than an
:class:`~pcapkit.corekit.multidict.OrderedMultiDict` (:issue:`1484`).
"""
#: Version.
version: 'Literal[4]'
#: Internet header length.
hdr_len: 'int'
#: Type of service.
tos: 'ToSField'
#: Total length.
len: 'int'
#: Identification.
id: 'int'
#: Flags.
flags: 'Flags'
#: Fragment offset.
offset: 'int'
#: Time to live.
ttl: 'timedelta'
#: Protocol.
protocol: 'TransType'
#: Header checksum.
checksum: 'bytes'
#: Source address.
src: 'IPv4Address'
#: Destination address.
dst: 'IPv4Address'
if TYPE_CHECKING:
#: Options, present only when the header carries any.
options: 'OrderedMultiInfo[OptionNumber, Option]'
#: Octets after the End of Option List, present along with ``options``.
padding: 'bytes'
#: Octets captured past the Total Length, present only when there are any.
trailer: 'bytes'
def __init__(self, version: 'Literal[4]', hdr_len: 'int', tos: 'ToSField', len: 'int', id: 'int', flags: 'Flags', offset: 'int', ttl: 'timedelta', protocol: 'TransType', checksum: 'bytes', src: 'IPv4Address', dst: 'IPv4Address') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin
[docs]
@info_final
class OptionType(Data):
"""Data model for IPv4 option type data."""
#: Change flag.
change: 'bool'
#: Option class.
#class: 'int'
#: Number.
number: 'int'
def __new__(cls, *args: 'Any', **kwargs: 'Any') -> 'OptionType':
self = super().__new__(cls, *args, **kwargs)
# NOTE: We cannot define ``class`` due to reserved keyword conflict.
# Thus, we directly inject the information into the annotations.
cls.__annotations__['class'] = OptionClass
return self
[docs]
class Option(Data):
"""Data model for IPv4 options."""
#: Option code.
code: 'OptionNumber'
#: Option length.
length: 'int'
#: Option type.
type: 'OptionType'
[docs]
@info_final
class UnassignedOption(Option):
"""Data model for IPv4 unassigned option."""
#: Option data.
data: 'bytes'
if TYPE_CHECKING:
def __init__(self, code: 'OptionNumber', length: 'int', type: 'OptionType', data: 'bytes') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin
[docs]
@info_final
class EOOLOption(Option):
"""Data model for IPv4 End of Option List (``EOOL``) option."""
if TYPE_CHECKING:
def __init__(self, code: 'OptionNumber', length: 'int', type: 'OptionType') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin
[docs]
@info_final
class NOPOption(Option):
"""Data model for IPv4 No Operation (``NOP``) option."""
if TYPE_CHECKING:
def __init__(self, code: 'OptionNumber', length: 'int', type: 'OptionType') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin
[docs]
@info_final
class SECOption(Option):
"""Data model for IPv4 Security (``SEC``) option.
.. versionchanged:: 1.5.0
New required field ``termination`` (:issue:`1393`).
"""
#: Classification level.
level: 'ClassificationLevel'
#: Protection authority flags.
flags: 'tuple[ProtectionAuthority, ...]'
#: Field termination indicator of each protection authority octet, as on
#: the wire.
termination: 'tuple[bool, ...]'
if TYPE_CHECKING:
def __init__(self, code: 'OptionNumber', length: 'int', type: 'OptionType', level: 'ClassificationLevel', flags: 'tuple[ProtectionAuthority, ...]', termination: 'tuple[bool, ...]') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin
[docs]
@info_final
class LSROption(Option):
"""Data model for IPv4 Loose Source Route (``LSR``) option.
.. versionchanged:: 1.5.0
New required field ``remaining`` (:issue:`1319`).
"""
#: Pointer.
pointer: 'int'
#: Route, i.e. the address slots before the pointer.
route: 'tuple[IPv4Address, ...]'
#: Address slots at or beyond the pointer.
remaining: 'tuple[IPv4Address, ...]'
if TYPE_CHECKING:
def __init__(self, code: 'OptionNumber', length: 'int', type: 'OptionType', pointer: 'int', route: 'tuple[IPv4Address, ...]', remaining: 'tuple[IPv4Address, ...]') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin
[docs]
@info_final
class TSOption(Option):
"""Data model for IPv4 Time Stamp (``TS``) option.
.. versionchanged:: 1.5.0
New required fields ``remaining`` and ``remainder`` (:issue:`1349`,
:issue:`1392`), and a ``timestamp`` that carries addresses is an
immutable :class:`~pcapkit.corekit.infoclass.OrderedMultiInfo` rather
than an :class:`~pcapkit.corekit.multidict.OrderedMultiDict`
(:issue:`1484`).
"""
#: Pointer.
pointer: 'int'
#: Overflow.
overflow: 'int'
#: Flag.
flag: 'TSFlag'
#: Timestamp data, i.e. the slots before the pointer.
timestamp: 'tuple[timedelta | int, ...] | OrderedMultiInfo[IPv4Address, timedelta | int]'
#: Slots at or beyond the pointer, as raw 32-bit words.
remaining: 'tuple[int, ...]'
#: Trailing octets that do not make up a whole 32-bit slot.
remainder: 'bytes'
if TYPE_CHECKING:
def __init__(self, code: 'OptionNumber', length: 'int', type: 'OptionType', pointer: 'int', overflow: 'int', flag: 'TSFlag', timestamp: 'tuple[timedelta | int, ...] | OrderedMultiDict[IPv4Address, timedelta | int]', remaining: 'tuple[int, ...]', remainder: 'bytes') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin
[docs]
@info_final
class ESECOption(Option):
"""Data model for IPv4 Extended Security (``ESEC``) option."""
#: Additional security information format code.
format: 'int'
#: Additional security information.
info: 'bytes'
if TYPE_CHECKING:
def __init__(self, code: 'OptionNumber', length: 'int', type: 'OptionType', format: 'int', info: 'bytes') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin
[docs]
@info_final
class RROption(Option):
"""Data model for IPv4 Record Route (``RR``) option.
.. versionchanged:: 1.5.0
New required field ``remaining`` (:issue:`1319`).
"""
#: Pointer.
pointer: 'int'
#: Route, i.e. the address slots before the pointer.
route: 'Optional[tuple[IPv4Address, ...]]'
#: Address slots at or beyond the pointer.
remaining: 'tuple[IPv4Address, ...]'
if TYPE_CHECKING:
def __init__(self, code: 'OptionNumber', length: 'int', type: 'OptionType', pointer: 'int', route: 'Optional[tuple[IPv4Address, ...]]', remaining: 'tuple[IPv4Address, ...]') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin
[docs]
@info_final
class SIDOption(Option):
"""Data model for IPv4 Stream ID (``SID``) option."""
#: Stream ID.
sid: 'int'
if TYPE_CHECKING:
def __init__(self, code: 'OptionNumber', length: 'int', type: 'OptionType', sid: 'int') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin
[docs]
@info_final
class SSROption(Option):
"""Data model for IPv4 Strict Source Route (``SSR``) option.
.. versionchanged:: 1.5.0
New required field ``remaining`` (:issue:`1319`).
"""
#: Pointer.
pointer: 'int'
#: Route, i.e. the address slots before the pointer.
route: 'Optional[tuple[IPv4Address, ...]]'
#: Address slots at or beyond the pointer.
remaining: 'tuple[IPv4Address, ...]'
if TYPE_CHECKING:
def __init__(self, code: 'OptionNumber', length: 'int', type: 'OptionType', pointer: 'int', route: 'Optional[tuple[IPv4Address, ...]]', remaining: 'tuple[IPv4Address, ...]') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin
[docs]
@info_final
class MTUPOption(Option):
"""Data model for IPv4 MTU Probe (``MTUP``) option."""
#: MTU.
mtu: 'int'
if TYPE_CHECKING:
def __init__(self, code: 'OptionNumber', length: 'int', type: 'OptionType', mtu: 'int') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin
[docs]
@info_final
class MTUROption(Option):
"""Data model for IPv4 MTU Reply (``MTUR``) option."""
#: MTU.
mtu: 'int'
if TYPE_CHECKING:
def __init__(self, code: 'OptionNumber', length: 'int', type: 'OptionType', mtu: 'int') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin
[docs]
@info_final
class TROption(Option):
"""Data model for IPv4 Traceroute (``TR``) option.
Important:
Due to the reserved keyword conflict, please use
:meth:`~pcapkit.corekit.infoclass.Info.from_dict`
to create an instance of this data model.
"""
#: ID number.
id: 'int'
#: Outbound hop count.
outbound: 'int'
#: Return hop count.
#return: 'int'
#: Originator IP address.
originator: 'IPv4Address'
def __new__(cls, *args: 'Any', **kwargs: 'Any') -> 'TROption':
self = super().__new__(cls, *args, **kwargs)
# NOTE: We cannot define ``return`` due to reserved keyword conflict.
# Thus, we directly inject the information into the annotations.
cls.__annotations__['return'] = int
return self
[docs]
@info_final
class RTRALTOption(Option):
"""Data model for IPv4 Router Alert (``RTRALT``) option."""
#: Router alert.
alert: 'RouterAlert'
if TYPE_CHECKING:
def __init__(self, code: 'OptionNumber', length: 'int', type: 'OptionType', alert: 'RouterAlert') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin
[docs]
class QSOption(Option):
"""Data model for IPv4 Quick Start (``QS``) option."""
#: QS function.
func: 'QSFunction'
#: Rate request/report.
rate: 'int'
[docs]
@info_final
class QuickStartRequestOption(QSOption):
"""Data model for IPv4 Quick Start request option.
.. versionchanged:: 1.5.0
New required field ``reserved`` (:issue:`1326`).
"""
#: TTL.
ttl: 'timedelta'
#: Nonce.
nonce: 'int'
#: Reserved bits after the nonce.
reserved: 'int'
if TYPE_CHECKING:
def __init__(self, code: 'OptionNumber', length: 'int', type: 'OptionType', func: 'QSFunction', rate: 'int', ttl: 'timedelta', nonce: 'int', reserved: 'int') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin
[docs]
@info_final
class QuickStartReportOption(QSOption):
"""Data model for IPv4 Quick Start report of approved rate option.
.. versionchanged:: 1.5.0
New required fields ``unused`` and ``reserved`` (:issue:`1326`).
"""
#: Not-used octet, where a request carries its TTL.
unused: 'int'
#: Nonce.
nonce: 'int'
#: Reserved bits after the nonce.
reserved: 'int'
if TYPE_CHECKING:
def __init__(self, code: 'OptionNumber', length: 'int', type: 'OptionType', func: 'QSFunction', rate: 'int', unused: 'int', nonce: 'int', reserved: 'int') -> 'None': ... # pylint: disable=unused-argument,super-init-not-called,multiple-statements,line-too-long,redefined-builtin