Source code for pcapkit.protocols.internet.mh
# -*- coding: utf-8 -*-
# pylint: disable=fixme
"""mobility header
:mod:`pcapkit.protocols.internet.mh` contains
:class:`~pcapkit.protocols.internet.mh.MH` only,
which implements extractor for Mobility Header
(MH) [*]_, whose structure is described as below:
======= ========= ================== ===============================
Octets Bits Name Description
======= ========= ================== ===============================
0 0 ``mh.next`` Next Header
1 8 ``mh.length`` Header Length
2 16 ``mh.type`` Mobility Header Type
3 24 Reserved
4 32 ``mh.chksum`` Checksum
6 48 ``mh.data`` Message Data
======= ========= ================== ===============================
.. [*] https://en.wikipedia.org/wiki/Mobile_IP#Changes_in_IPv6_for_Mobile_IPv6
"""
# TODO: Implements extractor for message data of all MH types.
from pcapkit.const.mh.packet import Packet as _MOBILITY_TYPE
from pcapkit.const.reg.transtype import TransType
from pcapkit.protocols.internet.internet import Internet
from pcapkit.utilities.exceptions import UnsupportedCall
__all__ = ['MH']
[docs]class MH(Internet):
"""This class implements Mobility Header."""
##########################################################################
# Properties.
##########################################################################
@property
def name(self):
"""Name of current protocol.
:rtype: Literal['Mobility Header']
"""
return 'Mobility Header'
@property
def length(self):
"""Header length of current protocol.
:rtype: int
"""
return self._info.length # pylint: disable=E1101
@property
def payload(self):
"""Payload of current instance.
Raises:
UnsupportedCall: if the protocol is used as an IPv6 extension header
:rtype: pcapkit.protocols.protocol.Protocol
"""
if self.extension: # pylint: disable=E1101
raise UnsupportedCall(f"'{self.__class__.__name__}' object has no attribute 'payload'")
return self._next
@property
def protocol(self):
"""Name of next layer protocol.
:rtype: pcapkit.const.reg.transtype.TransType
"""
return self._info.next # pylint: disable=E1101
##########################################################################
# Methods.
##########################################################################
[docs] def read(self, length=None, *, extension=False, **kwargs): # pylint: disable=arguments-differ,unused-argument
"""Read Mobility Header.
Structure of MH header [:rfc:`6275`]::
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Payload Proto | Header Len | MH Type | Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| |
. .
. Message Data .
. .
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Args:
length (Optional[int]): Length of packet data.
Keyword Args:
extension (bool): If the packet is used as an IPv6 extension header.
**kwargs: Arbitrary keyword arguments.
Returns:
DataType_MH: Parsed packet data.
"""
if length is None:
length = len(self)
_next = self._read_protos(1)
_hlen = self._read_unpack(1)
_type = self._read_unpack(1)
_temp = self._read_fileng(1)
_csum = self._read_fileng(2)
_data = self._read_fileng((_hlen+1)*8)
mh = dict(
next=_next,
length=(_hlen + 1) * 8,
type=_MOBILITY_TYPE.get(_type),
chksum=_csum,
data=_data,
)
length -= mh['length']
mh['packet'] = self._read_packet(header=mh['length'], payload=length)
if extension:
self._protos = None
return mh
return self._decode_next_layer(mh, _next, length)
[docs] def make(self, **kwargs):
"""Make (construct) packet data.
Keyword Args:
**kwargs: Arbitrary keyword arguments.
Returns:
bytes: Constructed packet data.
"""
raise NotImplementedError
##########################################################################
# Data models.
##########################################################################
[docs] def __post_init__(self, file, length=None, *, extension=False, **kwargs): # pylint: disable=arguments-differ
"""Post initialisation hook.
Args:
file (io.BytesIO): Source packet stream.
length (Optional[int]): Length of packet data.
Keyword Args:
extension (bool): If the protocol is used as an IPv6 extension header.
**kwargs: Arbitrary keyword arguments.
See Also:
For construction argument, please refer to :meth:`make`.
"""
#: bool: If the protocol is used as an IPv6 extension header.
self._extf = extension
# call super __post_init__
super().__post_init__(file, length, extension=extension, **kwargs)
[docs] def __length_hint__(self):
"""Return an estimated length for the object.
:rtype: Literal[6]
"""
return 6
[docs] @classmethod
def __index__(cls): # pylint: disable=invalid-index-returned
"""Numeral registry index of the protocol.
Returns:
pcapkit.const.reg.transtype.TransType: Numeral registry index of the
protocol in `IANA`_.
.. _IANA: https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
"""
return TransType(135)