BSD Loopback Encapsulation

pcapkit.protocols.link.loopback contains Loopback only, which implements extractor for the BSD loopback encapsulation [*] of LINKTYPE_NULL and LINKTYPE_LOOP, whose structure is described as below:

Octets

Bits

Name

Description

0

0

loopback.family

Address Family (Internet Layer)

The address family is in the byte order of the capturing host for LINKTYPE_NULL, which no capture format records, so it is inferred from the octets; for LINKTYPE_LOOP it is always in network byte order. Either way it is kept as loopback.byteorder.

class pcapkit.protocols.link.loopback.Loopback(file=None, length=None, **kwargs)[source]

Bases: Link[Loopback, Loopback]

This class implements BSD Loopback Encapsulation.

The header is one 4-octet address family, in the byte order of the host that captured the packet for LINKTYPE_NULL and in network byte order for LINKTYPE_LOOP. Which link type a frame was captured under is the 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 family_byteorder()). Either way it is kept in info, and 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 differs between the BSDs, so each of its values is read as IPv6. This class supports parsing of the following protocols, which are registered in the self.__proto__ attribute:

Any other family is kept as Raw.

property name: Literal['BSD Loopback Encapsulation']

Name of current protocol.

property length: Literal[4]

Header length of current protocol.

property protocol: int

Address family of next layer protocol.

read(length=None, *, alias=None, byteorder=None, **kwargs)[source]

Read BSD Loopback Encapsulation.

Structure of the BSD loopback header:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        Address Family                         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Parameters:
  • length (int | None) – Length of packet data.

  • alias (int | None) – Link type the frame was dispatched under, as Frame and PCAPNG pass it; LINKTYPE_LOOP reads the family in network byte order, and anything else as LINKTYPE_NULL.

  • byteorder (Literal['big', 'little'] | None) – Byte order to read the family in, ahead of alias. make() is handed the one info holds by from_data, and it reaches here too, so a rebuild reads the family as it was parsed rather than inferring it again.

  • **kwargs (Any) – Arbitrary keyword arguments.

Return type:

Loopback

Returns:

Parsed packet data.

Raises:

ProtocolError – If byteorder is neither 'big' nor 'little'.

make(family=2, byteorder='little', payload=b'', **kwargs)[source]

Make (construct) packet data.

Parameters:
  • family (int) – Address family, e.g. 2 for IPv4.

  • byteorder (Literal['big', 'little']) – Byte order to write the address family in, by default this host’s, as a capture of its own loopback interface does.

  • payload (bytes | ProtocolBase | Schema) – Payload data.

  • **kwargs (Any) – Arbitrary keyword arguments.

Return type:

Loopback

Returns:

Constructed packet data.

Raises:

ProtocolError – If byteorder is neither 'big' nor 'little', or family does not fit in 4 octets.

classmethod _make_data(data)[source]

Create key-value pairs from data for protocol construction.

Parameters:

data (Loopback) – protocol data

Return type:

dict[str, Any]

Returns:

Key-value pairs for protocol construction.

classmethod __index__()[source]

Numeral registry index of the protocol.

Return type:

LinkType

Returns:

Numeral registry index of the protocol in tcpdump link-layer header types. LINKTYPE_LOOP (108) is dispatched here as well.

__proto__: DefaultDict[int, ModuleDescriptor[ProtocolBase] | Type[ProtocolBase]]

Protocol index mapping for decoding next layer, c.f. self._decode_next_layer & self._import_next_layer. Keyed by address family rather than by EtherType, so this class keeps a registry of its own instead of sharing Link.__proto__.

Type:

DefaultDict[int, ModuleDescriptor[ProtocolBase] | Type[ProtocolBase]]

pcapkit.protocols.link.loopback.family_byteorder(family, linktype=None)[source]

Byte order a loopback header’s address family was written in.

Parameters:
  • family (bytes) – The 4 octets of the address family.

  • linktype (int | None) – Link type the frame was captured under; None reads as LINKTYPE_NULL.

Return type:

Literal['big', 'little']

Returns:

'big' for LINKTYPE_LOOP (108), whose family is in network byte order. Otherwise, for LINKTYPE_NULL (0), 'big' if the octets read as a smaller number big-endian than little-endian, else 'little'.

Note

A LINKTYPE_NULL family is in the byte order of the host that captured the packet, which the capture file does not record. Every address family is below 0x10000, so its zero octets lie at the high end, and the smaller of the two readings is the one in the writer’s byte order. A family that reads the same both ways, such as 0, packs to the same octets either way. A LINKTYPE_LOOP family is never inferred, so one written little-endian reads as a family no table holds.

Header Schemas

class pcapkit.protocols.schema.link.loopback.Loopback(*args: _VT, **kwargs: _VT)[source]

Bases: Schema

Header schema for BSD loopback encapsulation.

The address family is kept as its 4 octets, since their byte order depends on the link type the frame was captured under; see family_byteorder().

family: bytes = <BytesField family>

Address family.

payload: bytes = <PayloadField payload>

Payload.

Data Models

class pcapkit.protocols.data.link.loopback.Loopback(*args: VT, **kwargs: VT)[source]

Bases: Protocol

Data model for BSD loopback encapsulation.

family: int

Address family (internet layer).

byteorder: Literal['big', 'little']

Byte order the address family was written in.

Footnotes