Source code for pcapkit.protocols.link.link
# -*- coding: utf-8 -*-
# pylint: disable=bad-whitespace
"""root link layer 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.link.arp.ARP`/InARP,
:class:`~pcapkit.protocols.link.link.ethernet.Ethernet`, :class:`~pcapkit.protocols.link.link.l2tp.L2TP`,
:class:`~pcapkit.protocols.link.link.ospf.OSPF`, :class:`~pcapkit.protocols.link.link.rarp.RARP`/DRARP and etc.
"""
import collections
import importlib
from pcapkit.const.reg.ethertype import EtherType as ETHERTYPE
from pcapkit.const.reg.linktype import LinkType as LINKTYPE
from pcapkit.protocols.protocol import Protocol
__all__ = ['Link', 'LINKTYPE']
[docs]class Link(Protocol): # pylint: disable=abstract-method
"""Abstract base class for link layer protocol family."""
##########################################################################
# Defaults.
##########################################################################
#: Layer of protocol.
__layer__ = 'Link'
#: DefaultDict[int, Tuple[str, str]]: Protocol index mapping for decoding next layer,
#: c.f. :meth:`self._decode_next_layer <pcapkit.protocols.protocol.Protocol._decode_next_layer>`
#: & :meth:`self._import_next_layer <pcapkit.protocols.link.link.Link._import_next_layer>`.
__proto__ = collections.defaultdict(lambda: ('pcapkit.protocols.raw', 'Raw'), {
0x0806: ('pcapkit.protocols.link.arp', 'ARP'),
0x8035: ('pcapkit.protocols.link.rarp', 'RARP'),
0x8100: ('pcapkit.protocols.link.vlan', 'VLAN'),
0x0800: ('pcapkit.protocols.internet.ipv4', 'IPv4'),
0x86DD: ('pcapkit.protocols.internet.ipv6', 'IPv6'),
0x8137: ('pcapkit.protocols.internet.ipx', 'IPX'),
})
##########################################################################
# Properties.
##########################################################################
# protocol layer
@property
def layer(self):
"""Protocol layer.
:rtype: Literal['Link']
"""
return self.__layer__
##########################################################################
# Utilities.
##########################################################################
[docs] def _read_protos(self, size):
"""Read next layer protocol type.
Arguments:
size (int): buffer size
Returns:
pcapkit.const.reg.ethertype.EtherType: next layer's protocol enumeration
"""
_byte = self._read_unpack(size)
_prot = ETHERTYPE.get(_byte)
return _prot
[docs] def _import_next_layer(self, proto, length=None):
"""Import next layer extractor.
This method currently supports following protocols as registered in
:data:`~pcapkit.const.reg.ethertype.EtherType`:
.. list-table::
:header-rows: 1
* - ``proto``
- Protocol
* - 0x0806
- :class:`~pcapkit.protocols.link.arp.ARP`
* - 0x8035
- :class:`~pcapkit.protocols.link.rarp.RARP`
* - 0x8100
- :class:`~pcapkit.protocols.link.vlan.VLAN`
* - 0x0800
- :class:`~pcapkit.protocols.internet.ipv4.IPv4`
* - 0x86DD
- :class:`~pcapkit.protocols.internet.ipv6.IPv6`
* - 0x8137
- :class:`~pcapkit.protocols.internet.ipx.IPX`
Arguments:
proto (int): next layer protocol index
length (int): valid (*non-padding*) length
Returns:
pcapkit.protocols.protocol.Protocol: instance of next layer
"""
if length == 0:
from pcapkit.protocols.null import NoPayload as protocol # pylint: disable=import-outside-toplevel
elif self._sigterm:
from pcapkit.protocols.raw import Raw as protocol # pylint: disable=import-outside-toplevel
else:
module, name = self.__proto__[proto]
protocol = getattr(importlib.import_module(module), name)
next_ = protocol(self._file, length, error=self._onerror,
layer=self._exlayer, protocol=self._exproto)
return next_